Using explicit import statements in Java source files

Posted 76 days ago

I'd always read, and have tried to follow, the general rule of thumb that generalized package level imports are bad practice, and today at work I encountered my first real life example of why.

A customer who developed a J2EE application in-house on a J2EE 1.4 application server is currently migrating to a newer version, which supports J2EE 1.5, and EJB3. Their application has a source file that is structured basically like this:

package com.customer.application.ejbs;

import java.rmi.*;
import javax.ejb.*;

public interface MyPublicInterface extends Remote {
   // bla bla bla
}

Up until now, this had always worked just fine. Then, they tried to take their application bundle and migrate it to a new version of the platform. This resulted in runtime exceptions indicating that the class Remote could not be resolved due to a naming conflict.

Here's the problem: their interface MyPublicInterface extends java.rmi.Remote. J2EE 1.5 introduced a new class, javax.ejb.Remote, which is the annotation class used to identify an EJB's remote business interface. Since they use wild-card includes to make every class in both the java.rmi and javax.ejb packages available, they now have a naming conflict that can not be resolved when resources in their EAR files are compiled during deployment.

This is an important point - that this "error" is NOT a bug in the application server. There is a mentality among testers that says "well if it works on platform A, and not platform B, then there is a bug in platform B." - and this is simply not the case.

In fact, if the customer recompiles their application against the J2EE 1.5 libraries, this will be detected at compile time, well before the application ever gets deployed to the application server!

You basically have two choices in this scenario:

  1. Fully qualify any use of the Remote interface to java.rmi.Remote; or
  2. Use explcit import statements
In other words - rather that using wildcard imports, you should specifically import each class and interface you need from each package individually. I know that seems tedious, but most Java IDEs on the market (both free and commercial) automatically manage your imports for you. Many (such as Eclipse, and those based on Eclipse) have refactoring capabilities that will clean up your imports for you.

While it may seem like a tedious and daunting task - it is clearly the better fix. By fully qualifying use of the Remote interface you will fix the problem at hand, but still leave yourself open to repeating this problem down the line, when J2EE 1.6 comes around.

So long story short... Java's tagline really should be write carefully, run anywhere.

Your First EJB3 Session Bean

Posted 410 days ago

I just recently started playing with EJB3, and found it extremely tricky to get through my very first EJB3 Session Bean. While significantly simpler than EJB 2, the online resources just aren't there. Hopefully this simple Hello, EJB3! will help get you started.

Note: Your mileage may vary based on your application server platform. I do my development work on WebSphere Application Server 6.1.0.9 with the EJB3 Feature Pack Beta installed.

Write Your Session Bean

The first thing I did was create a new, empty Java Project - not a J2EE project, not an EJB project, just a blank project space. This avoids the built in wizards in your environment from creating deployment descriptors and other such silly EJB 2 nonsense.

Next, create a new interface called HelloEJB3, like so:

package com.timfanelli.ejb3;

import javax.ejb.Stateless;

public interface HelloEJB3 {
   public String sayHello();
}

This will be the local business interface for our session bean. If you want a remote business interface, annotate the interface with @Remote.

Next, create the bean implementation class, like so:

package com.timfanelli.ejb3;

import java.ejb.Stateless;

@Stateless
public class HelloEJB3Bean implements HelloEJB3 {
   private String greeting = "Hello, EJB3!";

   public String sayHello() { return greeting; }
}

And that's it! You have yourself an EJB3 stateless session bean with a local (or remote, if you annotated) business interface!

EJB3 eliminated the need for several complicated things noone liked, such as home interfaces, deployment descriptors or complicated EJB interfaces. Pretty neat. JAR it up and you're ready to roll on to writing a test client.

Oh - it's worth noting for backward compatibility, the @Stateless annotation tells your container that this is a stateless session bean, and it will be bound to java:comp/env/ejb/HelloEJB3.

EJB3 Session Bean Client

For our client, we'll create a new servlet application. The application will have a single servlet, HelloWeb. We'll use the new EJB3 dependency injection to obtain an instance of our bean, and use its business interface to execute methods on it; like so:

package com.timfanelli.ejb3;

import java.io.IOException;

import javax.ejb.EJB;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class HelloServlet extends javax.servlet.http.HttpServlet
   implements javax.servlet.Servlet {

   @EJB
   private HelloEJB3 hellobean;
 
   protected void doGet(HttpServletRequest request, HttpServletResponse response) 
      throws ServletException, IOException 
   {
      response.getWriter().write(hellobean.sayHello());
   }  	

   protected void doPost(HttpServletRequest request, HttpServletResponse response) 
      throws ServletException, IOException 
   {
      // TODO Auto-generated method stub
   } 
}

