Sunday, 1 November 2009

Installing Rational Software Architect Standard Edition 7.5.4 on Ubuntu 9.10

When installing Rational Software Architect Standard Edition 7.5.4 (and RAD 7.5.4) onto Ubuntu 9.10 it is likely that you might experience a few problems. This posting identifies these problems and their solutions.

The first is a missing library:
  • http://packages.ubuntu.com/jaunty/i386/libstdc++5/download
The second is an SWT error inside your initial workspace's .log file: /home/jsears/IBM/rationalsdp/workspace/.metadata, with: org.eclipse.swt.SWTError: XPCOM error.
  • sudo apt-get install xulrunner
  • sudo vi /opt/IBM/SDP/eclipse.ini with -Dorg.eclipse.swt.browser.XULRunnerPath=/usr/lib/xulrunner
The third problem is to do with GTK affecting various buttons such that a mouse click is not enough for the button to be dismissed. The answer to this is to invoke eclipse not by the main menu but via a .sh script (with an icon image of /opt/IBM/SDP/rsa_se/RSA_v7_32.xpm):
  • export GDK_NATIVE_WINDOWS=true
  • /opt/IBM/SDP/eclipse -product com.ibm.rational.rsastd.product.v75.ide
Only by carrying out these things was I able to start the IDE and use it as expected:

Friday, 4 September 2009

Using a WebSphere Scheduler

This posting demonstrates using a WebSphere Application Server Scheduler (tested in 6.0.2.35, but highly likely to be applicable upto 7.0) in the following way:
  1. Setting up a standard apache Derby database to hold the scheduler tables.
  2. Creating a WAS scheduler that is callable via JNDI (and uses tables in the derby database).
  3. Producing an .ear file containing three components: a servlet and two, minimalist, stateless EJB's that demonstrate the important scheduler API's.
  4. Invoking the API and seeing the expected output.
Code in the doGet of the servlet registers the EJB's with the scheduler. Doing this allows the scheduler to callback relevant methods either at the scheduled time or for when the state of the scheduled task changes...
  • The optional EJB uses a public void handleEvent(TaskNotificationInfo arg) method that gets invoked by the scheduler so that events related to the management of the scheduled task can be intercepted (if you want) by your business logic - e.g. a TaskNotificationInfo.PURGED notification.
  • The mandatory EJB implements a public void process(TaskStatus arg) method, that gets invoked by the scheduler and carries out your business logic.

Set up the Derby database

The SQL used for creating the derby tables, required by the scheduler, is shipped in the Scheduler folder - for me that was /home/jsears/IBM/WebSphere/7/AppServer1/Scheduler.

Basically I took the createSchemaMod1Derby.ddl file from my WAS 7 instance, created the database and then pointed my WAS 6.0 scheduler at it. I used this combination because RAD 6.0 and WAS 6.0 are my primary environments.

The .ddl has to be modified with some variable substitution, for example: "CREATE TABLE @TABLE_QUALIFIER@@TABLE_PREFIX@TASK ("TASKID" BIGINT NOT NULL ," became "CREATE TABLE TBLTASK ("TASKID" BIGINT NOT NULL ,". I saved the result in a derby.sql file.

From the command line (after downloading and extracting derby) I exported the following variables:
  • export DERBY_HOME=/home/jsears/local/tmp3/db-derby-10.5.3.0-bin
  • export CLASSPATH=$DERBY_INSTALL/lib/derbyclient.jar:$DERBY_INSTALL/lib/derbytools.jar:.
I then started the derby server:
  • java -jar $DERBY_HOME/lib/derbyrun.jar server start
