Sunday, May 9, 2010

Java, Know the Subclasses of a class.

While I was working on one of my project I came across with a need to know all the subclasses of particular class in a classpath.

How does one go about and try to find all subclasses of a given class (or all implementors of a given interface) in Java? As of now, I have a method to do this. The method is:

1.Get a list of all class names that exist on the class path
2.Load each class and test to see if it is a subclass or implementor of the desired class or interface

In Eclipse, there is a nice feature called the Type Hierarchy that manages to show this quite efficiently. How does one go about and do it programmatically?

I know Scanning for classes is not easy with pure Java, And the Spring framework offers a class called ClassPathScanningCandidateComponentProvider that can do what you need.

But here is a way of achieving it with in stand alone applications.

May not be an efficient way of coding, used Vectors in some places, which is not required, we can safely replace them with ArrayList, Sesrializing might not be the appropriate solution, but logic works well.. here the class which I implemented named with SubClassFinder.java.

import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.net.JarURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.TreeMap;
import java.util.Vector;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

/**
 * Will scan and list all the subclasses of a given class or Interface,
 * Its even search for classes in a jar file too.. 
 * <li>Get a list of all class names that exist on the class path</li>
 *  <li>
 * Load each class and test to see if</li>
 * While scanning all the classes it serializes the results, 
 * 
 * 
 * @author rajendra
 */
public class SubClassFinder {
 private Class<?> classToSearch = null;
 private Map<URL, String> classpathLocations = new HashMap<URL, String>();
 private Map<Class<?>, URL> results = new HashMap<Class<?>, URL>();
 private List<Throwable> errors = new ArrayList<Throwable>();

 public SubClassFinder() {
  refreshLocations();
 }

 /**
  * Rescan the classpath, cacheing all possible file locations.
  */
 public final void refreshLocations() {
  synchronized (classpathLocations) {
   classpathLocations = getClasspathLocations();
  }
 }

 /**
  * @param fqcn
  *            Name of superclass/interface on which to search
  */
 public final Vector<Class<?>> findSubclasses(String fqcn) {
  synchronized (classpathLocations) {
   synchronized (results) {
    try {
     classToSearch = null;
     errors = new ArrayList<Throwable>();
     results = new TreeMap<Class<?>, URL>(CLASS_COMPARATOR);
     // filter malformed FQCN
     if (fqcn.startsWith(".") || fqcn.endsWith(".")) {
      return new Vector<Class<?>>();
     }

     // Determine search class from fqcn
     try {
      classToSearch = Class.forName(fqcn);
     } catch (ClassNotFoundException ex) {
      errors.add(ex);
      return new Vector<Class<?>>();
     }

     return findSubclasses(classToSearch, classpathLocations);
    } finally {
    }
   }
  }
 }

 public final List<Throwable> getErrors() {
  return new ArrayList<Throwable>(errors);
 }

 /**
  * The result of the last search is cached in this object, along with the
  * URL that corresponds to each class returned. This method may be called to
  * query the cache for the location at which the given class was found.
  * <code>null</code> will be returned if the given class was not found
  * during the last search, or if the result cache has been cleared.
  */
 public final URL getLocationOf(Class<?> cls) {
  if (results != null)
   return results.get(cls);
  else
   return null;
 }

 /**
  * Determine every URL location defined by the current classpath, and it's
  * associated package name.
  */
 public final Map<URL, String> getClasspathLocations() {
  Map<URL, String> map = new TreeMap<URL, String>(URL_COMPARATOR);
  File file = null;

  String pathSep = System.getProperty("path.separator");
  String classpath = System.getProperty("java.class.path");
  // System.out.println ("classpath=" + classpath);

  StringTokenizer st = new StringTokenizer(classpath, pathSep);
  while (st.hasMoreTokens()) {
   String path = st.nextToken();
   file = new File(path);
   include(null, file, map);
  }
  return map;
 }

 private final static FileFilter DIRECTORIES_ONLY = new FileFilter() {
  public boolean accept(File f) {
   if (f.exists() && f.isDirectory())
    return true;
   else
    return false;
  }
 };