The important parts are in bold for you. Note the line annotated with @EJB. This is all you need to do to perform the JNDI lookup for your EJB bean. The container will automatically lookup java:comp/env/ejb/HelloEJB3 from the JNDI context for you.

Then, all you need to do is use its business methods, as shown in the doGet() method of the servlet.

Don't forget to add the name of the jar file that holds your HelloEJB3 interface and HelloEJB3Bean class to your web applications MANIFEST. Otherwise, you'll hit runtime classpath errors.

Deployment Setup

Here's where the really tricky part came in for me. I had to create an EAR project to add my HelloEJB3 project to, and also my web application project. Since I'm using Rational Application Developer 7, which does not yet have tooling support for EJB3, this was a little difficult.

In my EAR, I have added the WAR file as a war module - no surprise there. I then added my java project, called HelloEJB3.jar, as a utility jar and an ejb-module. Since I'm not overly familiar with many other tools, I don't know what that means for the rest of you. In any event, here's my application.xml file:

<?xml version="1.0" encoding="UTF-8"?>
<application id="Application_ID" version="1.4"
     xmlns="http://java.sun.com/xml/ns/j2ee"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/application_1_4.xsd">
	<display-name>
	HelloEJB3EAR</display-name>
	<module>
		<web>
			<web-uri>HelloTestWeb.war</web-uri>
			<context-root>HelloTestWeb</context-root>
		</web>
	</module>
	<module><ejb>HelloEJB.jar</ejb></module>
</application>

That's all there really is to it. You should be able to deploy to your EJB3 ready application server, access your servlet, and see your hello message!

Best of luck. And remember, stateless session beans are only the tip of the iceberg. I'm also investigating the Java Persistence API to replace my EJB2 Entity Beans... will post migration stories later!

EJB Project Settings in RAD 7

Posted 412 days ago

Lately, I've been using IBM's Rational Application Developer 7 to develop J2EE applications targeting the WebSphere 6.1 platform... all in all, I have to say RAD is a phenomenal tool with excellent integration to the platform. My only real complaint after almost a year of use is it's default paths and settings when you create a project.

By default, your source folder is named "ejbModule" - this in and of itself is not an issue... but "ejbModule" is also used as the default output folder, AND is where the deploy tools output their generated code.

The result is that when you publish your application to a local test environment, you wind up with a very messy source folder.

My original "work-around" for this was to ignore the source folder completely, and just access my beans via the deployment descriptor hierarchy. This works out well most of the time, until you change the remote or local interface of a bean. Then the generated sources need to be recreated... and to recreate them, you need to delete them (why they're not deleted when you clean your project is beyond me)... since they're mingled in with your actual source files, this is a very dangerous thing to do. Several times, I've accidentally deleted source files, and got myself into irritating situations attempting to restore files out of my repositories and other backups.

But today, persistence paid off. I've finally managed to configure my projects to have a very clean structure in RAD. It's actually so simple and obvious, I can't believe it took me this long.

The key is to do two things:

  1. Create a second source folder, called "src". This is where I keep my sources. META-INF can, and should, stay in the ejbModule folder. RAD7 seems to get confused when you try to move this in an existing project.
  2. Go into your project settings and edit the Java Build Path. On the "Sources" tab at the bottom, you'll find the default output folder. Click browse, create a new folder in your project called "bin", and choose that.

Now, your structure should look something like this:

Project/
   source/
      com/
          timfanelli/
              <etc...>
   ejbModule/
      META-INF/
   bin/

When the deploy tool runs, your sources remain under source and generated code is created under the ejbModule folder. When you build your project, all the binaries go into bin. Cleanup is a snap then, when you want to delete the deploy tool's generated code, simply delete all source packages under ejbModule.

Getting Started with Struts Shale

Posted 1003 days ago

Struts Shale is a proposal for a next-generation web development framework. I've spent a couple days scouring the internet trying to find a simple getting started guide to build a new Shale application, but there just doesn't seem to be one yet. Shale's website promises that a future milestone release will include a blank template ready for customization, but in the meantime, we're left to reading JavaDoc to figure out how to get going. This tutorial will walk you through building a very simple Hello / GoodBye world application using Shale and JavaServer Faces technology from scratch.

(read more)

Best of 2003

Posted 1045 days ago

Thanks to the Web Archive, I was able to retrieve a bunch of old posts that I had lost a couple years ago when the server I hosted on at the time crashed. I restored the posts that had interesting content with their original publish dates, and thought I'd post a "Best of '03" to those stories. So here they are, in chronological order:

Tomcat Configuration Trickery

Posted 1226 days ago

Say you're working on a handful of different web application projects using one installation of Tomcat; it's very likely that you need different resources, settings, and runtime parameters per project - and as a consequence of such it's very likely that your tomcat configuration is a mess! Well no more, I say! What if you could have a distinct set of configurations for each project you're working on?

Fortunately Tomcat makes this extremely easy. There are two primary locations that Tomcat works with, identified by and . is the location you installed Tomcat into -- in my setup, that's /opt/tomcat. is where it will look for configuration files and other "dynamic portions" (according to tomcat's documentation) of the server.

