Sunday, March 15, 2009

Web Beans Beta 1 is released

A first Beta of Web Beans a RI of "JSR-299: Java Contexts and Dependency Injection" has been recently released.

Yes, the name of the spec has been changed from Web Beans to "Java Contexts and Dependency Injection" (I am wandering whether it will be known as JCDI? :) ).

The development goes pretty hard, it's already implements about 90% of the JSR-299 spec.

The latest release (the next after ALFA-2) brings the following features:
* Transactional observers
* Asynchronous Observers
* Conversations, including propagation in JSF
* Bootstrap improvements

The release is targeted for use with JBoss AS 5.0.1.

What's interesting is that the TCK tests make intensive use of TestNG and annotations to couple the test cases with the spec chapters.
According to Pete Muir the only major feature to be implemented is beans annotation using XML.

Web Beans will make a core of JBoss Seam 3.0 which makes it even more interesting!

Way to go!

Monday, June 16, 2008

History of Apache, Eclipse and Python visualized

Michael Ogawa has been studying visualization of people activities and interactions in software projects. His visualization application called code_swarm shows history of developers' activity and their commits:

"Both developers and files are represented as moving elements. When a developer commits a file, it lights up and flies towards that developer. Files are colored according to their purpose, such as whether they are source code or a document. If files or developers have not been active for a while, they will fade away. A histogram at the bottom keeps a reminder of what has come before."
He has visualized well known projects such as Eclipse, Python, PostgreSQL and Apache.

I really liked the Python visualization:


code_swarm - Python from Michael Ogawa on Vimeo.

The rest of the videos can be found at the code_swarm project: http://vis.cs.ucdavis.edu/~ogawa/codeswarm/

It would be nice if the project went open source!

Sunday, December 2, 2007

Windows SSO with JBoss Seam

