vineri, 12 iunie 2009

java.util.logging and a wrapper log class

In this post, I show how can we easily implement a logger class which has three types of messages:
  • info
  • warning
  • error
This messages are saved in a file in the following format: err-"currentdate". This logger stile is inspired by classic unix/linux log style. The following class uses java.util.logging and it should be enough for most applications. The class has singleton pattern assigned to it because I need to instantiate it only once.

package ro.example;

import java.io.FileOutputStream;
import java.io.PrintStream;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.logging.*;

public class LoggerSingleton {
private static Logger logger;
private static LoggerSingleton selfInst = null;
private String msgFile = "err%s.log";

private LoggerSingleton() throws Exception {
logger = Logger.getLogger("MyApplication");

this.switchStdErr(this.msgFile);
}

private void switchStdErr(String fName) throws Exception {
Calendar cal = GregorianCalendar.getInstance();
String file = String.format(fName, cal.get(Calendar.YEAR) + "-" + cal.get(Calendar.MONTH) + "-" + cal.get(Calendar.DAY_OF_MONTH));

PrintStream err = new PrintStream(new FileOutputStream(file, true));

System.setErr(err);
}

public static LoggerSingleton getInstance() throws Exception {
if(selfInst == null)
selfInst = new LoggerSingleton();

return selfInst;
}

public void writeInfo(String msg) {
try {
logger.log(Level.INFO, msg);
}
catch(Exception ex) {
ex.printStackTrace();
}
}


public void writeWarning(String msg) {
try {
logger.log(Level.WARNING, msg);
}
catch(Exception ex) {
ex.printStackTrace();
}
}

public void writeWarning(Exception excp) {
try {
logger.log(Level.WARNING, excp.getMessage(), excp);
}
catch(Exception ex) {
ex.printStackTrace();
}
}


public void writeError(String msg) {
try {
logger.log(Level.SEVERE, msg);
}
catch(Exception ex) {
ex.printStackTrace();
}
}

public void writeError(Exception excp) {
try {
logger.log(Level.SEVERE, excp.getMessage(), excp);
}
catch(Exception ex) {
ex.printStackTrace();
}
}
}

Comment: The log method from Logger class writes all messages to System.err stream. Because of this. the first thing I do is to redirect System.err to a specified file.

In the following section I show a possible test file which uses all available methods.

package ro.example;

public class TestLoggerSingleton {
public static void main(String[] args) throws Exception {
LoggerSingleton log = LoggerSingleton.getInstance();

log.writeInfo("Just for fun");
log.writeWarning("Only a warning");
log.writeError("Only an error message");

try {
throw new Exception("Nice error.");
}
catch(Exception ex) {
log.writeWarning(ex);
log.writeError(ex);
}
}
}


The obtained file is presented below.

Jun 4, 2009 3:27:01 PM ro.example.LoggerSingleton writeInfo
INFO: Just for fun
Jun 4, 2009 3:27:01 PM ro.example.LoggerSingleton writeWarning
WARNING: Only a warning
Jun 4, 2009 3:27:01 PM ro.example.LoggerSingleton writeError
SEVERE: Only an error message
Jun 4, 2009 3:27:01 PM ro.example.LoggerSingleton writeWarning
WARNING: O eroare draguta
java.lang.Exception: Nice error.
at ro.example.TestLoggerSingleton.main(TestLoggerSingleton.java:16)
Jun 4, 2009 3:27:01 PM ro.example.LoggerSingleton writeError
SEVERE: Nice error.
java.lang.Exception: Nice error.
at ro.example.TestLoggerSingleton.main(TestLoggerSingleton.java:16)

Every day in which we use the logger class a new file is generated with yyyy-mm-dd.log name. In this way we can see how application evolved in an extremely simple manner. In a future post I'll show how can we generate an xml log file instead of a plain text file.

miercuri, 3 iunie 2009

Hibernate session in web applications

In this article, I show a method in which we can avoid using EAGER fetch type in hibernate entities. For opening a hibernate session in web application we can use a filter that is mapped for /* url pattern. This filter will open a hibernate session and make it available for the current request. In this way, every Collection attribute from an entity can be easily accessed during the request. Some common problems met when not using this method is related to session being closed when trying to access an element from a collection. The session will be put as an request attribute and we call it OPENED_CONNECTION. The following code should give an idea of how we open and use a hibernate session in this way.

public class ManageConnection implements Filter {

private FilterConfig filterConfig;

public void destroy() {}

public void init(FilterConfig fConfig) {

this.filterConfig = fConfig;

}

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {

Object obj = request.getAttribute("OPENED_CONNECTION");

Session ses = null;

if(obj != null) {

ses = (Session)obj;

try {

ses.close();

}

catch(HibernateException ex) {

ex.printStackTrace(); //just print the stack trace into log files

}

}

ses = HibernateSingleton.getInstance().openSession();

request.setAttribute("OPENED_CONNECTION", ses);

chain.doFilter(request, response);

}

}


I use a helper class called HibernateSingleton. The code for this class is presented bellow:


public class HibernateSingleton {

private static SessionFactory sessionFactory;

static

{

sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();

}

public static SessionFactory getInstance()

{

return sessionFactory;

}

public static Session getRequestSession() {

return (Session)Contexts.getRequest().getAttribute("OPENED_CONNECTION");

}

}


Basically, the class build a Hibernate session factory and provides two static methods. One of them help as to get a Hibernate session instance. The other method returns the opened_connection attribute from the request. In my case Contexts.getRequest() method is just a wrapper method which has the code: return (HttpRequest)FacesContext.getCurrentInstance().getExternalContext().getRequest();
Of course this is an example from a JSF application.
Now, everytime you need a hibernate session in your application you just use HibernateSingleton.getRequestSession() method. If you have used other methods for managing hibernate sessions you will definitely "love" this one. It also improves performance.