What we're going to do is create one per project (or one for just the projects you think require their own, anyway), and then configure tomcat to use the new TOMCAT_BASE.

The first thing to do is create a local tomcat directory structure in your project directory -- my project looks something like this:

  MyProject/
    docs/
    etc/
    src/
      java/
      test/
    tomcat/
      conf/
      logs/
      tmp/
      webapps/
      work/
MyProject/tomcat is going to be your .

You need to copy two files from /conf to /conf:

  • web.xml - Contains the default settings for all web apps deployed into .
  • server.xml - Contains the server configuration. For my web projects, i usually use server-minimal.xml file instead of the default server.xml, as it only loads the minimum amount of services needed to run a web application (which is usually sufficient for my hobby projects).

Once you have that done, your is ready for use. If you're launching Tomcat from the command line, you'll want to set the environment variable CATALINA_BASE to point to your TOMCAT_BASE directory (MyProject/tomcat). If you're launching Tomcat from XCode, you'll want to open your custom executable's properties, and add the following argument:

  -Dcatalina.base=../tomcat
Note: XCode appends arguments in order, so you'll want to put it somewhere before the argument that specifies the Bootstrap class to launch.

All that's left to do is start deploying your project's webapp to /webapps rather than /webapps, and you're good to go. Your project's instance of Tomcat will log to MyProject/tomcat/logs, use MyProject/tomcat/work for its working directory, and MyProject/tomcat/tmp for tmp space.

Why would you want to do this, you ask? Well first and foremost, cuz it's cool. Second, perhaps you have projects that really should be tested and run in isolation. Third, maybe you don't have the luxury of having multiple machines that you can run webservers on, and you need to test a multi-server setup - or test communications between applications on separate app-servers. For me, it's a configuration-location thing - it lets you keep project-specific server configurations in your project, where they belong.

Debugging Servlets in XCode

Posted 1226 days ago

So I've been struggling for a while with finding a way to debug web applications in XCode. The answer wasn't immediately obvious. I'm sure it would have been if I happened to have Apple's WebObjects, but I don't; just XCode. Well today I figured out how to do it -- you run Tomcat directly from within XCode!

Now before we get started, I want to point out that I realize there are pros and cons to doing this -- I'm going to save those for the end.

My setup

Here's the software I have installed to work with:

  • OS X 10.4 Tiger
  • XCode 2
  • Java 1.5.0 (also "Tiger")
  • Tomcat 5.5.9 (installed in /opt/tomcat)
I'm 99% certain this procedure will work using OS X 10.3, XCode 1.5, Java 1.4.2, and Tomcat 5.0.x as well, but I haven't tried it. If you try it, and it works, please let me know -- if your mileage varies and you want me to post instructions for that as well, please email me :).

Step 1: Creating a new project

If you already have a project you want to try this with - just skip to step 2.

If you don't already have an XCode project, now's the time to make it. I used the "Java: Ant Based Application Jar" project template in XCode. This creates a new project with an ant build script, and src and lib directories. Making yourself a nifty servlet that looks something like this:

import java.io.*;

import javax.servlet.http.*;
import javax.servlet.*;

public class javaplay extends HttpServlet {
  public void doGet ( HttpServletRequest req, 
                      HttpServletResponse res )
    throws ServletException, IOException
  {
    PrintWriter out = res.getWriter();
	
    out.println("Hello, world!");
    out.close();
  }
}

is a great beginning. You'll also want to make yourself a WEB-INF/web.xml file, like so:

<web-app>
  <servlet>
    <servlet-name>hello</servlet-name>
    <servlet-class>javaplay</servlet-class>
  </servlet>

  <servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/hello</url-pattern>
  </servlet-mapping>
</web-app>

And then modify your build script a little bit a make the WAR. Mine is embarrasing, so I'm not going to show it to you. There's two steps though:

  1. Make a new target that creates a WAR and depends on "compile"
  2. Change the default target of your build script to call your new target.

Ok great, one last final step, grab your servlet-api and jsp-api jars and copy them into your projects "lib" directory. The build script needs these in lib to resolve against at compile time. Now go ahead and build your project to make sure it goes smoothly and generates the WAR as expected.

Had a problem, did you? That's okay... I'll wait till your done.

( ... jeopardy theme ... )

Step 2: Tying in Tomcat

This part's also very easy -- you're going to create a new executable target that starts Tomcat. My setup has Tomcat 5.5.9 installed into /opt/tomcat.

