Extreme Java When vanilla Java is not enough

29Apr/080

Configuring proxy in Java applications

If you have a Java application that needs to connect to Internet, and you are behind a proxy, you have two options:

  1. Add this to the application command line parameters:
    -Dhttp.proxyHost=[host.of.proxy] -Dhttp.proxyPort=[port.of.proxy]
  2. Or edit the net.properties file in the lib folder of your java home. It is self-explanatory, since you have to edit one or two lines and there's about 70 lines of comments on that file.

The bad news is if your proxy requires authentication. This means you will have to do something like:

Authenticator.setDefault(new Authenticator() {
  @Override
  protected PasswordAuthentication getPasswordAuthentication() {
    return new PasswordAuthentication("username",
        new char[] { 49, 50, 51, 52, 53, 54 } );
  }
});

You can, of course, create a more complex Authenticator subclass, that will open a Popup asking for the proxy user and password.

23Apr/080

JAAS + Struts + Tomcat = Secure and pratical

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.

17Apr/080

DisplayTag inside a loop

In my (brand) new job, I've developed a simple report that is a list of employers along with phone calls they made. The employer list is iterated using JSTL's "c:forEach" and the call list is rendered by DisplayTag.

Very simple, except because I got a little problem: DisplayTag requires an unique id (set by the "uid" attribute) and this uid is also the iteration variable - just like the "var" attribute in "c:forEach".

This means I need to create an unique id for every outer iteration. But this also means that I create a new "current inner item" variable for each outer item. If I use a non-unique id, the navigation of all tables will be the same: if I click "next page" on the first table, the second table will also go to the next page. If I define an uid based on outer item data, I cannot access it using a direct approach (like "c:out"), because the EL must change for every iteration.

This limitation was solved by predefining the uid (before the DisplayTag table):

<c:forEach items="${myList}" var="${myItem}">
  <%-- This creates an unique id based on item's id --%>
  <c:set var="tableId" value="list-${myItem.id}"/>
 
  <display:table uid="${tableId}" name="${myItem.mySubList}">
    <display:column property="mySimpleValue"/>
    <display:column>
      <%-- Now, a little EL magick --%>
      <my:tag value="${pageScope[tableId].myValue}"/>
    </display:column>
  </display:table>
</c:forEach>

Notice that this approach isn't needed if you want to show simple values, like a String. Using this to pass the value to a is a waste. But it is the only way to work if you need to apply any transformation - like formatting a Date.

14Apr/080

java.lang.OutOfMemoryError: Java heap space

Another easy one that I always forget the recipe. If a Java-based application throws a OutOfMemoryError, you can solve the problem by giving it more memory. Just pass one of these command-line arguments to java.exe:

  • -Xms256m - Java VM will start with a heap of 256mb.
  • -Xmx512m - Java VM will have a maximum heap of 512mb.
  • -XX:PermSize=128m - The permgen space will start with 128mb. This is needed when application instantiates a lot of small objects. It can be explained as the "FAT" (or "EXT3") of the objects.
  • -XX:MaxPermSize=256m - The permgen space will have a maximum of 256mb.
3Apr/080

One more reason to love NetBeans

I'm trying NetBeans 6.1 Beta. It is pretty stable to a beta, but I got a little problem: the "Find Usages" resource has some kind of memory leak. I sent the log using NetBeans' built-in feature and voilá: it was sent successfully, and, like a charm, the server told me the issue was already sent by another user and is FIXED - yup, they are quick.

For the folks that laugh at Windows "send error" button, just take a look at the screenshot:

Upload of NetBeans Error Log

And, if you want to, you can see the report number 13304, and the issue #125531.

1Apr/081

How-(not-)to use Hibernate

Digging into some legacy code, I found the worst way to initialize Hibernate. The first step should be something like:

Configuration cfg = new Configuration();
cfg.addClass(Bean1.class)
   .addClass(Bean2.class)
   .addClass(Bean3.class);

But I found this:

Configuration cfg = new Configuration();
Object[] objs = new Object[] {
    new Bean1(), new Bean2(), new Bean3()
};
for (int i = 0; i < objs.length; i++)
    cfg.addClass(objs[i].getClass());
}

You only need to know the basics of Java to find out the waste of memory and CPU, instantiating a lot of classes (and an array) only to get the class instantiated. And, of course, the unnecessary loop to iterate over the array. It's like baking a cake to find out the brand of the flour.

As if it's not enough, this piece of code is replicated in about 7 spots. Yes, the right way to configure Hibernate is using the "HibernateUtils" pattern, as in documentation.

And, as if it's not enough yet, this piece of code creates a SessionFactory that is sent via constructor to an entire hierarchy of classes. Yes, it is the worst solution, since the Session creation could be on HibernateUtils (as in documentation, again).