Sunday, November 8, 2009

WebSphere Process Server JNDI client - JUnit template

Sooner or later you would like to test your code out of container. Of course you would like to use BusinessFlowManager and HumanTaskManager. To make use of them, they should be fetched from JNDI. Problem you may face is that WPS is running with security turned on. Writing JNDI client could be challenging because of JAAS. Official documentation is always missing some vital information. You end up surfing the net looking to some guidance. The same thing I did. The best one I found was blog from Nerdy Eddy. In first part he describes writing client with both SUN JRE and IBM one. To get around security check, EVERYONE group was given permission to use naming service. That will not help using BPC and HTM API. Better solution is one from second part where JAAS login is performed. You can see all the nasty exceptions you can get trying to connect. I got a many of them also. The end result for me was JUnit 4 template.
Here is the code:

import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.rmi.PortableRemoteObject;
import javax.security.auth.Subject;
import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import com.ibm.bpe.api.ActivityServiceTemplateData;
import com.ibm.bpe.api.BusinessFlowManager;
import com.ibm.bpe.api.BusinessFlowManagerHome;
import com.ibm.task.api.HumanTaskManager;
import com.ibm.task.api.HumanTaskManagerHome;
import com.ibm.websphere.security.auth.WSSubject;
import com.ibm.websphere.security.auth.callback.WSCallbackHandlerImpl;

/**
 * @author mresetar
 *
 */
public class SecureBfmAndHtmIntegrationTestAbstract {
    private static final Logger LOG = Logger.getLogger(SecureBfmAndHtmIntegrationTestAbstract.class.getCanonicalName());
    private static final String IIOP_URL = "iiop://localhost:2810";
    protected InitialContext ic;
    protected BusinessFlowManager bfm;
    protected HumanTaskManager htm;
    protected Subject subject;

    protected String getUsername() {
        return "admin";
    }

    protected String getPassword() {
        return "admin";
    }

    protected <T> T fetchRemoteHomeObject(Class<T> homeClass, String jndiName) throws NamingException {
        LOG.finest(String.format(
                "Trying to fetch remote home object of class %s with JNDI name %s", homeClass.getCanonicalName(), jndiName));
        final Object obj = ic.lookup(jndiName);

        return (T) PortableRemoteObject.narrow(obj, homeClass);
    }

    @Before
    public void init() throws Exception {
        Properties props = new Properties();
        props.put(InitialContext.INITIAL_CONTEXT_FACTORY, "com.ibm.websphere.naming.WsnInitialContextFactory");
        props.put(InitialContext.PROVIDER_URL, IIOP_URL);
        props.put(InitialContext.SECURITY_PRINCIPAL, getUsername());
        props.put(InitialContext.SECURITY_CREDENTIALS, getPassword());
        ic = new InitialContext(props);

        BusinessFlowManagerHome processHome = fetchRemoteHomeObject(BusinessFlowManagerHome.class,
                "com/ibm/bpe/api/BusinessFlowManagerHome");

        HumanTaskManagerHome htmHome = fetchRemoteHomeObject(HumanTaskManagerHome.class, "com/ibm/task/api/HumanTaskManagerHome");

        LoginContext lc = null;
        try {
            final WSCallbackHandlerImpl callbackHandlerImpl = new WSCallbackHandlerImpl(getUsername(), getPassword());

            lc = new LoginContext("WSLogin", callbackHandlerImpl);

        } catch (LoginException le) {
            LOG.log(Level.SEVERE, "Cannot create LoginContext.", le);
            throw le;
        } catch (SecurityException se) {
            LOG.log(Level.SEVERE, "Cannot create LoginContext.", se);
            throw se;
        }

        try {
            lc.login();
            subject = lc.getSubject();
        } catch (LoginException le) {
            LOG.log(Level.SEVERE, "Error while logging in!", le);
            throw le;
        }

        bfm = processHome.create();
        htm = htmHome.create();
    }

    @After
    public void afer() throws NamingException {
        if (ic != null) {
            ic.close();
        }
    }

    @Test
    public void testFetchWaitingActivites() throws Exception {
        WSSubject.doAs(subject, new java.security.PrivilegedAction() {
            public Object run() {
                ActivityServiceTemplateData[] waitingActivities = null;
                try {
                    waitingActivities = bfm.getWaitingActivities("_PI:90030123.e6d8e040.b8c09cf5.5dbc0000");
                    System.out.println(waitingActivities);
                } catch (Exception e) {
                    LOG.log(Level.SEVERE, "", e);
                }
                return waitingActivities;
            }
        });
    }
}