Right-click (ctrl-click) "Executables" under Groups & Files and select "New Custom Executable". Name it something meaningful, such as "Tomcat", and set the executable path to: /usr/bin/java. When you press "Finish" you'll get the "Executable Tomcat Info" dialog up. Go to the Arguments tab, and add the following set of arguments, in order:

  -classpath /opt/tomcat/bin/bootstrap.jar:/opt/tomcat/bin/commons-logging-api.jar
  -Dcatalina.home=/opt/tomcat
  -Xmx128m
  -Xms64m
  -Xincgc
  -Djava.awt.headless=true
  org.apache.catalina.startup.Bootstrap -debug start

Set your new target to be the active target, and run your project. You'll notice that your console output is Jakarta Tomcat starting up! Not too shabby, eh?

Step 3: There is no step 3

That's it. Just deploy your webapp to tomcat, start it up under XCode, and you're good to go. Give it a try, set a break point in your servlet code and hit the page through a web browser.

Conclusion

One thing I did to make my life easier in this setup is to make my default ant target automatically deploy the WAR file to my tomcat directory. That way when I hit "Build & Debug", it builds, deploys, and launches tomcat in my debugger.

Well I hope you found this helpful. I know I keep having to go back to using IntelliJ IDEA for my servlet based projects up until now I haven't been able to figure this out. I'm still looking into getting the XCode debugger to hook up to a remote Tomcat session, and I'll be posting info about that soon (I hope). If anyone out there has info on doing that, please get in touch with me.

Anonymous Abstract Factory pattern revisited

Posted 1428 days ago

A while ago I had posted an article about the Anonymous Abstract Factory Pattern - an adaptation of the Abstract Factory Pattern that takes advantage of anonymous class loading in Java. Well I've finally got around to pulling the framework for that pattern out of the jETIA source tree, so I CPL'd it and am making it available here: AnonymousAbstractFactory-1.0.0.tar.bz2.

Please let me know if you're interested in working on the project. I'd love to get a couple developers working on it, adding features such as support for factory constructors, configurable factories, and a few other features. If I get a couple people who are interested, I'll set up an SVN repository for the project and we'll start making plans. Sorry for the minimal documentation, I'll work on that as well.

Abstract Anonymous Factory Pattern

Posted 1626 days ago

A factory is an object that creates instances or related types of objects. An abstract factory provides the interface that factory objects implement, as well as a method return a concrete factory implementation. For example, jETIA contains an Abstract DAO Factory that defines abstract methods to get different types of data access objects, and a static method to obtain a concrete instance of a DAO Factory.

In the abstract factory pattern as described in "Design Patterns", the Abstract Factory's static method to obtain a concrete factory instance would take a parameter identifying the type of concrete factory to return, and instantiate the appropriate sub-class of itself to satisfy the request. This hard coded knowledge of the available types of concrete factories makes it difficult to supply new types of factories later.

The Abstract Anonymous Factory is an adaptation of the abstract factory pattern that takes advantage of the anonymous class loading abilities of the Java runtime environment. Instead of explicitly telling the Abstract Factory about each type of Factory, the Abstract Anonymous Factory reads information about the types of concrete factories from a configuration file. The anonymous abstract factory then asks the runtime environment to find the class by name, and instantiate it.

Using this method, to add support for a new type of factory, the developer must implement the objects that are created by the concrete factory, create a new concrete subclass of the abstract anonymous factory, and modify a configuration file that is read dynamically at runtime. There is no need to recompile any of the code to deploy a new factory.

To help illustrate this concept, consider the sequence diagram shown the figure below. It depicts the sequence of events that occur when an application needs to use a Widget. In order to support a wide variety of widgets, an abstract anonymous widget factory is used. As you can see, the client obtains a concrete widget factory from the abstract anonymous widget factory. The configuration file is read to determine what types of widget factories are available, and in this instance, since no particular type is specified, the name of the default widget factory to use.

This is why the factory is referred to as "anonymous." Neither the client application nor the abstract factory has any advanced knowledge of the type of factory to instantiate. Since the concrete widget factory implements a known interface, it can be instantiated as a generic Object instance, and then cast to the appropriate interface type.

Setting the User Timeout in JBoss

Posted 1751 days ago

When most people think of the session timeout in an EJB application, they're typically thinking about the HttpSession timeout of their web front ends. If, however, you need to set the authenticated user timeout in JBoss, it's as easy as adding a parameter to your configuration files...

Edit /server//conf/jboss-service.xml, and look for the following section:

<!-- JAAS security manager and realm mapping -->
<mbean 
  code="org.jboss.security.plugins.JaasSecurityManagerService" 
  name="jboss.security:service=JaasSecurityManager">
     <attribute 
       name="SecurityManagerClassName">
          org.jboss.security.plugins.JaasSecurityManager
     </attribute>
</mbean>

