Archive for the ‘Java EE’ Category

Password and confirmation with JSF

Tuesday, March 17th, 2009

If you need to validate a field in JSF and the value is dependent of another field (like password/confirmation), BalusC posted a nice tutorial about it. You need to create a JSF Validator and add a <f:attribute/> to your field. Easier than I thought…

Spring injection outside application context

Tuesday, March 17th, 2009

Are you using ApplicationContext (and friends) to create a single “spring context” for all your web application? If so, you are on the right way. And it is possible that you feel the need to inject properties where Spring isn’t accessible (like a Servlet Filter). You can use this little trick:

public static void inject(ServletContext context,
    Object bean) {
  WebApplicationContext wCtx =
      WebApplicationContextUtils
          .getWebApplicationContext(context);
  if (wCtx != null) {
    wCtx.getAutowireCapableBeanFactory()
        .autowireBeanProperties(bean,
            AutowireCapableBeanFactory.AUTOWIRE_NO,
            false);
  }
}

Hibernate JPA and Enums

Tuesday, March 17th, 2009

Assume you have a simple enum:

public enum Status {
  ACCEPTED, REJECTED, NOTREADDEN
}

And your legacy database stores it as ordinal values (ACCEPTED = 0, REJECTED = 1, NOTREADDEN = 2). For reasons lost in time, DBA created the column as “varchar”. If you want to use JPA, you will have a bad time using Hibernate:

java.lang.IllegalArgumentException: No enum const class mypkg.Status.1
  java.lang.Enum.valueOf(Enum.java:196)
  org.hibernate.type.EnumType.nullSafeGet(EnumType.java:110)

After digging into EnumType.java, I noticed it is hardcoded “if-varchar-then-name-else-ordinal”. I assume they never dealed with ancient, legacy databases.

If I switch to TopLink, it works as expected… One thumb down to Hibernate…

JAAS and Filters

Tuesday, March 17th, 2009

Small tip of the day. If you define a servlet filter and container managed security on the same application, keep these in mind:

  • If your filter is “url-mapped”, it is executed BEFORE the security manager;
  • If it is “servlet-mapped”, it is executed AFTER the security manager.