 private final static Comparator<URL> URL_COMPARATOR = new Comparator<URL>() {
  public int compare(URL u1, URL u2) {
   return String.valueOf(u1).compareTo(String.valueOf(u2));
  }
 };

 private final static Comparator<Class<?>> CLASS_COMPARATOR = new Comparator<Class<?>>() {
  public int compare(Class<?> c1, Class<?> c2) {
   return String.valueOf(c1).compareTo(String.valueOf(c2));
  }
 };

 private final void include(String name, File file, Map<URL, String> map) {
  if (!file.exists())
   return;
  if (!file.isDirectory()) {
   // could be a JAR file
   includeJar(file, map);
   return;
  }

  if (name == null)
   name = "";
  else
   name += ".";

  // add subpackages
  File[] dirs = file.listFiles(DIRECTORIES_ONLY);
  for (int i = 0; i < dirs.length; i++) {
   try {
    // add the present package
    map.put(new URL("file://" + dirs[i].getCanonicalPath()), name
      + dirs[i].getName());
   } catch (IOException ioe) {
    return;
   }

   include(name + dirs[i].getName(), dirs[i], map);
  }
 }

 private void includeJar(File file, Map<URL, String> map) {
  if (file.isDirectory())
   return;

  URL jarURL = null;
  JarFile jar = null;
  try {
   jarURL = new URL("file:/" + file.getCanonicalPath());
   jarURL = new URL("jar:" + jarURL.toExternalForm() + "!/");
   JarURLConnection conn = (JarURLConnection) jarURL.openConnection();
   jar = conn.getJarFile();
  } catch (Exception e) {
   // not a JAR or disk I/O error
   // either way, just skip
   return;
  }

  if (jar == null || jarURL == null)
   return;

  // include the jar's "default" package (i.e. jar's root)
  map.put(jarURL, "");

  Enumeration<JarEntry> e = jar.entries();
  while (e.hasMoreElements()) {
   JarEntry entry = e.nextElement();

   if (entry.isDirectory()) {
    if (entry.getName().toUpperCase().equals("META-INF/"))
     continue;

    try {
     map.put(new URL(jarURL.toExternalForm() + entry.getName()),
       packageNameFor(entry));
    } catch (MalformedURLException murl) {
     // whacky entry?
     continue;
    }
   }
  }
 }

 private static String packageNameFor(JarEntry entry) {
  if (entry == null)
   return "";
  String s = entry.getName();
  if (s == null)
   return "";
  if (s.length() == 0)
   return s;
  if (s.startsWith("/"))
   s = s.substring(1, s.length());
  if (s.endsWith("/"))
   s = s.substring(0, s.length() - 1);
  return s.replace('/', '.');
 }

 private final Vector<Class<?>> findSubclasses(Class<?> superClass,
   Map<URL, String> locations) {
  Vector<Class<?>> v = new Vector<Class<?>>();

  Vector<Class<?>> w = null; // new Vector<Class<?>> ();

  Iterator<URL> it = locations.keySet().iterator();
  while (it.hasNext()) {
   URL url = it.next();
   // System.out.println (url + "-->" + locations.get (url));

   w = findSubclasses(url, locations.get(url), superClass);
   if (w != null && (w.size() > 0))
    v.addAll(w);
  }

  return v;
 }