To set the default timeout value, simply add an attribute between inside the tag:

<attribute name="DefaultCacheTimeout">VALUE_IN_SECONDS</attribute>

Each time a client accesses an EJB, the timeout value is checked. If it has been at least as long as the value specified since the last time the client accessed an EJB, then the JAAS manager calls the logout() method of the LoginContext. This will subsequently cause a security exception to be thrown, since the user is no longer authorized to make requests to the EJB.

Securing EJB Applications with Custom JBoss Login Modules

Posted 1753 days ago

JBoss comes out-of-the-box with a handful of great login modules, but lets face it, you need a custom one to integrate with your existing security infrastructure. This overview shows you how to secure your EJB application with a custom server login module, and also to use a custom client login module to authenticate your EJB client applications.

JBoss makes use of the Java Authentication and Authorization Service API to authenticate and authorize users in your EJB applications. If you are not already familiar with creating JAAS login modules, I would recommend that you read my entry on Creating JAAS Login Modules to get an understanding of how they work.

This overview will show you how to secure your EJB Applications in JBoss using JAAS, and how to authenticate your client applications to the JBoss server. I will assume that since you are at the level of creating custom login modules, that you already know how to set up your XML Descriptor file for role based authorization, and have already done so. If you haven't, you should... otherwise, it makes it difficult to test your login module! We won't go over the steps of creating an EJB, but for this example we'll assume that we have a stateless session bean called HelloBean. The HelloBean's remote interface defines one method, hello(), that returns the String "Hello" to the client. HelloBean's XML Descriptor is set up such that the caller must be in the role "ExampleRole".

So here's the scenario, you have an existing security infrastructure that provides username and password based authentication. You want to perform client side authentication, and have the server lookup what roles the user is in from some database or other part of the existing security infrastructure. My entry on Creating JAAS Login Modules will show you how to set up the client side login module that performs client side authentication. Everything in that entry holds true for this tutorial, with only a couple additional steps needed for JBoss. The first thing that is required is that in addition to your own custom login module, you also use JBoss's ClientLoginModule. To do this, your security domain configuration file should look like this:

exampleDomain {
     net.eskeeter.jaasexample.CustomLoginModule required;
     org.jboss.security.ClientLoginModule required;
};

JBoss's ClientLoginModule will get the username and password from the callback handler you initialized the login context with. If you look carefully at the implementation of the CustomCallbackHandler (in the jaas login module entry), you'll see that it only interacts with the user the first time it is called. Since each login module in the context shares the same instance of the callback handler, the user is not prompted for their credentials twice. There are other (and probably "better") ways to accomplish this using the shared state map, but this way is effective as well.

So now that your client is authenticated, you need to get the principal and credentials to the server. Note that if you do not need to perform further password authentication on the server side, there is no reason to pass the actual password to the server, although for JBoss, you do need to pass something to the server. In the implementation I wrote for jETIA, I pass the hard-coded string "IDontNeedThePassword" to the server as the credentials. So how do you get this information to the server? It's easy. JBoss's ClientLoginModule takes the username and password and puts them in the org.jboss.security.SecurityAssociation class. You get the information to the server by initializing your JNDI Naming Context with them as follows:

HashTable props = new HashTable();
props.put( Context.SECURITY_PRINCIPAL, 
           SecurityAssociation.getPrincipal() );
props.put( Context.SECURITY_CREDENTIALS, 
           SecurityAssociation.getCredential() ); 

InitialContext initialContext = new InitialContext( props );

From then on, when you use that naming context to lookup EJB Home and Remote references, that information can be obtained by the server in the caller's context. Using a Service Locator pattern (Core J2EE Patterns, Prentice Hall, Alur, Crupi and Malks) simplifies this, since you only have one initial context in the whole application.

So that's all there is to the client side additions. By requiring JBoss's ClientLoginModule and initializing the JNDI naming context with the principal and credentials, you have fulfilled all your client side obligations for using custom JBoss login modules. Implementing the server side login module is no more difficult than it was to do the client side.

To write the server side login module, all you need to do is implement the JAAS module, set up your EJB Application in a security domain, and tell JBoss to use your module for that domain. Recall that our client's CustomLoginModule subclasses the JAAS javax.security.auth.login.LoginModule class. The server side login module should subclass org.jboss.security.auth.spi.AbstractLoginModule, which is a subclass of javax.security.auth.login.LoginModule. The reason we subclass JBoss's class instead of directly extending the JAAS class is because JBoss expects to find the user and role principals arranged in a specific manner. Using the AbstractLoginModule ensures that these are set up properly for JBoss. Our CustomServerLoginModule looks like this:

package net.eskeeter.jbossjaasexample;

import java.security.acl.Group;
import javax.security.auth.login.LoginException
import org.jboss.security.auth.api.AbstractLoginModule;

