basic Posts

How to Log Log4J’s Message Logs Into Database

Today im going to do a simple log4j logging into mysql database, the only reason i want to log into database instead of into file is so that i could query the logs i have.

This is my java class that i use to do my testcase,

package com.edw.main;

import java.io.IOException;
import java.sql.SQLException;
import org.apache.log4j.Logger;

public class Main {

    private static Logger logger = Logger.getLogger(Main.class);

    private void doSomething() {
        logger.debug("im doing something");
        logger.error("im doing something - error -");
    }

    public static void main(String[] args) {
        Main main = new Main();
        main.doSomething();
    }
}

and my simple table, to store all my log messages

CREATE TABLE `logs` (
  `thread_id` varchar(20) NOT NULL,
  `tanggal` datetime NOT NULL,
  `kelas` varchar(50) NOT NULL,
  `level` varchar(10) NOT NULL,
  `pesan` varchar(1000) NOT NULL,
  `ID` bigint(20) NOT NULL AUTO_INCREMENT,
  PRIMARY KEY (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=latin1;

This is my log4j.properties,

# Define the root logger with appender file
log4j.rootLogger = DEBUG, DB

# Define the DB appender
log4j.appender.DB=org.apache.log4j.jdbc.JDBCAppender

# Set JDBC URL
log4j.appender.DB.URL=jdbc:mysql://localhost/test

# Set Database Driver
log4j.appender.DB.driver=com.mysql.jdbc.Driver

# Set database user name and password
log4j.appender.DB.user=root
log4j.appender.DB.password=password

# Set the SQL statement to be executed.
log4j.appender.DB.sql=INSERT INTO LOGS VALUES('%x',now(),'%C:%L','%p','%m', null)

# Define the layout for file appender
log4j.appender.DB.layout=org.apache.log4j.PatternLayout

And this is what the contents of my database

This is my Netbeans; Project structure, as you can see, i only need 2 jars, mysql driver and log4j jar.

A Simple AES Encryption – Decryption Using Java

Several days ago, my friend asked me how to create a simple AES encryption – decryption using java. Well, here is your answer, hope it will helped you.

package com.edw.testing;

import java.security.AlgorithmParameters;
import java.security.spec.KeySpec;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
import sun.misc.BASE64Encoder;

public class TestingAES {

    public TestingAES() {
    }

    private void execute() throws Exception {
        
        String password = "mypassword";
        String salt = "salt";
        String cipherText = "Hello, World!";
        
        SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
        KeySpec spec = new PBEKeySpec(password.toCharArray(), salt.getBytes(), 65536, 256);
        SecretKey tmp = factory.generateSecret(spec);
        SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES");

        // encrypt
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, secret);
        AlgorithmParameters params = cipher.getParameters();
        byte[] iv = params.getParameterSpec(IvParameterSpec.class).getIV();
        byte[] ciphertext = cipher.doFinal(cipherText.getBytes("UTF-8"));
        
        System.out.println("password : "+password);
        System.out.println("salt : "+salt);
        System.out.println("cipherText : "+cipherText);
        System.out.println("iv : "+new BASE64Encoder().encode(iv));
        System.out.println("ciphertext : "+new BASE64Encoder().encode(ciphertext));
        
        // decrypt
        Cipher cipherDecrypt = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipherDecrypt.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(iv));
        String plaintext = new String(cipherDecrypt.doFinal(ciphertext), "UTF-8");
        System.out.println("decrypted text : "+plaintext);
        
    }

    public static void main(String[] args) throws Exception {
        TestingAES testingAES = new TestingAES();
        testingAES.execute();
    }
}

And this is what is written on my netbeans console,

Oh and if you ever found this kind of error

Caused by: java.security.InvalidKeyException: Illegal key size or default parameters

it means that you need to install Java Cryptography Extension (JCE). You will find it here,

http://www.oracle.com/technetwork/java/javase/downloads/jce-6-download-429243.html

Have fun 😀

How to Add Expiry Date on Your Static Files using Java’s Servlet Filter

Perhaps there would be some people wondering, why should i use expiry date on my static files? Well for a first-time visitor to your page may have to make several HTTP requests to load all your web page’s content, but by using the Expires header you make those components cacheable. This avoids unnecessary HTTP requests on subsequent page views. Expires headers are most often used with images, but they should be used on all components including scripts, stylesheets, and Flash components.

But dont forget, using a far future Expires header affects page views only after a user has already visited your site. It has no effect on the number of HTTP requests when a user visits your site for the first time and the browser’s cache is empty. Therefore the impact of this performance improvement depends on how often users hit your pages with a primed cache.

Okay, so basically i use a simple ServletFilter to add Expiry header on each static contents, on this example would be .css, .png and .gif files. So here is my code,

