Wednesday, September 13, 2006

RAD - 'the evil WSAD legacy' strikes back

Ok, interestingly I read that IBM will not support WSAD from September 30th, 2006; so inevitably that means the big corporates will migrate to RAD (IBM's Rational Application Developer) over the next year.

The experience I have had with RAD is minimal. Of interest, I did, however, try and import a legacy J2EE project which was being developed and maintained with WSAD. RAD was unable to do this.

Let me clarify this - RAD was able to import all the source, ejb folders and the J2EE project was able to compile. The RMIC deployment however was significantly flawed. The only theories I have at the moment are:

(1) WSAD embeds IBM-centric descriptors in the configuration of EJBs (in particular entity beans) that are not fully supported in RAD
(2) the RMIC deployment tool between WSAD and RAD is not the same (requires some feature to deply RMIC code like WSAD)
(3) more stringent validation occurs in the RMIC deployment of RAD over WSAD
(4) updates to libraries (e.g. database drivers) causes errors in the OR mappings

Unfortunately, for the J2EE legacy project I am working on, this means that WSAD is no longer supported and RAD cannot support it! And indeed the error messages that RAD has produced have been highly ineffectual.

So IntelliJ? well that would be a great! but like any high-quality IDE it does not allow cyclic dependencies. So what now?

Tuesday, September 12, 2006

IntelliJ live templates

I know, I know a lot of other people have done this; but I am continually working in IntelliJ and keep losing the live templates I write, so whenever, I need one, I will just update this post.

JUnit test


public void test$METHOD_TO_TEST$() throws Exception {
$END$
}


JUnit test (fail condition)

public void test$METHOD_TO_TEST$() throws Exception {
try {
$FAIL_CONDITION$
fail();
}
catch ($EXCEPTION$ $EXCEPTION_ABBREVIATION$)
{ }
}

J2EE development and the 'evil WSAD legacy'

Around 2 years ago, I read a blog from a prominent software engineer in Melbourne (Jon Eaves) who posted about the 'evils' of Websphere Application Developer - having never used it, I read with curiosity and this reaffirmed my own development management of the team I was running at the time, in using: IntelliJ for an IDE, Maven for an independent test/build/development management system, and predefined, one-per-developer based IBM Webpshere Application Server (to which developers deployed to).

2 years forward (and as mentioned before, working on a legacy J2EE project) - I am using IBM's Eclipse2.0-based WSAD and a 1 hour + ANT development management system. After using it for a week, there are several key characteristics of WSAD which seem to engender poor code and development practises:

  • In-built pseudo 'test' Websphere Application Server; what is the rationale in deploying to a IDE-based server? if everything deploys what has this actually proven? it has not been deployed on a Websphere Application Server and does not mitigate any of the risk associated with this. If anything, it promotes point-and0click testing and runtime debugging to be used as a substitute for unit testing. A better idea would be to have WSAD / RAD, etc. to have an extensible / callable EJB container that could be invoked off a unit testing framework such as JUnit, TestNG such that unit tests of legacy EJB2.0 code actually be tested. Assumptions regarding the full application deployment could then be verified on developer instances of WAS (and with integration tests).
  • Non-standards based directory structure; if WSAD / RAD is going to provide Wizards to set up a new project - then conform to the industry standards in terms of directory structure, or at least allow any directory structure to be used. Currently, WSAD imposes a directory structure.
  • Non-standards based artifact generation. Upon seeing the monolithic ANT development management process, I thought, I would be easy able to refactor the constituent jars, wars, and ejbs of the project. Unfortunately, this is not possible because IBM introduces its own bindings in the ejb-jar.xml such that it does not even conform to the schema - nonetheless it is able to be deployed on WSAD, WAS. Now only through WSAD (or by calling WAS libraries) is a deployment possible - complete vendor lock-in!
  • Loose intra / inter project error checking - WSAD allows projects to have cyclic dependencies - when is this ever a maintainable approach? Error checking within a project is also poor (somewhat an artifact of Eclipse2.0).
  • Extremely poor IDE responsiveness / performance on projects with multiple modules.
The 'evil WSAD legacy' results :- J2EE projects that are WSAD-bound (i.e. not able to develop / develop in any other IDE), poorly defined, poorly error-checked, and poorly tested. Of course, this is somewhat dependent on the developers that worked on the project in the first place - but with WSAD's loose industry compliance - it is difficult to see how any significant J2EE project will be maintainable in the long run if it has been developed, and continues to be devloped on WSAD.

So what do all the projects that have been run on WSAD do in the next 2-3 years when dealing with this legacy unmaintanenable code ...

Wednesday, September 06, 2006

OpenEJB 1.0

I am currently working on a legacy J2EE project, which requires some rework to its EJB 2.0 implementation (e.g. session beans, entity beans). To do this, I investigated OpenEJB 1.0 - this open source library aims to establish a J2EE container inside a unit test. The aim of this is to facilitate the unit testing of EJBs. A thorough investigation revealed that OpenEJB 1.0 should only be used for lightweight session bean based only EJB implementations. I was able to successfully unit test session bean interfaces on session beans which did not call any other EJBs, or if so, only other session beans (e.g. session beans following the command pattern). Here are the steps I followed to unit test the session beans:

  1. copy the OpenEJB default 'logging.conf' and 'openejb.conf' to a properties directory in your project's unit test classpath; ensure that your log4j (through log4j.properties) configuration is outputting to the console (as the logging of OpenEJB is very useful at runtime to find JNDI references)

  2. configure OpenEJB in the constructor of the test case
    public SBBeanTest(String testcaseName) throws Exception {
    super(testcaseName);
    System.setProperty
    (Context.INITIAL_CONTEXT_FACTORY, "org.openejb.client.LocalInitialContextFactory");

    System.setProperty("openejb.configuration", "conf/openejb.conf");
    context = new InitialContext(System.getProperties());
    }


  3. configure the 'openejb.conf' xml file such that it is pointing to the base directory where the META-INF directory and ejb.xml of the session beans resides; specify the full path, if necessary (including drive, etc.)
    <openejb>
    <Container id="Default Stateless Container" ctype="STATELESS" />
    <Deployments dir="\src\java" />
    </openejb>


  4. add a 'openejb-jar.xml' xml file to the META-INF directory where the ejb-jar.xml is located; this provides a mapping between the bean names (in the ejb.xml) and the JNDI names with which you are providing

    ejb-jar.xml
    <ejb-jar>
    <enterprise-beans>
    <session>
    <ejb-name>SB</ejb-name>
    <home>foo.bar.SBHome</home>
    <remote>foo.bar.SBRemote</remote>
    <ejb-class<foo.bar.SB</ejb-class>
    <session-type>Stateless</session-type>
    <transaction-type>Container</transaction-type>
    </session>
    </enterprise-beans>
    </ejb-jar>

    openejb-jar.xml
    <openejb-jar>
    <ejb-deployment ejb-name="SB"
    deployment-id="ejb/foo/bar/SBHome"
    container-id="Default Stateless Container"/>
    </openejb-jar>


  5. test that the session bean has been successfully looked up with OpenEJB
    public void testSBNotNull() throws Exception {
    Object ebObject = context.lookup("ejb/foo/bar/SBHome");
    SBHome sessionbeanHome = (SBHome)
    PortableRemoteObject.narrow(ebObject, SBPHome.class);

    SB sessionbean = sbHome.create();
    assertNotNull(sessionbean);
    }


  6. if configured correctly then the JUnit test will pass, with similar logger.debug output to this below
    ********************************************************************************
    OpenEJB http://www.openejb.org
    Startup: 30/08/06 10:39
    Copyright 1999-2004 (C) OpenEJB Project, All Rights Reserved.
    Version: 1.0
    Build date: 20060226
    Build time: 1701
    ********************************************************************************
    WARN : No ApplicationServer was specified! The container system will only be accessible
    by same-vm clients via the IntraVm Server.

    DEBUG: Instantiating assembler class org.openejb.alt.assembler.classic.Assembler
    WARN : Cannot find the configuration file [null], Trying conf/openejb.conf instead.
    DEBUG: Containers : 4
    DEBUG: Type Container ID
    DEBUG: ENTITY Default BMP Container
    DEBUG: ENTITY Default CMP Container
    DEBUG: STATEFUL Default Stateful Container
    DEBUG: STATELESS Default Stateless Container
    DEBUG: Deployments : 1
    DEBUG: OpenEJB.startup - Type Deployment ID
    DEBUG: OpenEJB.startup - STATELESS ejb/foo/bar/SBHome
    DEBUG: SecurityService : org.openejb.ri.sp.PseudoSecurityService
    DEBUG: TransactionManager: org.openejb.core.TransactionManagerWrapper
    INFO : OpenEJB ready.
And there you have it - session beans unit tested!