public class CustomServerLoginModule 
  extends AbstractServerLoginModule
{
    private Principal identity;
	
    public Principal getIdentity() {
        return identity;
    }
	
    public Group[] getRoleSets() {
        ...
    }
	
    public boolean login() throws LoginException {
        ...
    }
} 

The getIdentity() and getRoleSets() methods are abstract in the AbstractServerLoginModule, and must be implemented by our server login module. The login() method has a default implementation, but you'll typically want to override this do anything you need to do on the server side. This login method is the very same as the one in the JAAS login module, and thus follows the same rules: return true if successful, false if this module should be ignored, or throw a LoginException if an error occurs.

public boolean login() throws LoginException
{
    identity = 
      org.jboss.security.SecurityAssociation.getPrincipal();
	
    if ( identity == null )
    { 
        throw new LoginException( 
            "The principal was not found in " +
            "the SecurityAssociation." );
    }
	
    loginOk = true;
    return true;
}

Our simple sets the identity principal, and returns true. The boolean loginOk is a protected member of the AbstractServerLoginModule class, and is checked by the commit() method to determine if the login() method succeeded. The getIdentity() method simply returns the principal that should be used as the identity of the subject on the server. The getRoleSets method returns an array of Groups of Principals, our sample implementation is as follows:

public Group[] getRoleSets() 
{
    // Your implementation should lookup what roles
    // the user, identified by the identity principal, is in 
    // from a database, or some group management 
    // system you have in place.
	
    Group rolesGroup = new SimpleGroup( "Roles" );
    rolesGroup.addMember( 
        new SimplePrincipal( "ExampleRole" ) );
	
    return new Group[]{ rolesGroup };
}

JBoss expects to find the user's roles in a group called "Roles". If you have a need for them, you can add other groups as well. Our simple implementation is not very dynamic, it always returns the Roles group with a single role principal, "ExampleRole".

That's all there is to writing the custom login module for the server. All that's left to do now is tell the JBoss what security domain your EJB Application should run in, and to use your server login module for that domain. Setting your EJB Application's security domain is as easy as adding a tag to your jboss.xml descriptor file:

<jboss>
<security-domain>ExampleDomain</security-domain>
</jboss>

Note that this security domain does not have anything to do with the security domain you set up on the client. When you build your EJB jar file, put the jboss.xml file along side your ejb-jar.xml file in the jar files META-INF directory. JBoss will process this file with the ejb-jar.xml descriptor file, appending any information found in it to the information found in the ejb-jar.xml file. To tell JBoss to use your login module, you need to edit the /server/

Writing Custom JAAS Login Modules

Posted 1753 days ago

This tutorial will show you in detail the steps required to implement a custom JAAS login module for a Java application.

When a client application needs to authenticate the user, the only thing it needs to do is obtain a LoginContext, and execute its login() method, as follows:

package net.eskeeter.jaasexample;

import javax.security.auth.login.LoginException;
import javax.security.auth.login.LoginContext;
import javax.security.auth.callback.CallbackHandler;

public class JAASExample
{
    public static void main( String[] args )
    {
        String securityDomain = "exampleDomain";
	CallbackHandler callbackHandler = 
		new CustomCallbackHandler();

	try
	{
	    LoginContext lc = 
	    new LoginContext( securityDomain, 
			      callbackHandler );
	    lc.login();
	}
	catch ( LoginException e )
	{
	    System.exit( -1 );
	}
    }
}

The two relevant lines of code are in the try block. First, the application creates a LoginContext, then calls the login() method. Although this sounds simple enough, there is quite a bit going on here, so lets start from the top:

First, the securityDomain string. The security domain is used to determine what login modules should be used by the LoginContext instance. On the client, you will need to create a security domain configuration file that defines this security domain; I called mine auth.conf (the name is not importatant) and it simply contains the following:

exampleDomain {
     net.eskeeter.jaasexample.CustomLoginModule required;
};

The contents of the file are simple. The exampleDomain label identifies a security domain, and the modules it needs are enclosed in the curly braces. In this example, there is only one module, MyCustomLoginModule, and it is required. We will see the implementation of the MyCustomLoginModule class shortly.

Second is the instantiation of a CallbackHandler. The callback handler is used by the login modules to prompt the user for their username and password. This allows you to write Login Modules independent of how the client application interacts with the user, wether it be console based, Swing, network communications, or even a database lookup. We will come back to callback handlers later. For now, it is enough that you understand that the handler will get the username and password from the user, and then give that information back to the LoginModule.

The next thing we do is instantiate the LoginContext with these two pieces of information. When the LoginContext is created, it looks at your security domain configuration file and creates an instance of each login module specified. Before we can understand how the LoginContext interacts with each Login Module, perhaps we should take a look at what goes into the login module itself. Here is the MyCustomLoginModule implementation, details have been taken out for brevity, but we will come back to them in a bit:

