Sunday, April 28, 2013

Never ever though I could have such fate with Login module.

My intention is develop a login module for an web application, this is very important as in an Enterprise Application architecture design, authentication and authorization should never miss. Since the Feb 2013 I start on this, along the development journey, I have explore into 4 different types of technologies, start from Spring Security -> LDAP -> Apache Directory Studio -> JAAS.

Spring security doesn't have much problem. I come into my attention on LDAP when I start configuring Spring security for LDAP. LDAP configuration is real deep advance piece. Base on my experience on learning it, never do it using plain text editor. There are tons jargon I never know when configuring LDAP. Without the help from tools to speed up the configuration, this is a very difficult task for me. Thus Apache Directory Studio playing the primary role on this configuration. I wasn't lucky so, I was downloaded the wrong tool, Apache Directory, without Studio append at the end. There is difference, the studio one allow me to create new configuration whereas the other one doesn't, and only allow me to amend on the existing configuration.

Hey! I just realize that there isn't any web login module using LDAP authentication. May be I should put back myself, where majority of the web authentication are talk to database. Here come to JAAS. Unfortunately there isn't much resource and blog talk about this, I got no choice but try and error to see whether I can find some light on this JAAS thing. As of today, I was totally helpless on the JAAS configuration part. This piece is very dependent on the server configuration. No rush, I start from Tomcat.

Due to the JAAS configuration on Tomcat, I meet realm. This is the mystery piece embedded inside the heart of Tomcat. It is a configurable plugin module that could allow me to have variety type of authentication which is done in JAVA. UserDatabaseRealm is one of it. I haven't finish studying the realm thing.

While I'm still haven't finish with Realm. I meet the fifth technology on authentication module called Apache Shiro. I was quite inspire and attracted by its capability. I will come back on this after I have finish with JAAS.

Sunday, April 14, 2013

Learning JAAS is real frustrating.

It has been a long time for me to figure out how could I develop a login module for an application? I have already spent so much time digging JAAS in Google until I got this one tutorial, a very nice and easy to hands on tutorial, which I think could give some hints for those who is serious about JAAS. Learning is a step by step process, without going too far, start from Helloworld and then gradually move on to Hollywood. I have come across the problem on learning JAAS. I have collect 4 frustrate point on this JAAS thing during my learning.

Frustrate point 1: What is the value should I pass in LoginContext's first param?
The very first step in JAAS is to create a LoginContext, and this context will always required a name among the overloaded constructors to be pass in. Interestingly the documentation didn't state clearly that this parameter is actually the entry name from the login configuration file. Still confuse where is the name? The contents of login configuration file will have something like this:

< entry name >
< LoginModule > < flag > < LoginModuleOption >

The entry name is the value I should pass into the first parameter of LoginContext.

Frustrate point 2: What is the LoginModule in login configuration file as seen above?
I know the configuration can have multiple entries, each of the entry must have an entry name. Underneath this tag will be the LoginModule. Is this simply a name or what?

The documentation didn't clearly mention that this is actually the class that you and me and every programmer must provide in order to complete the login module. This custom LoginModule is simply a class which extend the LoginModule's implementation. Meaning this is my responsibility to complete the class. The flag is require field, skipping this field will have configuration error at runtime. There has been a discussion raise in StackOverflow on LoginModule flag. LoginModuleOption is additional flag that is require for the login module to process but not necessary.

Frustrate point 3: What if I execute my program without login configuration file?
No. This will cause configuration error at runtime. Look at how LoginContext constructor is document, there is no way for me to skip the name parameter. I must always pass in at least one valid entry name into LoginContext constructor.

Frustrate point 4: I have the configuration file, but why there are still configuration error?
The configuration is not load by default, and it is not even load automatically when the program run. Three way to load the configuration file:

1. Use -Djava.security.auth.login.config command line argument. This is the most common practical way that every programmer do.
2. Configure the login configuration path in java.security under the JDK_install_apth/jre/lib. This is a sound of good programming practice.
3. Use System.setProperty("java.security.auth.login.config", "jaas.config") right inside the program.

Tuesday, April 9, 2013

I know how to truncate a table, but that was in Oracle. To do this in DB2, an immediate keyword is required at the end of the statement. Here is the sample > truncate table < Table_Name > immediate

But sometimes after the table has been truncate, the table becomes un-editable. I come across this issue by applying this command > db2 reorg < Table_Name > to the server, not the SQL editor. And it just work. More information on reorg can be found here.

Monday, April 1, 2013

What!! DB connection is full?