I then ran the ddl file (via a new terminal with the export's):
  • java -jar $DERBY_HOME/lib/derbyrun.jar ij
  • connect 'jdbc:derby://localhost:1527//home/jsears/local/tmp3/MyDbTest;create=true';
  • run '/home/jsears/local/tmp3/derby.sql';
  • show tables;
I then set up security:
  • CALL SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY('derby.user.user1', 'password1');
  • CALL SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY('derby.connection.requireAuthentication', 'true');
  • disconnect;
  • connect 'jdbc:derby://localhost:1527//home/jsears/local/tmp3/MyDbTest;user=user1;password=password1';
  • exit;
Create The Scheduler
Through the WebSphere Administrative console I created the database stuff first and then the scheduler stuff:
  • Security > Global security > JAAS Configuration > J2C Authentication data > New ...
  1. Username and Password values as above, from derby setup, for jsears-desktopNode01/MyDerbyUID:
  • Resources > JDBC providers @ Server level > New ...
  1. Name = Derby JSEARS 01
  2. Class path = /home/jsears/local/tmp3/db-derby-10.5.3.0-bin/lib/derbyclient.jar
  3. Implementation class name = org.apache.derby.jdbc.ClientConnectionPoolDataSource
  • JDBC providers > Derby JSEARS 01 > Data sources > New ...
  1. Name = Derby Network Server DataSource
  2. JNDI name = jdbc/DerbyNSDS
  3. Component-managed authentication alias = jsears-desktopNode01/MyDerbyUID
  4. When created press the "Test connection" button!
  • JDBC providers > Derby JSEARS 01 > Data sources > Derby Network Server DataSource > Custom properties
  1. databaseName = /home/jsears/local/tmp3/MyDbTest
  2. serverName = localhost
  3. portNumber = 1527
  • Resources > Schedulers @ Server Level > New ...
  1. Name = MyScheduler
  2. JNDI name = sched/MyScheduler
  3. Data source JNDI name = jdbc/DerbyNSDS
  4. Data source alias = jsears-desktopNode01/MyDerbyUID
  5. Table prefix = tbl
  6. Work managers = Default Work Manager
  7. When completed press the "Verify tables" button!
Use the API's
The servlet looks like this, in my mind the important bit is how the call backs are registered:

The first EJB is the optional one:

And here is the mandatory EJB:

What is most important is how the deployment descriptor looks (take into account that this was coded in a RAD 6 IDE). In particular how the tag values mean that these interfaces do not have to be coded in java.

NOTE: use the following in RAD as the JDBC Driver class if you want to connect RAD to derby: org.apache.derby.jdbc.ClientDriver

Invoke the API
Figure out what the appropriate BOOTSTRAP_ADDRESS + WC_defaulthost ports are of the servlet:
  • Servers > Application Servers > server1 > Ports
And then call the servlet:
  • http://127.0.0.1:9081/SchedWebApp/Main/
Finally, you should end up with something like this:

Friday, 10 July 2009

Updating / Patching WebSphere Application Server

Figure out which fixpack you want by visiting the IBM Recommended fixes for WebSphere Application Server page.

Next visit the IBM Maintenance Download Wizard for WebSphere Application Server V7.0 site and download the maintenance wizard:

With the Wizard, once you have extracted and installed it, you'll load the fixpack and basically patch your existing WebSphere install. For me, on Ubuntu 9.04, it was a straight forward process for both my 6.0 and 7.0 installs.

Friday, 3 July 2009

JavaMail on WebSphere

Creating a mail resource - whereby you use JNDI to get a context that you send email through - is surprisingly easy in WebSphere, at least for my minimal requirements :-)

I reused the Built-in Mail Provider @ server level:

...and then created my own mail session:

Mail Providers > Built-in Mail Provider > Mail Sessions

  • Name = MyMailSession
  • JNDI name = mail/MyMailSessionMail
  • transport host = 192.168.192.5
  • Mail transport user ID = wiki
  • Mail transport password = wiki
  • Enable debug mode = ticked

Next I created a very simple servlet, whose doGet method grabs the JNDI context and then uses the JavaMail API to send an email:

I pulled in the JNDI reference straight from the web container, but I could have used an environmental reference from the web.xml file:

Because the SMTP debugging was on I got output that looked like the following and that resulted in an email being sent to me :-)

NOTE: a useful reference is at http://www.ibm.com/developerworks/websphere/library/techarticles/0310_fung_yu/fung_yu.html

Creating & Referencing a JDBC JNDI Data Source

Here is how to create & reference a MySQL data source in WAS - one that can be retrieved using JNDI and features connection pooling. An example of how to call the data source, from a simple .war application running in the local container is also shown.

NOTE:
  • The instructions below apply to WebSphere Application Server 6.0.2.35 on Ubuntu 9.04, however I've also tested them successfully on in i5 WAS V6.1.0.11 Express instance - but bear in mind that some of the steps are slightly different (easier) due to the more modern version of WAS (best used via IE6 as the client IMO!)
Create The Data Source
1. Resources > JDBC Providers @ Server level (the default for all of these instructions) > New...
  • For General properties I used "User-defined"
After clicking Next I provided the following details
  • Name = MySQL JDBC Provider
  • Class path = ${USER_INSTALL_ROOT}/mysql/mysql-connector-java-5.1.8-bin.jar - this equated to /home/jsears/IBM/RAD-6.0/runtimes/base_v6/profiles/AppSrv01/mysql
  • Implementation class name = com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource
2. Security > Global security > JAAS Configuration > J2C Authentication data > New
  • Alias = MySQLUID - WAS renamed this to jsears-desktopNode01/MySQLUID
  • User ID = root
  • Password = mysql