I tested it when developing a filter to handle “user life cycle” (expired passwords, agreement signing, etc). If I map both filter and security to “/*”, filter was run. If I map security to “/*” and filter to “Faces Servlet”, it is not executed until authenticated (even when accessing “/faces/index.jsp”).

Tomcat manager with SSO and a different Realm

Monday, March 16th, 2009

Tomcat Manager’s default configuration isn’t pratical (nor secure): you must store your users and passwords in a plain XML file. Of course, you can change the “<Realm>” definition on “<Engine name=’Catalina’>”, but it has no effect if you need a host with Single Sign On.

Since Manager needs to share the same host with managed applications, you need to create a context.xml for your Manager:

<?xml version="1.0" encoding="UTF-8"?>
<Context path="/manager" privileged="true">
  <Realm className="my.secure.and.custom.Realm"/>
</Context>

Put it on “conf/<engine>/<host>/manager.xml”. The “privileged=’true’” will prevent a “java.lang.SecurityException: Servlet of class org.apache.catalina.manager.HTMLManagerServlet is privileged and cannot be loaded by this web application”.

You must change “webapps/manager/WEB-INF/web.xml” and replace “<role-name>manager</role-name>” with the name of the role you want.

MQSeries not closing connections

Thursday, August 21st, 2008

I got this error while connecting to MQSeries:

MQJE001: An MQException occurred: Completion Code 2, Reason 2009
MQJE016: MQ queue manager closed channel immediately during connect
Closure reason = 2009

After some trial-and-error, I found the problem: MQ’s InitialContext opens a connection, but only closes it if I close the IC itself:

ic.close();

Since my application creates a lot of instances of InitialContext, a lot of connections got leaked, giving that annoying error.

+1 to the IBM’s hall-of-shame, section “useless error messages”.

Changing HSQLDB in-process database default password

Wednesday, June 18th, 2008

HSQLDB is not the kind of database I can use in enterprise systems (with terabytes of data), but it is specially useful if I need a simple RDBMS to small (or temporary) databases.
While trying it with Glassfish, I got a big problem: if you create an in-process database (using “jdbc:hsqldb:mem” or “jdbc:hsqldb:file” or “jdbc:hsqldb:res”), HSQLDB creates a default user named “SA” with an empty password. But Glassfish does not accept data sources without passwords (I get a “No PasswordCredential found”).
To solve this, I grab the HSQLDB sources and changed the org.hsqldb.Database class. The “reopen” method has the following command:

if (isNew) {
  sessionManager.getSysSession().sqlExecuteDirectNoPreChecks(
    "CREATE USER SA PASSWORD \"\" ADMIN");
  logger.synchLogForce()
}

I just changed it to:

if (isNew) {
  sessionManager.getSysSession().sqlExecuteDirectNoPreChecks(
    "CREATE USER " + urlProperties.getProperty("user") +
    " PASSWORD \"" + urlProperties.getProperty("password") +
    "\" ADMIN");
  logger.synchLogForce();
}

Compiling with “ant jar” (in build dir), the new hsqldb.jar will now allow you to create the user based on the credentials passed as login. But this will only work if you compile with a JDK 5, because a lot of methods required by JDBC in JDK 6 are implemented by throwing UnsupportedOperationException.

For some reason, Glassfish and HSQLDB with in-process only works with OpenJPA. I’ve tryed with Hibernate and TopLink, with really strange results. If I find a solution, I’ll post later.

Java SCBCD 5.0 Certification

Friday, June 13th, 2008

I am strudying for the SCBCD certification, and I realized there is almost no free material about it. I found this website and, IMHO it is an incredible source of information.
They also have some materials for other certifications (SCJP, SCWCD, etc), too, but I did not read them yet.

JBossAS + JBossWS + JDK 6 = problems

Monday, June 9th, 2008

Years ago, a lot of applications did not support JDK 5, even with the incredible range of new features. Today, the history repeats itself with JDK 6. A lot of applications do not support it. For my surprise, I added a big one to the list: JBoss.

How did I found it? By publishing a webservice using JBossWS (included in JBossAS). Deployment works, but when I consume the WS, I got this exception:

java.lang.UnsupportedOperationException: setProperty must be overridden by
all subclasses of SOAPMessage

After researching it on Google, I found this bug report. They tell JBoss is not supported on JDK 6, but, since I follow the “upgrade-or-bust” philosofy, I decided to put it to work.

It was pretty simple (on JBoss 4.2.2GA): grab a copy of “jboss-saaj.jar” from “server/default/lib” and copy it to “JBOSS_HOME/lib/endorsed”. Works like a charm!

JAAS + Struts + Tomcat = Secure and pratical

Wednesday, April 23rd, 2008

Still working on the application I describe in my previous post, I started to integrate it to use JAAS. It is a Struts-based system running in a Tomcat server. The login was an Struts Action, and a RequestProcessor took care of redirecting to login page.

It was pretty easy the conversion to JAAS:

  1. I developed a new Realm for Tomcat. It was just a matter of extend the RealmBase class and override the authenticate method. This step could be skipped if my employer’s LDAP server accepted anonymous search - JNDIRealm can do this job;
  2. With the Realm ready, add it to the application’s context.xml (NetBeans users will find it inside META-INF folder of the project);
  3. Next step was to make a “public access” version of the application. Every code that does the authentication and authorization was removed, except the dynamic menu;
  4. The dynamic menu was changed to use the request.isUserInRole method. For some reason, this property can’t be accessed by EL. I expected something like “request.userInRole[’role’]”, but it didn’t work;
  5. The logged user can be retrieved with either request.getUserPrincipal() or the EL “pageContext.request.userPrincipal”;
  6. Now, it is just a matter of adding every Struts action to security constraints in web.xml. In NetBeans, it’s an easy-to-use visual editor. Here is a snippet:
    <security-constraint>
      <web-resource-collection>
        <web-resource-name>SecurePages</web-resource-name>
        <description>My secret pages</description>
        <url-pattern>/secure.do</url-pattern>
        <http-method>GET</http-method>
      </web-resource-collection>
    
      <auth-constraint>
        <description>Allowed roles</description>
        <role-name>power_user</role-name>
      </auth-constraint>
    </security-constraint>
  7. The login page, if using FORM-based authentication, is now something like:
    <form action="j_security_check" method="post">
      User: <input type="text" name="j_username"/>
      Password: <input type="password" name="j_password"/>
      <input type="submit" name="btLogin" value="login"/>
    </form>
  8. To activate the FORM-based login, this must be added to web.xml:
    <login-config>
      <auth-method>FORM</auth-method>
      <form-login-config>
        <form-login-page>/login.jsp</form-login-page>
        <form-error-page>/login.jsp</form-error-page>
      </form-login-config>
    </login-config>
  9. Did you notice the login error page is the same as the login page? To check if the user entered an invalid password, I use:
    <c:if test="${param.btLogin == 'login' and param.j_username <> ''}">
      <c:out value="Invalid username and/or password"/>
    </c:if>

It is a long boilerplate, but steps are the same for every application. Using JAAS instead of programatic authorization makes your system more secure and easier to maintain.