package com.edw.fw.server.filter;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;

public class ExpiryFilter implements Filter {

	// add a five years expiry
	private Integer years = 5;

	@Override
	public void destroy() {
	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		if (years > -1) {
			Calendar c = Calendar.getInstance();
			c.setTime(new Date());
			c.add(Calendar.YEAR, years);

			// HTTP header date format: Thu, 01 Dec 1994 16:00:00 GMT
			String o = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss zzz")
					.format(c.getTime());
			((HttpServletResponse) response).setHeader("Expires", o);
		}

		chain.doFilter(request, response);
	}

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {		
	}
}

And dont forget to register your Filter to your web.xml file

		<!--  
			expiration date filter
		-->
	  	<filter>
			<description>Set cache expiry for static content</description>
			<filter-name>ExpiryFilter</filter-name>
			<filter-class>com.edw.fw.server.filter.ExpiryFilter</filter-class>
		</filter>
		<filter-mapping>
			<filter-name>ExpiryFilter</filter-name>
			<url-pattern>*.css</url-pattern>
			<dispatcher>REQUEST</dispatcher>
		</filter-mapping>
		<filter-mapping>
			<filter-name>ExpiryFilter</filter-name>
			<url-pattern>*.png</url-pattern>
			<dispatcher>REQUEST</dispatcher>
		</filter-mapping>
		<filter-mapping>
			<filter-name>ExpiryFilter</filter-name>
			<url-pattern>*.gif</url-pattern>
			<dispatcher>REQUEST</dispatcher>
		</filter-mapping>

This is what it looks like on my browser’s http log,

as you can see, my http request get 304 not modified header, due to accessing my browser’s cache instead of the targetted web page.

Okay, i hope this helped other. Have Fun 🙂

Weird Error when Connecting Spring’s JavaMailSender to Postfix

I had a weird error today when trying to connect to my server’s postfix mail server. It’s weird because i never had this kind of error when connecting to Google Mail server. This is the error that i see on postfix’s log.

Mar 26 01:50:19 localhost postfix/smtpd[24907]: connect from localhost[127.0.0.1]
Mar 26 01:50:19 localhost postfix/smtpd[24907]: setting up TLS connection from localhost[127.0.0.1]
Mar 26 01:50:19 localhost postfix/smtpd[24907]: SSL_accept error from localhost[127.0.0.1]: 0
Mar 26 01:50:19 localhost postfix/smtpd[24907]: warning: TLS library problem: 24907:error:14094416:SSL routines:SSL3_READ_BYTES:sslv3 alert certificate unknown:s3_pkt.c:1193:SSL alert number 46:
Mar 26 01:50:19 localhost postfix/smtpd[24907]: lost connection after STARTTLS from localhost[127.0.0.1]
Mar 26 01:50:19 localhost postfix/smtpd[24907]: disconnect from localhost[127.0.0.1]

This is my email configuration on Spring’s applicationContext.xml.

<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
	<property name="host" value="localhost"/>
	<property name="port" value="25"/>
	<property name="username" value="admin@whatever.com"></property>
	<property name="password" value="password"></property>
	<property name="javaMailProperties">
		<props>
			<prop key="mail.smtp.auth">true</prop>
			<prop key="mail.smtp.starttls.enable">true</prop>
		</props>
	</property>
</bean>

After googling for a while, i found out that somehow the error happen because of TLS problem. The workaround is actually easy, i disabled the starttls property on bean mailSender.

<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
	<property name="host" value="localhost"/>
	<property name="port" value="25"/>
	<property name="username" value="admin@whatever.com"></property>
	<property name="password" value="password"></property>
	<property name="javaMailProperties">
		<props>
			<prop key="mail.smtp.auth">true</prop>
			<prop key="mail.smtp.starttls.enable">false</prop>
		</props>
	</property>
</bean>

[Java] How to Map Properties from HashMap to Java Bean

On this example, im trying to do a simple mapping from java.util.Map to a simple Java Bean, using Apache Common BeanUtils.

First as usual, a simple java bean.

package com.edw.bean;

public class Student {
    public String name;
    public int age;

    public Student() {
    }

    // other setter and getter
}

And this is how i map simple values to Student bean.

package com.edw.main;

import com.edw.bean.Student;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.beanutils.BeanUtils;

public class Main {
    public static void main(String[] args) throws Exception {
        Student student = new Student();
        
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("name", "edwin");
        map.put("age", 22);
        
        BeanUtils.populate(student, map);
        
        System.out.println(student.getName());
        System.out.println(student.getAge());
    }
}

This is the libraries that i used,

Actually, my plan is to create a dynamic bean to bean mapping configured via xml files. And this class is my starting point. (H)