 private final Vector<Class<?>> findSubclasses(URL location,
   String packageName, Class<?> superClass) {
  // System.out.println ("looking in package:" + packageName);
  // System.out.println ("looking for  class:" + superClass);

  synchronized (results) {

   // hash guarantees unique names...
   Map<Class<?>, URL> thisResult = new TreeMap<Class<?>, URL>(
     CLASS_COMPARATOR);
   Vector<Class<?>> v = new Vector<Class<?>>(); // ...but return a
   // vector

   // TODO: double-check for null search class
   String fqcn = classToSearch.getName();

   List<URL> knownLocations = new ArrayList<URL>();
   knownLocations.add(location);
   // TODO: add getResourceLocations() to this list

   // iterate matching package locations...
   for (int loc = 0; loc < knownLocations.size(); loc++) {
    URL url = knownLocations.get(loc);

    // Get a File object for the package
    File directory = new File(url.getFile());

    // System.out.println ("\tlooking in " + directory);

    if (directory.exists()) {
     // Get the list of the files contained in the package
     String[] files = directory.list();
     for (int i = 0; i < files.length; i++) {
      // we are only interested in .class files
      if (files[i].endsWith(".class")) {
       // removes the .class extension
       String classname = files[i].substring(0, files[i]
         .length() - 6);

       // System.out.println ("\t\tchecking file " +
       // classname);

       try {
        Class<?> c = Class.forName(packageName + "."
          + classname);
        if (superClass.isAssignableFrom(c)
          && !fqcn.equals(packageName + "."
            + classname)) {
         thisResult.put(c, url);
        }
       } catch (ClassNotFoundException cnfex) {
        errors.add(cnfex);
        // System.err.println(cnfex);
       } catch (Exception ex) {
        errors.add(ex);
        // System.err.println (ex);
       }
      }
     }
    } else {
     try {
      // It does not work with the filesystem: we must
      // be in the case of a package contained in a jar file.
      JarURLConnection conn = (JarURLConnection) url
        .openConnection();
      // String starts = conn.getEntryName();
      JarFile jarFile = conn.getJarFile();

      // System.out.println ("starts=" + starts);
      // System.out.println ("JarFile=" + jarFile);

      Enumeration<JarEntry> e = jarFile.entries();
      while (e.hasMoreElements()) {
       JarEntry entry = e.nextElement();
       String entryname = entry.getName();

       // System.out.println ("\tconsidering entry: " +
       // entryname);

       if (!entry.isDirectory()
         && entryname.endsWith(".class")) {
        String classname = entryname.substring(0,
          entryname.length() - 6);
        if (classname.startsWith("/"))
         classname = classname.substring(1);
        classname = classname.replace('/', '.');

        // System.out.println ("\t\ttesting classname: "
        // + classname);

        try {
         // TODO: verify this block
         Class<?> c = Class.forName(classname);

         if (superClass.isAssignableFrom(c)
           && !fqcn.equals(classname)) {
          thisResult.put(c, url);
         }
        } catch (ClassNotFoundException cnfex) {
         // that's strange since we're scanning
         // the same classpath the classloader's
         // using... oh, well
         errors.add(cnfex);
        } catch (NoClassDefFoundError ncdfe) {
         // dependency problem... class is
         // unusable anyway, so just ignore it
         errors.add(ncdfe);
        } catch (UnsatisfiedLinkError ule) {
         // another dependency problem... class is
         // unusable anyway, so just ignore it
         errors.add(ule);
        } catch (Exception exception) {
         // unexpected problem
         // System.err.println (ex);
         errors.add(exception);
        } catch (Error error) {
         // lots of things could go wrong
         // that we'll just ignore since
         // they're so rare...
         errors.add(error);
        }
       }
      }
     } catch (IOException ioex) {
      // System.err.println(ioex);
      errors.add(ioex);
     }
    }
   } // while

   // System.out.println ("results = " + thisResult);

   results.putAll(thisResult);

   Iterator<Class<?>> it = thisResult.keySet().iterator();
   while (it.hasNext()) {
    v.add(it.next());
   }
   return v;

  } // synch results
 }

 public static void main(String[] args) {
  args = new String[] { "java.lang.Object" };

  SubClassFinder finder = null;
  Vector<Class<?>> v = null;
  List<Throwable> errors = null;

  if (args.length == 1) {
   finder = new SubClassFinder();
   v = finder.findSubclasses(args[0]);
   errors = finder.getErrors();
  } else {
   System.out
     .println("Usage: java SubClassFinder <fully.qualified.superclass.name>");
   return;
  }

  System.out.println("RESULTS:");
  if (v != null && v.size() > 0) {
   for (Class<?> cls : v) {
    System.out.println(cls
      + " in "
      + ((finder != null) ? String.valueOf(finder
        .getLocationOf(cls)) : "?"));
   }
  } else {
   System.out.println("No subclasses of " + args[0] + " found.");
  }
 }
}

Monday, May 3, 2010