I did changes to sas.client.props and ssl.client.props. To run JUnit I had add VM arguments in Elipse's Run Configurations window to following:
-Djava.security.auth.login.config=file:///D:/IBM/WID62/pf/wps/properties/wsjaas.conf
-Dcom.ibm.CORBA.ConfigURL=file:///D:/IBM/WID62/pf/wps/properties/sas.client.props
-Djava.security.policy=file:///D:/IBM/WID62/pf/wps/properties/security.policy
-Dcom.ibm.SSL.ConfigURL=file:///D:/IBM/WID62/pf/wps/properties/ssl.client.props
-DtraceSettingsFile=TraceSettings.properties -Djava.util.logging.manager=com.ibm.ws.bootstrap.WsLogManager  -Djava.util.logging.configureByServer=true


Working directory I changed to bin (build directory) because I wanted to use TraceSettings.properties file for logging. I also changed JRE to WPS JRE. To be able to use BPC API I also added org.eclipse.equinox.registry_3.2.1.R32x_v20060814.jar from WPS plugins directory to class path.

Running the JUnit code above you should get similar to:
Processing Trace Settings File: TraceSettings.properties
[2009.11.08 22:38:00:734 CET] 0000000a WsLoggerConfi W com.ibm.ws.logging.WsLoggerConfigurator getExtensionPointLoggingConfiguration Unable to get extension point - com.ibm.wsspi.extension.logger-properties
[2009.11.08 22:38:00:906 CET] 0000000a SecureBfmAndH 3   Trying to fetch remote home object of class com.ibm.bpe.api.BusinessFlowManagerHome with JNDI name com/ibm/bpe/api/BusinessFlowManagerHome
[2009.11.08 22:38:01:484 CET] 0000000a SASRas        A   JSAS0006I: Security connection interceptor initialized.
[2009.11.08 22:38:01:828 CET] 0000000a SASRas        A   JSAS0001I: Security configuration initialized.
[2009.11.08 22:38:01:875 CET] 0000000a SSLConfig     W   CWPKI0041W: One or more key stores are using the default password.
[2009.11.08 22:38:01:875 CET] 0000000a SSLConfigMana I   CWPKI0027I: Disabling default hostname verification for HTTPS URL connections.
[2009.11.08 22:38:01:906 CET] 0000000a SASRas        A   JSAS0003I: Authentication mechanism: BASICAUTH
[2009.11.08 22:38:02:000 CET] 0000000a SASRas        A   JSAS0007I: Client request interceptor registered.
[2009.11.08 22:38:03:343 CET] 0000000a SecureBfmAndH 3   Trying to fetch remote home object of class com.ibm.task.api.HumanTaskManagerHome with JNDI name com/ibm/task/api/HumanTaskManagerHome
[2009.11.08 22:38:03:796 CET] 0000000a SecureBfmAndH E   
                                 com.ibm.bpe.api.ObjectDoesNotExistException: CWWBA0015E: The object '_PI:90030123.e6d8e040.b8c09cf5.5dbc0000' does not exist; it might have been deleted in the meantime.
 at com.ibm.bpe.framework.BusinessProcessServiceImpl.getWaitingActivities(BusinessProcessServiceImpl.java:29151)
 at com.ibm.bpe.framework.BusinessProcessServiceImpl.getWaitingActivities(BusinessProcessServiceImpl.java:29105)
 at com.ibm.bpe.framework.BusinessFlowManagerBean.getWaitingActivities(BusinessFlowManagerBean.java:16905)
 at com.ibm.bpe.api.EJSRemoteStatelessGenericBusinessFlowManagerEJB_a412961d.getWaitingActivities(Unknown Source)
 at com.ibm.bpe.api._EJSRemoteStatelessGenericBusinessFlowManagerEJB_a412961d_Tie.getWaitingActivities__CORBA_WStringValue(_EJSRemoteStatelessGenericBusinessFlowManagerEJB_a412961d_Tie.java:16226)
 at com.ibm.bpe.api._EJSRemoteStatelessGenericBusinessFlowManagerEJB_a412961d_Tie._invoke(_EJSRemoteStatelessGenericBusinessFlowManagerEJB_a412961d_Tie.java:1131)
 at com.ibm.CORBA.iiop.ServerDelegate.dispatchInvokeHandler(ServerDelegate.java:627)
 at com.ibm.CORBA.iiop.ServerDelegate.dispatch(ServerDelegate.java:480)
 at com.ibm.rmi.iiop.ORB.process(ORB.java:512)
 at com.ibm.CORBA.iiop.ORB.process(ORB.java:1571)
 at com.ibm.rmi.iiop.Connection.respondTo(Connection.java:2717)
 at com.ibm.rmi.iiop.Connection.doWork(Connection.java:2582)
 at com.ibm.rmi.iiop.WorkUnitImpl.doWork(WorkUnitImpl.java:62)
 at com.ibm.ejs.oa.pool.PooledThread.run(ThreadPool.java:118)
 at com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java:1497)