public class CustomLoginModule 
  implements javax.security.auth.spi.LoginModule
{
    private Subject subject;
    private CallbackHandler handler;
    private Map sharedState;
    private Map options;

    private String username = null;

    // Saves the state of phase 1, login().
    private boolean loginOk = false;  

    private SimplePrincipal usernameprincipal;
    private Object password;

    public void initialize( Subject subject, 
			    CallbackHandler callbackHandler, 
			    Map sharedState, 
			    Map options)
    {
	this.subject = subject;
	this.handler = callbackHandler;
	this.sharedState = sharedState;
	this.options = options;
    }

    public boolean login() throws LoginException
    {
        ...
    }

    public boolean commit() throws LoginException
    {
        ...
    }

    public boolean abort() throws LoginException
    {
        ...
    }

    public boolean logout() throws LoginException
    {
        ...
    }
}

Each of these methods are defined in the LoginModule interface, so they must all be overridden. When the LoginContext creates an instance of the login module, it uses the default no-parameter constructor, and then calls the initialize() method. The only purpose that initialize() serves is to store away the parameters for the other methods to use later. The implementation shown here is exactly how you should expect to see it in any subclass of LoginModule. The Subject that is passed in represents the "thing" being authenticated (i.e., the user). The CallbackHandler is a reference to the handler you passed in to the LoginContext. The sharedState map lets you pass parameters between login modules, such as the username and password, so that the user does not need to be prompted for them with each module. The options map allows you to configure options at runtime; we do not use it in our sample implementation.

The next thing that happens in our JAASExample class is that we call the LoginContext's login() method. As you might have figured out by now, this will in turn call the login() method on each of the LoginModule instances it created. The login method looks like this:

public boolean login() throws LoginException
{
    NameCallback namecallback = 
	new NameCallback( "Enter username" );
    PasswordCallback passwordcallback = 
	new PasswordCallback( "Enter password", false );

    try
    {
        handler.handle( new Callback[]{ namecallback, 
					passwordcallback } );

	username = namecallback.getName();
	password = new String( passwordcallback.getPassword() );

	System.out.println( "TODO\t" + 
		            this.getClass().getName() + 
			    ": Call Authentication Code." );

	loginOk = true;
	return true;
    }
    catch ( UnsupportedCallbackException e )
    {
    }
    catch ( java.io.IOException e )
    {
    }
    finally
    {
    }

    return false;
}

The execution of the login method completes phase 1 of authentication. The login method creates a NameCallback and PasswordCallback and passes them to the CallbackHandler; we will look at this in more depth a little later. The only other thing that login does is to save the state of the callbacks by storing the username and password in its private instance variables. The SimplePrincipal class is defined as follows:

public class SimplePrincipal implements Principal
{
    private String name;
    private boolean destroyed = false;

    public SimplePrincipal( String name )
    {
	this.name = name;
    }

    public String getName()
    {
	return name;
    }
}

The implementation in the download is a little more complicated than this one because of some JBoss requirements. For more information on that, see my entry on creating custom JBoss login modules with JAAS. Note that nothing has been added to the Subject yet, this is done in commit().

public boolean commit() throws LoginException
{
    if ( ! loginOk )
	return false;

    usernameprincipal = new SimplePrincipal( username );
    password = new String( "idontusethis" );

    subject.getPrincipals().add( usernameprincipal );
    subject.getPublicCredentials().add( password );

    this.username = null;
    return true;
}