Undersating Java Dynamic Proxy

UNDERSTANDING DYNAMIC PROXIES

Dynamic proxy is a class that is created at runtime implementing a set of given interfaces that you need. ‘Created at runtime’ means that you will not be actually writing and compiling any class that implements the interfaces that you need. Instead you will be creating a class dynamically at runtime using the java.lang.reflect.Proxy class. It is called proxy because it is based on the Proxy Design Pattern.

Dynamic proxy invocation is a well established pattern in Java. Especially, Containers that provide middle-ware services use this pattern extensively to intercept the calls and embed their services.
Like Hibernate, spring and many more technologies will use third party libraries to proxy our instances.

Class you should get to Know:
1) java.lang.reflect.InvocationHandler – When you create proxy objects you would want come code to be executed when any method is called on the Proxy Objects, you write that code to be executed in your implementation of this InvocationHandler Interface.
The Invocation Handler interface has only one method:-
Object invoke(Object proxy, Method method, Object[] args)
Here you can see that There are three arguments passed to this method, lets see what they mean:-
a) The proxy Object – This is nothing but the object on which a method was called which caused this method on the invocation handler to the invoked. You might think ‘why this argument is needed?’ Well, you can use one invocation handler to create more that one proxy which implements different interfaces in which case you would want to know the object on which the method was called.
b) The Method - The method in the proxy Object which was called. Its trivial why this is needed.
c) args Object array - The arguments that were passed to the method that was invoked.
2) java.lang.reflect.Proxy – User to create Proxy Objects which will be implementing all the interfaces that you desire. To create a new Proxy object, you use the static method
static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler handler)
Lets see what the arguments mean:-
a) Loader :- it is the class loader to be used to hold the Dynamic Class that was created. The dynamic class that is created will be extending the Proxy class and implementing the interfaces given by you and the proxy object that is returned will be an instance of this class.
b) Interfaces:- is the list of interfaces that this proxy object should implement
c) Handler:- is the handler which should be invoked when any method is invoked on the proxy object.
 
Example
To learn to use dynamic proxies lets develop a small application where we shall be using dynamic proxy to create a listener that implementsMouseListener and MouseMotionListener and then use this listener instance to print all the mouse events that occur on a JFrame.
 
First let’s create a class called TestHandler that implements InvocationHandler.
public class TestHandler implements InvocationHandler
{
             public Object invoke(Object proxy, Method method, Object[] args)throws Throwable
        {
            System.out.println("Invocation handler invoke method "
+ method.getName() + " with args " + args.toString());
                         return null;
        }
}

In the invoke Method, we are just printing the method name and the arguments
 
 
Now lets write our main function.
 
public static void main(String[] args)
{
    JFrame frame = new Testframe();
    Object proxy = Proxy.newProxyInstance(frame.getClass().getClassLoader(),
    new Class[] { MouseListener.class, MouseMotionListener.class },new TestHandler());
    frame.addMouseListener((MouseListener) proxy);
    frame.addMouseMotionListener((MouseMotionListener) proxy);
    frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
    frame.setSize(400, 400);
    frame.setVisible(true);
}
Lets now inspect the snippet of code that create a proxy instance
Object proxy = Proxy.newProxyInstance(frame.getClass().getClassLoader(),
new Class[] { MouseListener.class, MouseMotionListener.class },new TestHandler());
 
We are creating a new proxy instance for a dynamic class that implements MouseListener and MouseMotionListener . All the method calls in this object will be delegated to the instance of TestHandler that is passed.
 