Tuesday, November 3, 2009

Using DB2 Command Window Command to discover DB2 sqlstate message

Colleague showed me a neat way to display DB2 SQLSTATE message. For this "trick" you should have DB2 installed. Launch DB2 Command Window using shortcut or command line by typing db2cmd. New command window is opened. Then you can type db ? SQLSTATE_CODE and you should se message related to that code.
Example is:
C:\Documents and Settings\mresetar>db2 ? 20000

SQLSTATE 20000: The case was not found for the CASE statement.



Wednesday, September 30, 2009

Setup java.util.logging in WAS client (unit test)

If you run WebSphere client it is very useful to have client logging set up. Recently I had the same need when I run some JUnit integration test. In that test I instantiated SCA POJO component that had a lot of log statements logged in. Naturally I wanted to have those log message printed out on console when test is run. After short googling I found out that there are two (easiest) options available:
  1. Using java.util.logging.LogManager built in functionality reading initial configuration from logging.properties file
  2. Enabling trace on client using IBM trace support using trace settings file
I created junit run configuration using both options. There is one issue that I experienced though, I was unable to use eclipse variables like "workspace_loc". I believe that this is because this variable has windows file syntax that is not best understood when reading property file. So when defining run configuration you should use bin (or other output directory) as working directory under Arguments tab. Property file is placed in java source folder.

When using logging.properties I had
-Djava.util.logging.config.file=logging.properties
under VM arguments. My logging.properties has content:
# Add handlers to the root logger.
# These are inherited by all other loggers.
handlers=java.util.logging.ConsoleHandler, java.util.logging.FileHandler

# Set the logging level of the root logger.
# Levels from lowest to highest are
# FINEST, FINER, FINE, CONFIG, INFO, WARNING and SEVERE.
# The default level for all loggers and handlers is INFO.
.level=INFO

# Specify logging levels for specific namespaces.
org.example.level=FINEST

# Configure the ConsoleHandler.
# ConsoleHandler uses java.util.logging.SimpleFormatter by default. 
# Even though the root logger has the same level as this,
# the next line is still needed because we're configuring a handler,
# not a logger, and handlers don't inherit properties from the root logger.
java.util.logging.ConsoleHandler.level=FINEST

# Configure the FileHandler.
# FileHandler uses java.util.logging.XMLFormatter by default. 
java.util.logging.FileHandler.formatter=java.util.logging.SimpleFormatter
java.util.logging.FileHandler.level=FINEST

# The following special tokens can be used in the pattern property
# which specifies the location and name of the log file.
#   / - standard path separator
#   %t - system temporary directory
#   %h - value of the user.home system property
#   %g - generation number for rotating logs
#   %u - unique number to avoid conflicts
# FileHandler writes to %h/demo0.log by default.
java.util.logging.FileHandler.pattern=E:/temp/org_example_test.log

For other run configuration, using IBM trace settings file under VM settings I have
-DtraceSettingsFile=TraceSettings.properties -Djava.util.logging.manager=com.ibm.ws.bootstrap.WsLogManager  -Djava.util.logging.configureByServer=true
  Where TraceSetting.properties has content:
# 5724-I63, 5724-H88 (C) COPYRIGHT International Business Machines Corp. 2000, 2004
# All Rights Reserved * Licensed Materials - Property of IBM


########################################################################
# A property to specify where the output messages and trace (if enabled)
# should be routed. Valid values include stdout or a fully qualified
# file name. If a file is specified but cannot be opened, stdout is used.
# 
# Sample invocations
# To specify stdout - traceFileName=stdout
# To specify a file on NT - traceFileName=c:\\MyTraceFile.log or
#                           traceFileName=c:/MyTraceFile.log
# To specify a file on Unix - traceFileName=/usr/MyTraceFile.log
########################################################################
#traceFileName=e:\\test\\MyTraceFile.log
traceFileName=stdout

########################################################################
# Specify trace strings here. Trace strings take the form of:
# logger={level}={type} where:
#     level = entryexit || debug || event || all
#     type =  enabled || disabled
# examples:
# com.ibm.ejs.ras.SharedLogBase=all=enabled enables all tracing for the
#         single logger created in class com.ibm.ejs.ras.SharedLogBase.
# com.ibm.ejs.*=debug=enabled enables debug tracing for all loggers with
#         names starting with com.ibm.ejs.
#
# Multiple trace strings can be specified, one per line.
########################################################################
org.example.*=all=enabled