3. Resources > JDBC providers > MySQL JDBC Provider > Data sources > New
  • Name = MySQL
  • JNDI name = jdbc/MySQL
  • Component-managed authentication alias =jsears-desktopNode01/MySQLUID
4. Resources > JDBC providers > MySQL JDBC Provider > Data sources > MySQL > Custom Properties
  • databaseName = bugs - I referenced a BugZilla install on a separate server
  • port = 3306
  • serverName = 192.168.192.110
5. Resources > JDBC providers > MySQL JDBC Provider > Data sources > MySQL > WebSphere Application Server data source properties
  • Statement cache size = 10
  • Pretest connections = ticked
6. Resources > JDBC providers > MySQL JDBC Provider > Data sources > MySQL > Test connection
  • NOTE: first restart WAS!
Reference The Data Source
1. Create a simple Servlet, with a doGet method, and flesh it out - the important thing will be the JNDI reference line:
  • DataSource ds = (DataSource) ctx.lookup("java:comp/env/MySQLResourceReference");
2. Against the web.xml deployment descriptor, using RAD, I added the Resource Reference to a data source:

Thus, after writing a very simple doGet I ended up with the following container based servlet that called the JNDI reference via indirection in the web.xml deployment descriptor:

I accepted all the defaults when uploading the .war - including the "Map resource references to resources" options, as I had already defined the details previously:

The URL I used, once the application was started, to invoke this servlet was: http://127.0.0.1:9081/ReferenceJNDIdataSource/ReferenceJNDIdataSource

Monday, 29 June 2009

Message Driven Beans in WebSphere Application Server 6+

Creating a basic Message Driven Bean is quite straightforward, the hard part is setting up the WebSphere Application Server embedded JMS details and making sure your deployment references the correct details.

An MDB is invoked asynchronously when a JMS message is put on a destination. The destination needs to be known before deployment as the soon to be created .EAR, holding our MDB, contains a deployment descriptor - ejb-jar.xml - that references the destination. Part of the deployment process, via the WebSphere Administrative Console, also references a JMS activation specification that can be said to be part of setting up the embedded JMS.

Set up WAS embedded JMS
1. Create a new Service Integration Bus, called "B1":
  • Service Integration > New > accept all defaults
2. Assign "B1" to the Server, accepting all the defaults:
  • Service Integration > Buses > B1 > Bus members
3. On "B1" create a destination, "Q1", accepting all defaults:
  • Service Integration > Buses > B1 > Destinations > New > Queue
4. Create a new JMS queue, accepting all defaults unless shown below:
  • Resources > JMS Providers > Default messaging provider @ Server level > JMS queue
  • Name = JMS_Q
  • JNDI name = jms/JMS_Q1
  • Bus name = B1
  • Queue name = Q1
  • Delivery mode = Persistent
5. Create a new JMS connection factory, accepting all defaults unless shown below:
  • Resources > JMS Providers > Default messaging provider @ Server level > JMS connection factory
  • Name = JMS_CF1
  • JNDI name = jms/JMS_CF1
  • Bus name = B1
6. Create a new JMS queue connection factory, accepting all defaults unless shown below:
  • Resources > JMS Providers > Default messaging provider @ Server level > JMS queue connection factory
  • Name = JMS_QCF1
  • JNDI name = jms/JMS_QCF1
  • Bus name = B1
7. The final part is creating an activation specification:
  • Resources > JMS Providers > Default messaging provider @ Server level > JMS activation specification > New
  • Name = JMS_AS1
  • JNDI name = eis/JMS_AS1
  • Destination Type = Queue
  • Destination JNDI name = jms/JMS_AS1
  • Bus name = B1
8. In order for WAS to recognise the JMS details we've just created unfortunately we need to restart WAS.