Program Output:
Invocation handler invoke method mouseEntered with args [Ljava.lang.Object;@1ffb8dc
Invocation handler invoke method mouseMoved with args [Ljava.lang.Object;@1ffbd68
Invocation handler invoke method mouseMoved with args [Ljava.lang.Object;@ec16a4
Invocation handler invoke method mouseMoved with args [Ljava.lang.Object;@1cd8669
Invocation handler invoke method mouseMoved with args [Ljava.lang.Object;@119cca4
Invocation handler invoke method mouseMoved with args [Ljava.lang.Object;@ca2dce

I will try to update this post with more examples later, this is just a quick wrap up

Friday, March 26, 2010

Java Authentication and Authorization Service (JAAS)

Introduction
Java™ Authentication and Authorization Service (JAAS). Im trying to explain some of the options available to help you enable security on the JBOSS Application Server, version 4.x, and how to choose between these options. Here i will discusses various aspects of J2EE security, common pitfalls found during implementing JAAS in one of my earlier tasks, and mechanisms I followed for overcoming these pitfalls.

Introduction to JAAS
JAAS delivers a framework for providing authentication and authorization for all the Java applications. Authentication is a mechanism to verify the client; authorization is a mechanism to ensure that the client has the permissions required to access a secured resource.
At a high level, the steps to enable JAAS-based security are as follows:

1. Identify the resource that needs to be secured. For the purpose of this paper, let’s consider a Web application and an Enterprise Java Bean (EJB) application.

2. Identify a suitable security provider. The security manager that comes with JAVA 2 provides the security. In the case of JBOSS, the security is provided by the JBOSS security manager.

3. Use a security implementation to secure the identified resources.

4. Make the clients of the secured resources aware of the security implementation and usage mechanisms. This is important as it is expected that the client will provide some sort of identifier before allowing access to secured resources. The identifiers in most cases are either username/password combinations or digital certificates. The clients must be aware of the required identifier before accessing the resource and should provide it when required.

The JAAS classes that enable the above are:

• LoginModule: This is the security implementation that authenticates and authorizes the clients. A typical implementation involves validating the username/password combination.

• LoginContext: Using this LoginContext, the client will be able to perform a login.

• CallbackHandler and Callback: These are the classes that allow interaction/data-transfer between the clients and the LoginModule. The LoginModule uses a Callback class to request information from the clients. The CallbackHandler class on the client side provides the required information based on the type of Callback class.

• Principal and Group: The LoginModule populates identification information (for example, Name, Address, etc.) about the client into the Principal class and authorization information (role list) into the Group class.

• Subject: This is the result of a successful login. This contains the authenticated Principal and Group. A Subject can also be viewed as a secure representation of the client after authentication.
1. The client initiates the login using the LoginContext. The inputs to the LoginContext are the    CallbackHandler and the type of login configuration to use. The LoginContext internally instantiates the LoginModule and calls the initialization method.
2. The client then calls login() on the context. This results in the LoginContext calling the login() method of the LoginModule. The LoginModule would need some client verification information. This will be obtained using Callbacks. The CallbackHandler handles these Callbacks and provides the requested information. Note: The CallbackHandler is a client implementation that handles specific Callbacks. The handler must know the exact Callbacks (or have a list of all potential Callbacks) that the LoginModule uses so that it can provide the required information to the LoginModule.

3. The LoginModule verifies this information. If the information is invalid, then a LoginException is thrown. If the information is correct, authorization information for the client is obtained.

4. The LoginContext then calls the commit method. In this method, the LoginModule sets the principal and authorization information into the Subject.

5. The LoginContext returns this authenticated information back to the client.

6.The client uses the Subject to access a protected resource.

Security mechanisms in JBOSS
The JBOSS application server provides pluggable security managers. The Web and the EJB Containers use the security managers to perform authentication and authorization. The JAAS-based security manager is the default security manager provided with JBOSS. Though it is easy to replace the security manager with a custom implementation, this is not recommended.
Note: The JAAS security manager obtains the required configuration information from the login-config.xml file located in the conf folder.
The XML file provides a list of security domains that are available on the server. Each domain specifies a list of LoginModules that protect the domain. The list of LoginModules can be specified as “required” or “optional”. To gain access to the resources protected by a domain, the client must be able to satisfy all the LoginModules that are configured as required. If any of the required LoginModules are not satisfied, the client will not be able to access the resource.
Any options to the LoginModule can be specified in a configuration file. These will be passed to the module during the call to initialize().
Note: Each security domain will be read by the JAAS security manager, converted into a SecurityDomainContext object, and bound in JNDI at java:/jass/
An application can choose from one (and only one) of the configured security domains to protect itself from the client access.

LoginModule implementation in JBOSS
The JAAS security manager doesn't perform the authentication. Instead, it instantiates the LoginModules that performs the actual authentication and authorization.
JBOSS provides LoginModules out of the box. Some of these LoginModules are:

• UserRolesLoginModule: This module reads the username, password and role information from files that are packaged with the applications.

• DatabaseServerLoginModule: This module reads the username, password and role information from the tables in a database. The database is accessed using JDBC and the JDBC driver needs to be available in the application classpath.

• LDAPLoginModule: This module requires the username and password. This is used to connect to LDAP as a means of verification. If successful, the roles are based on the group memberships of the user. This module is not very configurable as it doesn’t expose enough configuration options to work with all LDAPs.

• BaseCertLoginModule: This module uses client certificates to perform authentication. It cannot provide role information. This is typically used in conjunction with one of the other LoginModules to obtain the role memberships.

Custom LoginModule implementations
If the available login modules in JBOSS are insufficient, we can provide a custom implementation of the login module. In most enterprise applications, the user and the role information is stored in LDAP. As the LDAPLoginModule that comes with JBOSS not extensible enough to search for the group memberships, we must provide a custom implementation of the LoginModule interface.
We have a couple of options for doing so:

• Extend the abstract UsernamePasswordLoginModule: JBOSS provides an abstract UsernamePasswordLoginModule that is the super class for all Authentication and Authorization (A&A) based on the username and password. This can be extended to perform the required authentication against LDAP and to search for group memberships.

• Write an independent LoginModule: We could use this option if we don’t want the LoginModule to use JBOSS specific classes and to remain totally portable.

Let’s look at the latter option with a sample.
A custom implementation of the LoginModule interface involves implementation of the following methods:
• initialize (Subject, CallbackHandler, Map, Map): This is called by the security manager after the object instantiation. The purpose of this method is for the LoginModule to initialize itself based on the configuration options. The example of these configuration options could either be (in case of LDAP) the LDAP server address that holds the user or the LDAP context where the roles can be searched. These options are specific to the LoginModule implementation and this determines its behavior. The Subject is used to store the Principal and role information after a successful login() and commit().

• login(): This is the core method. This method is supposed to perform the authentication and get the authorization (role) information from the information store. However, it’s important to note that this method should not store the authentication and the role information in the Subject. This information must be stored in the Subject only in the commit method.

• commit(): This method is called only if all the required LoginModules in the security domain successfully execute the login() method. This method should store the A&A information in the Subject.

• logout(): This method is called when the client does a logout. Here, the implementation should delete the A&A information from the stored Subject.

• abort(): This method is called when the client aborts during a login. This method is used to free up any resources that are held by the implementation.

In the case of the LoginModule implementations (JBOSS supplied or custom), the A&A information is stored in the Subject. The information is stored using implementations of the two interfaces. One interface is used for the user data and the other for specifying the role information.

• Interface java.security.Principal: A principal represents the information related to an authenticated client.

• Interface java.security.acl.Group: Implementation used to hold a collection of Principals under a common name. The interface provides methods to add and remove Principals and to query if a Principal is part of the group.

Notes:

• java.security.acl.Group extends java.security.Principal. So in reality, all the information is stored in the form of a Principal.
Any information about an authenticated client is stored using a Principal. Typically, this includes name, address, phone number, email etc.

• It’s important to note that the role memberships are also Principals. In these cases, every role that the client belongs to is a Principal and all these Principals are collected into a group with a common name.

In the case of JBOSS, for the JAAS security manager to be able to identify the principals that identify the role memberships, the principals need to be consolidated into a Group named “Roles.”

Securing a Web application in JBOSS
Let’s examine what it takes to secure a J2EE web application in JBOSS. In this section, we will examine only the declarative security mechanisms; we won’t cover programmatic security.
Declarative security for a web application involves providing select access to web resources based on certain roles that the client is assigned.
Note: In J2EE web applications, a web resource is secured based on the URL pattern and the HTTP method (GET, POST etc) used to access the resource.
In the web.xml file, collections of resources that can be accessed by certain roles must be defined along with the list of roles that can access the resources. An example of web.xml settings for declarative security is shown below:
<security-constraint>
<web-resource-collection>
<http-method>HEAD</http-method> 
<http-method>GET</http-method> 
<http-method>POST</http-method> 
<http-method>PUT</http-method> 
<http-method>DELETE</http-method> 
</web-resource-collection> 
<auth-constraint> 
<role-name>Secure</role-name> 
</auth-constraint> 
</security-constraint> 
In the above example, all the resources with the URL pattern /secure/* are protected, and the client must belong to the “Secure” role to access these resources.
Note: Any number of tags may be defined in web.xml.

During application packaging, the administrator must choose the security domain that will protect the application. This is specified in the JBOSS specific deployment descriptor, jboss-web.xml. A sample jboss-web.xml is shown below:
<jboss-web> 
<security-domain>java:/jaas/securedomain tag. 
• org.jboss.security.SecurityProxy: This interface provides methods that permit or disallow the access to an EJB method.
Notes:

o The invokeHome() and the invoke() methods provide hooks to check whether or not the EJB method should be allowed to execute.

o The out-of-the-box org.jboss.security.SubjectSecurityProxy provides the implementation of the interface.

o An alternate proxy can be installed on a per EJB basis in the jboss.xml using the tag at the XPATH /jboss/enterprise-beans/session.

Some common pitfalls in JBOSS
HTTPServletRequest.getUserPrincipal()
The “getUserPrincipal()” method defined in the HTTPServletRequest interface is used by the web clients to access the Principal called the resource. In the case of custom implementations of the LoginModule interface, it is likely that this method will return a null to JBOSS. To prevent this and to ensure that the correct Principal is available, a Group must be created with the name “CallerPrincipal” in the LoginModule. This group must be added to the Subject within the commit() method. As there can be any number of principals in an authenticated Subject, this indicates to the JBOSS to pick this as the principal to return when the “getUserPrincipal()” method is called.
JBOSS SimplePrincipal and SimpleGroup Vs Custom Principal and Group
As described above, JAAS requires that we use the Principal and Group interfaces to store the authentication and the authorization data. The two options given below discuss this.
JBOSS-provided SimplePrincipal and SimpleGroup implementations
JBOSS provides implementations of the Principal and Group interfaces. However, the use of these implementations binds us to JBOSS, which results in the LoginModule not being portable. Using these implementations is recommended only if a JBOSS provided LoginModule is being extended.
Custom implementations
This is recommended if a completely new LoginModule is written. However, when used with JBOSS, the following must be noted.While implementing the isMember(Principal) : boolean method of the Group interface, comparison must be made based on the String contained within the Principal rather than by directly checking for the Principal. The reason for this is that the Principals within the group might have a different implementation class compared to the implementation class of the method parameter. Therefore, although the Principals contain the same String within them, the result might be false (with a direct comparison).

Saturday, February 27, 2010

Seam Contexts

Seam Contexts


Most of the web based applications use tradetional contexts (Request, Sesssion, ServletContext and end up with writing lots of code base to maintain the state. Some times developers need to store instances in Session Context though they need not to be in Session context for the whole User’s Session. That’s where Seam comes in, Go on..


One of the most exciting features of JBoss Seam is the contextual component model that radically changes the way we design applications. It has become so important, it is now part of the JEE6 specification through the JSR-299.


You may already be familiar with the request, session and application scopes of the Servlet specification. They are very useful to save and retrieve data but they have a huge limitation: you can only access them from a Servlet/JSP.

JBoss Seam overcomes this limitation by making the scopes (called contexts in Seam) available to the whole application instead of only to Servlets/JSP’s. So, you’ll find request(event)session and application contexts and 3 more they’ve created: pageconversation and business process contexts.

The request(event), session and application contexts work exactly as they do in Servlets/JSP’s so I’ll just skip their explanation. I will, however, explain briefly the pageconversation and business process contexts.

Page Context
The page context is broader than the request context as it spans multiple requests over the same page. This is very useful if you need to make roundtrips to the server to perform validation, bring information, etc. while maintaining the same page state.

Conversation Context
The conversation context is broader than the page context as it can expand to multiple request and pages but narrower than the session context. It is very useful to implement wizards-like interfaces in which the user has to fill data across multiple pages while maintaining the state over the whole process. You control the creation and destruction of each conversation.

Business Process Context
As it name implies, it is used to maintain state information during the execution of a business process instance in jBPM.

Using contexts from your code
You can use the Contexts class to gain access to one of the contexts, defined by the Context interface, and then use theset or get methods to save or retrieve information respectively.
Each Context will be bind to a ThreadLocal, so you can access them using set and get methods of ThreadLocal as usual

Contexts Class code snippet
static final ThreadLocal<context> applicationContext = new ThreadLocal<context>();
static final ThreadLocal<context> methodContext = new ThreadLocal<context();
static final ThreadLocal<context> eventContext = new ThreadLocal<context>();
static final ThreadLocal<context> pageContext = new ThreadLocal<context>();
static final ThreadLocal<context> sessionContext = new ThreadLocal<context>();
static final ThreadLocal<context> conversationContext = new ThreadLocal<context>();
static final ThreadLocal<context> businessProcessContext = new ThreadLocal<context>();

For example, to save the current user information in the session context you use the following code:
User user = new User();
Contexts.getSessionContext().set("user", user);
Then, when you need to retrieve the user information, you use:
User user = (User)Contexts.getSessionContext().get("user");
Really simple, ah? You can also use the @Out and @In annotations in class attributes to save and retrieve information:
@Out(value="user",scope=ScopeType.SESSION)
User user;
What the @Out annotation is telling Seam is to save the User object in the Session context with the key “user”. Then, you can retrieve the user with the following code:
@In(value="user",scope=ScopeType.SESSION);
User user;
Again, the @In attribute is telling Seam to inject the User object from the Session context saved with the “user” key. You don’t have to write any getters or setters in your class, Seam will just outject or inject the information whenever an @Out or @In annotation is present. If no object is found under the “user” key, null will be injected.
As you can see, the value attribute of the @In and @Out annotations are used as a key for searching or saving data in the contexts. The scope attribute is used to specify the context in which the value should be injected or outjected. This attributes are optional; so, what happens if we don’t specify them as in the following example?
@In
When you don’t specify the value attribute, Seam uses the attribute’s name as key by default. In the preceding code fragment, Seam will use “name” as the key for the @In annotation and “user” for the @Out annotation.
If you don’t specify the scope of an @In annotation, Seam will scan all the contexts in the following order: eventpage,conversationsessionbusiness process and application. If the key is not found, it will inject null. You can use this feature programmatically by calling the Contexts.lookupInStatefulContexts() method.
If you don’t specify the scope of an @Out annotation … well, as the @Out JavaDoc states: “If no scope is explicitly specified, the default scope depends upon whether the value is an instance of a Seam component. If it is, the component scope is used. Otherwise, the scope of the component with the @Out attribute is used.” I know, I haven’t talked anything about Seam components as it is not the topic of this article. I probably post my next topic on Seam Componet model.

JBoss Seam

JBoss Seam is a web application framework for Java EE 5, developed by JBoss. It uses two proven Java frameworks: EJB3 and JSF, by using these you can easily access any back-end EJB component from the front-end by addressing it by its Seam component name. Seam introduces the concept ofcontexts. Each seam component exists within a context. The conversation context for example captures all actions of a user until he logs out or closes the browser - even multiple uses of the browser back-button. You can automatically generate a CRUD (create-read-update-delete) web application from an existing database using seam-gen, a command line tool. Seam unifies the component models of JSF and EJB3, eliminating glue code, and letting the developer think about the business problem. Seam supports two open source JSF-based AJAX solutions: ICEfaces and Ajax4JSF. These solutions let you add AJAX capability to your user interface without the need to write any JavaScript code. Seam also provides a built-in JavaScript remoting layer for EJB3 components. AJAX clients can easily call server-side components and subscribe to JMS topics, without the need for an intermediate action layer. Neither of these approaches would work well, were it not for Seam's built-in concurrency and state management, which ensures that many concurrent fine-grained, asynchronous AJAX requests are handled safely and efficiently on the server side.