Friday, July 3, 2009

It's time to update your WebSphere/Rational software

If you are doing SOA/BPM development then you are probably using RAD4WS (or RSA4WS) and WID. In last few days there are fixes available. Let me mention some versions and fixes that could be in your interest:

1. Rational Application Developer for WebSphere Software, Version 7.5.3
If you are using 7.5 version then you should consider to upgrade. If you are not, why aren't you? I recently upgraded from 7.0 and I had no problem opening old workbench continue working where I lefted.

1.1. IBM WebSphere Application Server 6.1 Test Environment Update v6.1.0.25
If you are developing for (old) 6.1 version of WAS you should also consider to upgrade your TE. You should also get Update Installer V7.0 if you don't have it allready.

2. 6.1.2: WebSphere Integration Developer 6.1.2 Interim Fix 004 for Windows
What is fixed you can read here.

2.1. WebSphere Test Environment V6.1.2 Fix Pack 3 (V6.1.2.3)
Together with WID fix you should install this TE fix pack. Fix list is here.

There are probably fixes for other versions try to google for them.
 

Saturday, May 30, 2009

Keep up with IBM using twitter

Recently IBM is very active on twitter. I found a few of them regarding IBM software, mostly WebSphere and SOA. Check them out: To ease keeping up with tweets you can try one of twitter rich clients like thirl.

Saturday, May 9, 2009

Tools for connecting to IBM WAS Service Integration Bus

For the past year me and my colleagues at CROZ were doing a lot of work that included using service integration bus (SIB) and WAS 6.1 as JMS provider. Very often we needed to look are there any messages in queue or send test message. Two basic tools that does the job comes with WAS distribution:
  • WAS admin console

  • Universal test client (UTC)
Admin console can be used for looking queue (and topic) status at runtime. You can use UTC for sending and posting message using JMS API. However admin console is very cumbersome to use because you need to make 10 clicks to see message content and UTC is okay only for basic scenario.

So what other tools you can use to connect to SIB? Preferably stand alone one.

There are actually 3 nice tools from IBM and few from open source community that are very handy. From IBM you have:
  1. Service Integration Bus Explorer
  2. Service Integration Bus Performance
  3. IBM Client Application Tool for JMS


There are also very nice open source tools that can be connected to WAS SIB. I will mention :
  1. Hermes JMS
  2. Apache JMeter

Service Integration Bus Explorer

SIB explorer Tool that we used the most was SIB Explorer. It is stand alone tool from IBM alphaWorks. Installation is simple and described here. Trickier part is downloading SWT libraries. I have in my swt dir (version number may vary)
  • org.eclipse.swt.win32.win32.x86_3.3.2.v3347a.jar
  • org.eclipse.swt_3.3.2.v3347.jar
  • swt-gdip-win32-3347.dll
  • swt-win32-3347.dll
The reason this tool is very handy is that everything is there and you don't need to click too much. If you like to see what messages are in what queue you just open queue points and there you have all queues with their current depth. However for putting new messages in queue it is not so great because you can't add any message property (for instance targetService for SOAP/JMS).

Service Integration Bus Performance

If you need to get some SIB performance related data this tool can be very useful. You can use it to monitor thread pools, queues, topic spaces, communication and data store in near real time (with refresh every 2s). We didn't use it much as we have ITCAM but data it provides can be used for performance tuning. Also you can detect some anomalies like messages with inadequate reliability level.

IBM Client Application Tool for JMS

If you need to experiment a lot with putting messages in queue than you should probably use this tool. It also come from IBM alphaWorks but it doesn't require SWT libraries. However this tool connects to WAS JNDI so you need to have JMS JNDI resources defined. Dan Zrobok has wrote how to connect to the WAS from this tool. Once you connect you can send and receive message (tabs Message Producer and PtoP Message Consumer). Very nice feature is registering new Message Listener. Window pops up for every new message that is deliverd to destination that listener listens to.

Hermes JMS

One more tool you can use for exploring SIB destinations and posting is Hermes JMS. It can be quite handy if you have (or wanna have) messages stored in files and use them for testing. Also you can save messages to file from destinations for later use. Unfortunately Hermes JMS doesn't come with SIB adapter (only with WebSphere MQ one) so you must set it up on your own. It isn't trivial but you can start with downloading "IBM Client for JMS on J2SE with IBM WebSphere Application Server" and installing it. There are also some resources on the web available describing the whole procedure.