Commit stores the state saved in login in the subject being authenticated. Note that in the implementation I did for jETIA (http://www.jetia.com), I pass a phony password to the server. Since I do my authentication to the corporate user database on the client side, there is no reason to pass the actual password to the server. For JBoss though, it is important that you pass SOMETHING in the subject's credientials (we'll talk more about JBoss after we understand JAAS in general.).

The abort method should simply destroy all internal state saved in the LoginModule. The logout method should remove any principals or credentials from the subject that were added by that LoginModule.

The ONLY thing left to understand of the client side of things is the CallbackHandler. The CallbackHandler interface only defined one method, handle, that takes an array of Callback objects. For a description of the different types of callback objects, see the javax.security.auth.callback package in the J2SE API. Our CallbackHandle, CustomCallbackHandler, looks like this:

package net.eskeeter.jaasexample;

import javax.security.auth.callback.Callback;
import javax.security.auth.callback.UnsupportedCallbackException;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
import java.io.IOException;

public class CustomCallbackHandler 
  implements javax.security.auth.callback.CallbackHandler
{
    private String username = null;
    private char[] password = null;

    public void handle(Callback[] callbacks) 
	throws IOException, UnsupportedCallbackException
    {
        prompt();

        for ( int i = 0; i < callbacks.length; i++ )
	{
	    Callback callback = callbacks[i];

	    if ( callback instanceof NameCallback )
	    {
	        NameCallback ncb = (NameCallback) callback;
		ncb.setName( username );
	    }
	    else if ( callback instanceof PasswordCallback )
	    {
	        PasswordCallback pcb = (PasswordCallback) callback;
                pcb.setPassword( password );
	    }
	    else
	    {
	        System.out.println( 
			"Unsupported callback: " + 
			callback.getClass().getName() );
	        throw new UnsupportedCallbackException( callback );
	    }
	}
    }

    /**
     * Prompts the user for username and password with the 
     * AuthenticationDialog dialog. This method may only be
     * called once per instance.
     */
    private void prompt()
    {
	AuthenticationDialog dlg = 
            new AuthenticationDialog( null );
	dlg.show();

	username = dlg.getUserName();
        password = dlg.getPassword();
    }
}

The only thing to do now is compile everything together, and run it. The one detail we did not cover above, is telling the LoginContext where exactly to find you security domain configuration file. Fortunately, this is as easy as passing a parameter to the JVM when you run it. To start this application, type the following:

java -Djava.security.auth.login.config=/auth.conf 
    net.eskeeter.JAASExample
Passing J2SE Collections in EJB Remote Methods

Posted 1764 days ago

The J2SE Collection interfaces and abstract classes do not implement the Serializable interface, making it difficult to pass Collections around using EJB Remote Interfaces.

The trick to this one is to be explicit about the type of Collection you want to use. I discovered this problem while implementing the Value List Hander pattern from Sun's J2EE Patterns Catalog. If you're unfamiliar with the pattern, it allows you to iterate over a list of remote entities in an efficient manner, by utilizing the Transfer Object pattern, also from the J2EE Patterns Catalog.

I wrote an Enterprise Java Bean to act as a facade to my VLH objects in the business tier, and found that it was throwing a NotSerializableException when I attempted to return a sublist of a java.util.List reference. The List variable referenced an instance of an ArrayList object, which does implement Serializable, but since I was referencing it as a java.util.List, which does not implement Serializable, the resulting sublist was not Serializable either.

I simply changed the VLH classes to contain a reference to an ArrayList internally instead of a List. This seems to have fixed that problem, hope it helps you with yours!

Serializing Static Instances over EJB Calls

Posted 1764 days ago

I've recently run across a problem serializing "enumeration" classes over RMI method calls... here's how I resolved it.

First note that "enumeration" is in quotes for a reason, I'm not talking about the java.util.Enumeration interface. Lets say that I wanted to represent user-states in an enum, I've come to use the following pattern to accomplish this in Java in place of C/C++'s enum type:

public class UserState
{
    public final static ONLINE = new UserState( "ONLINE" );
    public final static OFFLINE = new UserState( OFFLINE );
    public final static IDLE = new UserState( "IDLE" );
    public final static AWAY = new UserState( "AWAY" );
 
    private String name;

    private UserState( String name ) {
        this.name = name;
    }
}

This provides me with four final static instances of a UserState in the system. I can compare them using the == operators, because UserState references will point to one of these four.

In the J2EE world, this works great within each tier; however as soon as you try to pass an object like this into another tier using a remote EJB method call, problems arise. When you pass an object over an EJB method call, the object is serialized on the caller's side, and deserialized on the receiver's side. When that object is deserialized, however, it has the same logical values, but is itself a NEW INSTANCE of the UserState class. This will fail any comparison made using the == operator to one of the original four static instances.

To get around this, what you need to do on the receiving side is check the logical value of the object passed in, and set that reference to be one of the original four static instances. To help facilitate this, I've added toString() and getInstance( String str ) methods to my enumeration class pattern:

public class UserState
{
    ...

    public String toString() { return name; }

    public UserState getInstance( String str )
    {
        if ( str.equals( "ONLINE" ) ) return ONLINE;
        if ( str.equals( "OFFLINE" ) ) return OFFLINE;
        if ( str.equals( "AWAY" ) ) return AWAY;
        if ( str.equals( "IDLE" ) ) return IDLE;

        return null;
    }
}

So say I had a method in an EJB's Remote interface that looked like this:

public UserState getUsersState( String username ) throws RemoteException;

On the client side, what I would need to do is this:

UserState state = ejbremotereference.getUsersState( "timfanelli" );
state = UserState.getInstance( state.toString() );

This will get the user's state from the EJB instance, and then the second line reassigns the UserState reference to point to the appropriate static instance on the client. The same type of trick would be used in the Business Tier if I were to ever pass a UserState object into the EJB.

About

My name is Tim Fanelli, I am a software engineer in Northern NY. I spend most of my time working, and when I can, I try to post interesting things here.

Cigar Dossiers