Unified authentication has been one of the frequently asked functionality for quite some time now. Users have to remember username/password for various systems or having to login for each system while all those systems are part of the same intranet and this doesn't make life/work easier.
The goal of this article is to show how it is possible to have a very simple solution to use Single Sign-On for WIntel based intranets to get access (and authenticate) to web sites without having to fill-in their user name and password (by allowing browser to use the windows' user login silently).
Please, also note, that this is merely a demo and in no way a "bullet proof" or production-ready example.

This example uses NTLM implemented by JCIFS that implements the CIFS/SMB networking protocol in 100% Java. CIFS is the standard file sharing protocol on the Microsoft Windows platform. JCIFS already has an implementation of a filter that does the authentication against windows domain contoller. This article simply shows how to make this solution work closely with JBoss Seam built-in security functionality.

For the following example I used JBoss 4.2.2 with default profile, Seam 2.0 GA, JCIFS 1.2.17. And a simple application generated by seam-gen.

  1. Of course you need to get JCIFS library, you can put the jar in /lib directory of your application and modify the 'ear' target in your build script to include the library in EAR during packaging.

  2. Next step would be configuring JCIFS http authentication filter to authenticate incoming requests against the domain controller. This is no different from the way it is done by JCIFS authentification filter:


    <filter>
    <filter-name>NtlmHttpFilter</filter-name>
    <filter
    -class>jcifs.http.NtlmHttpFilter</filter-class>
    <init-param>
    <param-name>jcifs.http.domainController</param-name>
    <param-value>your domain controller ip or name</param-value>
    </init-param>
    <init-param>
    <param-name>jcifs.smb.client.domain</param-name>
    <param-value>your domain</param-value>
    </init-param>
    <init-param>
    <param-name>jcifs.smb.lmCompatibility</param-name>
    <param-value>3</param-value>
    </init-param>
    <init-param>
    <param-name>jcifs.util.loglevel</param-name>
    <param-value>2</param-value>
    </init-param>
    </filter>
    <filter-mapping>
    <filter-name>NtlmHttpFilter</filter-name>
    <url-pattern>
    /*</url-pattern>
    </filter-mapping>



  3. Add autoLogin() method to the generated Authenticator that does the authentication without the need to fill in user name and password by getting the authentication information from the browser. Please note, we are setting a fake password as in this case we don't even know it, but by having a password set we actually make Seam recongize the identity as logged-in:


    /**
    * Performs the windows authentication.
    * @return true if auto login was successful
    */
    public boolean autoLogin() {

    // trying auto-login
    Object autoLogin = sessionContext.get("NtlmHttpAuth");
    boolean isAuthenticated = false;

    if ( autoLogin != null && (autoLogin instanceof NtlmPasswordAuthentication) ) {
    NtlmPasswordAuthentication ntlm = (NtlmPasswordAuthentication) autoLogin;
    String username = ntlm.getUsername();
    identity.setUsername( username );
    identity.setPassword("jibberish"); // trusting NTLM - not setting real password and even better if we don't
    isAuthenticated = true; // user is authenticated successfully via NTLM
    identity.addRole("admin");
    }

    return isAuthenticated;
    }

    I have also modified the generated authenticate() method so it can re-use the auto-login functionality. Note, it does not have any particular purpose in this concrete example but shows how you can re-use SSO if you login manually:

    @In Context sessionContext;

    public boolean authenticate()
    {
    boolean isAuthenticated = autoLogin();
    log.info("authenticating #0", identity.getUsername());
    if ( ! isAuthenticated ) {
    //write your authentication logic here,
    //return true if the authentication was
    //successful, false otherwise
    }
    // if we are here then the user is authenticated against NTLM or login dialog
    return true;
    }



    Furthermore, for manual form-based authentication (this is where authenticator.authenticate() is used) you can use "arbitrary user credentials from an application" as specified in the JCIFS FAQ.

  4. Now we need to make Seam to actually call our autoLogin() method when authentication is needed so that our application would have the correct identity in the session scope. This is done by making our authenticator.autoLogin() method to listen to "org.jboss.seam.notLoggedIn" event. Since the generated application already has this event registered we simply add our call to the event registration:

    <event type="org.jboss.seam.notLoggedIn">
    <action execute="#{authenticator.autoLogin}"/>
    <action execute="#{redirect.captureCurrentView}"/>
    </event>

  5. We can also protect all our pages by forcing the login in pages.xml:

    <page view-id="*" login-required="true">
    <navigation>
    <rule if-outcome="home">
    <redirect view-id="/home.xhtml"/>
    </rule>
    </navigation>
    </page>


This was the final step! To get the whole picture this is what is happening:
By forcing the login-required we are forcing the authentication in the application. Since for the first time authentication fails we we have "org.jboss.seam.notLoggedIn" event fired which will call our #{authenticator.autoLogin}. In turn autoLogin does the windows authentication and sets the user name and fake password on Identity.
Because notLoggedIn event is fired before the authentication for the page we requested fails, initializing the injected identity with the user name and password marks the identity as already logged and thus let's us reach the page without the visiting the login page.

p.s. If you authenticating against a workstation make sure you have simple file sharing switched off! This setting can be found at (Win XP) Explorer->Tools->Folder Options->View->Use simple file sharing - uncheck this checkbox!

Wednesday, September 5, 2007

Maven 2 and WebSphere - automated build and deployment of J2EE applications

After long search on different solutions on automated building and deployment of J2EE applications with maven that can work for WebSphere few posts were found. Some of them (big thanks to Peter Pilgrim) cover ways to build EJB modules that could be 'understood' by websphere (that is build websphere specific stubs and skeletons). Some posts show how to configure maven (including maven-eclipse-plugin) so that maven could work with RAD-6 and vice versa.
All we have to do is put it all together, automate deployment of EAR (remember cargo plugin doesn't support websphere yet) to websphere and hook functional tests (using selenium) into the integration test phase.
So the project consists of an ejb, war, ear, functional testing and a parent modules, like this:


 parent_project
|-ejb_module
|
|-war_module
|
|-ear_module
|
|-test_module




Looks like a complete set? Let's go through all the modules.



Saturday, March 3, 2007

No more pain in constructing collections of SelectItem's

It's been some time before I noticed something in Seam that I should have noticed long time ago... Ever experienced pain converting results of your queries into collections of Collection<SelectItem> just to show them in, for example <h:selectOneMenu>? Well this pain may be over with Seam (starting from version 1.1.5 I think) now supporting the following tag: <s:selectItems>.

What it does is it creates a collection of SelectItem (List<SelectItem>) from your List, Set, DataModel or Array. For the list of attributes refer to the reference documentation and the "ui" example of seam which is included in the Seam distribution (can be found in "examples/ui")

Wednesday, February 28, 2007

Seam 1.2 is released

It's nice to see Seam gaining more speed (especially since the JBoss Seam team has been increased). Because of the number of changes it was decided to skip the 1.1.7 release and make it 1.2 which I think is a wise decision (considering the big 'jump' in 1.1.5). More and more Seam tries gets one of the best frameworks out there closer and closer together making it look like one framework more and more with every release. Many RoR followers (and .Net actually as well) think that the enormous variety in java client-server frameworks becomes a disadvantage... well.. Seam eliminates a lot of reasons to think so - It already makes jsf/ajax4jsf/facelets look like one framework with the help of seam-gen (it's enough to have a look at the tutorial to see that). The major improvements I think are spring, ajax4jsf integration and security (full release notes can be found here). Even though the security was brought in 1.x I still think it's a major step forward. And things like (Gavin©):


entityManager.createQuery("select u from User u where u.name=#{user.name}").getResultList();


make the coding much more pleasant especially to those who did similar things in RoR.

And I would love to see the following things from my wish list implemented in some (near) future:

  • rails-like database data migrations (but less redundant)


  • rails-like test possibilities (I would love to be able to assert html as result of actions as well)

Thursday, December 14, 2006

Running JBoss Seam on Resin 3.0.2x

Yes, it's working. With little Resin 'compatibility' workaround its' possible to run Seam 1.1 on Resin! In this example it run on Resin 3.0.21.
To make Seam working on Resin the following steps are necessary:

  • Make Resin to 'like' the web.xml by making the namespace empty: <web-app xmlns="">

  • Make Resin use apache xml parser by creating WEB-INF/resin-web.xml and putting the following in it:


    <web-app xmlns="http://caucho.com/ns/resin">

    <system-property javax.xml.parsers.DocumentBuilderFactory="org.apache.xerces.jaxp.DocumentBuilderFactoryImpl"/>
    <system-property javax.xml.parsers.SAXParserFactory="org.apache.xerces.jaxp.SAXParserFactoryImpl"/>

    </web-app>


  • Put xercesImpl.jar in the lib dir of the web app

  • If you want to run Seam in ejb3 micro-container you would have to delete the ejb-30.jar from Resin/lib directory otherwise you will get conflicts.





If it's not possible to delete ejb-30.jar from resin/lib (permissions don't allow or can't interfere with other virtual hosts) the the following can be still done to make ejb-3 work in jboss microcontainer:

Create the following class:


package org.emaps.resin;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
* Introduces a very specific classloader hack for Resin so that it uses ejb.*
* packages from deployed Seam. This hack wont be needed as soon as Resin
* catches up with ejb-3.
*
* @author Siarhei Dudzin
*
*/
public class ClassloaderHack implements ServletContextListener {

/** Log from apache commons logging */
private static final Log log = LogFactory
.getLog(ServletContextListener.class);

/**
* @see javax.servlet.ServletContextListener#contextDestroyed(javax.servlet.ServletContextEvent)
*/
public void contextDestroyed(ServletContextEvent arg0) {
// do nothing
}

/**
* @see javax.servlet.ServletContextListener#contextInitialized(javax.servlet.ServletContextEvent)
*/
public void contextInitialized(ServletContextEvent arg0) {
log.info("Starting Resin classloader hack for JBoss Seam");

try {
ClassLoader classLoader = ClassloaderHack.class.getClassLoader();
if (classLoader instanceof com.caucho.loader.DynamicClassLoader) {
com.caucho.loader.DynamicClassLoader resinCL = (com.caucho.loader.DynamicClassLoader) classLoader;

resinCL.addPriorityPackage("javax.persistence.");
resinCL.addPriorityPackage("javax.persistence.spi.");
resinCL.addPriorityPackage("javax.ejb.");
resinCL.addPriorityPackage("javax.ejb.spi.");
}
} catch (Throwable t) {
log.error("Could not get Resin classloader: " + t.getMessage());
t.printStackTrace();
}
}
}



and the following entry in the web.xml before the seam context listener entry:



<!-- Resin classloader hack (needs to be first before all listeners!) -->
<listener>
<listener-class>
org.emaps.resin.ClassloaderHack
</listener-class>
</listener>


This will make sure Resin will use ejb-3 interfaces from your webapp web-inf/lib directory!

That's about it! Enjoy! :)