What went wrong with this? During the UAT, the WAS console output showing me this long story line. Initially I though I have cause some trouble in the UAT but later my investigation shows that the database connection has been fully utilize.
Caused by: org.hibernate.exception.GenericJDBCException: Cannot open connection
            at org.hibernate.exception.SQLStateConverter.handledNonSpecificException(SQLStateConverter.java:140)
            at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:128)
            at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
            at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:52)
            at org.hibernate.jdbc.ConnectionManager.openConnection(ConnectionManager.java:449)
            at org.hibernate.jdbc.ConnectionManager.getConnection(ConnectionManager.java:167)
            at org.hibernate.jdbc.JDBCContext.connection(JDBCContext.java:160)
            at org.hibernate.transaction.JDBCTransaction.begin(JDBCTransaction.java:81)
            at org.hibernate.impl.SessionImpl.beginTransaction(SessionImpl.java:1473)
            at org.springframework.orm.hibernate3.HibernateTransactionManager.doBegin(HibernateTransactionManager.java:558)
            ... 89 more
    Caused by: com.ibm.db2.jcc.am.SqlException: DB2 SQL Error: SQLCODE=-1040, SQLSTATE=57030, SQLERRMC=null, DRIVER=3.58.81
            at com.ibm.db2.jcc.am.ed.a(ed.java:679)
            at com.ibm.db2.jcc.am.ed.a(ed.java:60)
            at com.ibm.db2.jcc.am.ed.a(ed.java:127)
            at com.ibm.db2.jcc.am.jb.a(jb.java:4303)
            at com.ibm.db2.jcc.t4.db.q(db.java:703)
            at com.ibm.db2.jcc.t4.db.p(db.java:576)
            at com.ibm.db2.jcc.t4.db.l(db.java:397)
            at com.ibm.db2.jcc.t4.db.d(db.java:142)
            at com.ibm.db2.jcc.t4.b.Qc(b.java:1264)
            at com.ibm.db2.jcc.t4.b.b(b.java:1184)
            at com.ibm.db2.jcc.t4.b.a(b.java:5193)
            at com.ibm.db2.jcc.t4.b.c(b.java:743)
            at com.ibm.db2.jcc.t4.b.b(b.java:686)
            at com.ibm.db2.jcc.t4.b.a(b.java:367)
            at com.ibm.db2.jcc.t4.b.<init>(b.java:307)
            at com.ibm.db2.jcc.DB2SimpleDataSource.getConnection(DB2SimpleDataSource.java:214)
            at com.ibm.db2.jcc.DB2Driver.connect(DB2Driver.java:456)
            at java.sql.DriverManager.getConnection(DriverManager.java:582)
            at java.sql.DriverManager.getConnection(DriverManager.java:154)
            at org.springframework.jdbc.datasource.DriverManagerDataSource.getConnectionFromDriverManager(DriverManagerDataSource.java:174)
            at org.springframework.jdbc.datasource.DriverManagerDataSource.getConnectionFromDriver(DriverManagerDataSource.java:165)
            at org.springframework.jdbc.datasource.AbstractDriverBasedDataSource.getConnectionFromDriver(AbstractDriverBasedDataSource.java:149)
            at org.springframework.jdbc.datasource.AbstractDriverBasedDataSource.getConnection(AbstractDriverBasedDataSource.java:119)
            at org.springframework.orm.hibernate3.LocalDataSourceConnectionProvider.getConnection(LocalDataSourceConnectionProvider.java:82)
            at org.hibernate.jdbc.ConnectionManager.openConnection(ConnectionManager.java:446)
            ... 94 more

How to determine the page is first load in JSF?

It has been a very frustrating question for me to resolve. Due to the limited knowledge I have in JSF, how could I determined when the page is first load in JSF? I was thinking to use onLoad() in the body tag but it seems not the right way of doing this. What I mean not about the right way is this solution isn't complete and I couldn't feel satisfaction on it.

I continue my research and I found @PostConstruct might be a good help? The code would be something like this:
@PostConstruct
public void init() {
   // first load?
}
What went wrong with this code? This code will call only if the bean has been constructed. Meaning this will only call once, which is during the Spring has successfully configured and never get call upon each request to the particular web page.

I nearly gave up my research until I found PreRenderView event listener where I feel this is pretty nice fit into my situation.

   

public void initialize(ComponentSystemEvent event) {

   final boolean getMethod = ((HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest()).getMethod().equals("GET");
   final boolean ajaxRequest = FacesContext.getCurrentInstance().getPartialViewContext().isAjaxRequest();
   final boolean validationFailed = FacesContext.getCurrentInstance().isValidationFailed();

   if( getMethod && !ajaxRequest && !validationFailed ) {
      // do something during page is first loaded
   }
}
One bad thing about this code is whenever there is a request sent from the page, especially AJAX event called. This function could be very irritating, thus there is a guard to prevent this to happen.

I did also try hiddenInput to cheat the server on page first load, the code will like this:

@ManagedBean("name=theBean")
@SessionScoped
public class TheActionBean {

   private String initPageLoad;

   public String getInitPageLoad() { }
}

This way is a bit cheating, not a recommended way for this purpose. I will strongly encourage to use PreRenderView event listener.

Eclipse IDE is a good help when Spring bean is missing.

Never thought Eclipse IDE has already determine there is a missing bean declaration in my Spring configuration. I have a Spring project, when I execute this project, the following error will be shown in the console output.
   cvc-id.1: There is no ID/IDREF binding for IDREF 'inputDataGeneratorDao'.

This error happened where there is an inputDataGeneratorDao bean is being reference in the property of another bean, but its Spring declaration of this bean is undeclared.

I really miss out this error before I execute this project.