Use RAD to construct a very simple MDB & deploy it
1. You'll end up with 3 very small projects, the key files are the ejb-jar.xml deployment descriptor...
...and the bean itself (notice the onMessage method I've fleshed out)

2. Deploy the .EAR file and provide the following information for the activation specification of:
  • JNDI name = eis/JMS_AS1
  • Destination JNDI Name = jms/JMS_Q1
3. Test the MDB is listening by sending a message with the Universal Test Client:
  • http://localhost:9081/UTC/initialize?port=2810&wasAdminPort=2810&wasAdminConn=RMI > Utilities > Send JMS Message
  • Queue JNDI Name = jms/JMS_Q1
  • Queue CF JNDI Name = jms/JMS_QCF
  • Message = hello world
  • if the MDB is not deployed then look in: Buses > B1 > Destinations > Q1 > Queue points > Q1@jsears-desktopNode01.server1-B1 >
  • else, look in the console window (as we had System.out logging there from the MDB):

log4j and WebSphere

Porting an application from Tomcat 5+ to WebSphere 6+ raises the question: what about the log4j log file? The following simple application demonstrates porting from one to the other with the minimum of hassle.

The first step is to create a minimal servlet application in the IDE (unless otherwise stated, accepting all the defaults):


I used the rather ancient Rational Software Development Platform as my IDE:

However, the project can just as easily be created / imported in RAD 7.5.n (or a non Rational version of eclipse):


My Servlet looked like this:

package jsears;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.Servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;

/**
* Tomcat = http://127.0.0.1:8080/log4j/main
* WebSphere = http://127.0.0.1:9080/log4j/main
*
* @author jsears
*
*/
public class Main extends HttpServlet implements Servlet {
private static final long serialVersionUID = 233300306772977426L;

protected static final Logger logger = Logger.getLogger(Main.class);

private static String sessionId = null;

public static synchronized String getSessionId() {
return Main.sessionId;
}

protected void doGet(HttpServletRequest arg0, HttpServletResponse arg1)
throws ServletException, IOException {
sessionId = arg0.getSession().getId();

logger.debug(sessionId);

PrintWriter out = arg1.getWriter();
out.println(sessionId);
out.close();
}
}

The only library I added to the project was log4j that I downloaded from http://logging.apache.org/log4j/1.2/index.html.

I also created a second class, inherited from PatternLayout, that allows me to see the sessionId for each client in a single log file. Its not needed for getting lo4j to work, just that its a handy class to keep track of in this blog :-)

package jsears;

import org.apache.log4j.PatternLayout;
import org.apache.log4j.spi.LoggingEvent;

public class HelperLayout extends PatternLayout {
StringBuffer stringBuffer = new StringBuffer(128);

private String getSessionId() {
return Main.getSessionId() + ": ";
}

public void activateOptions() {
return;
}

public String format(LoggingEvent event) {
return getSessionId() + super.format(event);
}

public boolean ignoresThrowable() {
return true;
}
}

Finally, I added the following two files - so that they were on the classpath and ended up inside WEB-INF/classes:
  • commons-logging.properties
# Set application classloader mode as PARENT_LAST when deploying in WAS as .ear
priority=1
org.apache.commons.logging.LogFactory=org.apache.commons.logging.impl.LogFactoryImpl

  • log4j.properties
# HIERARCHY: ALL > DEBUG > INFO > WARN > ERROR > FATAL > OFF

# Everything ###############################################################
#log4j.rootCategory=OFF, file

# application ###############################################################
log4j.logger.jsears=ALL, out, file

# Get rid of various Tomcat "WARN No appenders" complaints
log4j.logger.org.apache.catalina=OFF

# Appender definitions ########################################################
log4j.appender.out=org.apache.log4j.ConsoleAppender
log4j.appender.out.target=System.out

log4j.appender.file=org.apache.log4j.RollingFileAppender
log4j.appender.file.MaxFileSize=5MB
log4j.appender.file.MaxBackupIndex=5

# Tomcat
#log4j.appender.file.File=${catalina.home}/logs/log4j.log

# WAS - e.g. use this line when deploying into WAS
log4j.appender.file.File=${LOG_ROOT}logs/log4j.log

# Appender layouts ##########################################################
log4j.appender.out.layout=jsears.HelperLayout
log4j.appender.out.layout.ConversionPattern=%-5p: %d{dd MMM yyyy HH:mm:ss,SSS}: %C{1},%L: %m%n

log4j.appender.file.layout=jsears.HelperLayout
log4j.appender.file.layout.ConversionPattern=%-5p: %d{dd MMM yyyy HH:mm:ss,SSS}: %C{1},%L: %m%n

Depending on where you are porting the application to - from WebSphere to Tomcat, or vice versa - then you need to comment out the appropriate Tomcat or WAS line in the log4j.properties file.

I did not bundle the servlet into an .ear file - instead I specified the context when I uploaded / installed it into WebSphere:

Specifying a .war context in WebSphere Application Server 6.0.2.33

Specifying a .war context in WebSphere Application Server 7.0.0.0 ND

I exported the .war file from the IDE and have successfully deployed it in WAS 6 through to WAS 7 as well as Tomcat 5.5.27 - all running on Ubuntu 9.04. The only change that I needed to make was in the log4j.properties file - uncommenting / commenting out the appropriate file appender line.

In WebSphere the logfile will appear in your profiles folder - e.g. AppServer1/profiles/AppSrv01/logs. Similarly, in Tomcat it will appear in the logs folder.

NOTE: A useful reference to this is at http://wiki.apache.org/jakarta-commons/Logging/FrequentlyAskedQuestions