Apache JMeter

Another tool that can be very useful is Apache JMeter. With JMeter you can send and receive P2P messages using JMS Point-to-Point sampler. Publish-Subscribe functionality is also available. I was using JMeter for performance testing and also for functional testing. It is really great because you can set up JMS test case and test your messaging infrastructure with it. To set it up connect to the WAS SIB, you will also need IBM Client for JMS on J2SE with IBM WebSphere Application Server. If you need instructions on any of these tools please reply and maybe I'll blog about it.

Tuesday, April 14, 2009

XML Validation - simple Groovy app runnig on Google App Engine

After announcemnt that Java is available on Google App Engine I was lucky enough to register and get account to try this exciting feature for us Java developers. Guillaume Laforge blogged about creating Google App Engine application in Groovy. As I was playing with Groovy/Grails lately I decided to make a simple GAE web app using Groovy.

The result is XML Validation application that basically consist of one Groovlet and one GSP page.

I must say that I was inspired by a simple but great Groovy web console app. Mostly in using CodeMirror for XML syntax highlighting. If you want to know more on Groovlets and GroovyTemplate (GSPs) I recommend that you read excellent article by Andrew Glover and Scott Davis on developerworks. I look forward to see all the great applications that will be deployed on GAE. Keep Grooving!

Friday, April 3, 2009

Hello World! REST service using Jersey and WebSphere Application Server v6.1 (WAS)

I was wondering how easy it is to create Hello World REST service using Jersey and deploying it to WAS 6.1. Long story short: It is really easy. So here are the steps:

  1. Download jersey-archive-1.0.2.zip from http://jersey.dev.java.net/.
  2. Extract jersey-archive-1.0.2.zip.
  3. Go to your favorite tool for WAS development. Mine was Rational Software Architect 7.5 (RSA) but the same steps works for 7.0.
  4. Create new Dynamic web project (HelloWorldRest). In RSA 7.5 you should choose WAS 6.1 as your target platform. Also choose Servlet spec 2.4.
  5. Copy jersey jars from lib folder. That’s the folder where you extracted jersey archive in step 2. Put them in the WEB-INF/lib folder.
  6. Now you must add Servlet configuration and mapping. You can do this through wizard or you can copy the following in web.xml just after display-name element:
    
     Jersey Servlet
     ServletContainer
     ServletContainer
     com.sun.jersey.spi.container.servlet.ServletContainer
    
    
     ServletContainer
     /resources/*
    
    
    With this in place we have configured Jersey servlet. It will serve REST services with pattern resources in URI.
  7. Now we can create service implementation class. We are creating simple POJO class (in JAX-RS term Root Resource Class) with one method like one below:
    /**
     * 
     */
    package org.example;
    
    import javax.ws.rs.GET;
    import javax.ws.rs.Path;
    import javax.ws.rs.Produces;
    import javax.ws.rs.QueryParam;
    
    @Path("/helloworld")
    public class HelloWorldResource {
    
     @GET
     @Produces("text/plain")
     public String sayHello(@QueryParam("world") String world) {
      return "Hello " + world;
     }
    
    }
    
    The interesting bits are four annotations:
    1. @Path("/helloworld") – this annotation exposes methods in this class through helloword path. Annotation value is the thing that we will add after resources in URI to call this service
    2. @GET – annotated method (sayHello) is available through HTTP GET method
    3. @Produces("text/plain") – method will return plain text
    4. @QueryParam("world") – with this annotation we are mapping URI parameter world to method parameter world
  8. Deploy project on server!
And that’s it. Now we can test service using browser. If you enter following URI: http://localhost:9080/HelloWorldRest/resources/helloworld?world=World! you should get response in clear text, as expected: Hello World!. Next we can create a simple stand alone client for this service. I have:
  1. Created a new Java project called HelloWorldRestJava.
  2. Created new folder called lib.
  3. Copied jars from WEB-INF/lib to lib folder. Added them to project classpath.
  4. Created new class with main method:
    package org.example;
    
    import com.sun.jersey.api.client.Client;
    import com.sun.jersey.api.client.WebResource;
    
    public class HelloWorldRestClient {
    
     public static void main(String[] args) {
      Client client = new Client();
      WebResource webResource = client.resource("http://localhost:9080/HelloWorldRest");
      String response = webResource.path("resources").path("helloworld")
        .queryParam("world", "World!").get(String.class);
      System.out.println("Response: " + response);
     }
    }
    
  5. Run the client as Java application.
If you do the same you should see Response: Hello World! in the console. Now when you saw how easy it is, you can continue to play with Jersey.