Feeds:
Posts
Comments

Archive for the ‘Technology’ Category

If you are looking to create a portlet that accesses a non-liferay database, follow these instructions. I am using the Liferay 6.0.x Tomcat bundle with the eclipse ide plugin to create a portlet that accesses a db2 database. The main lportal database is living in mysql.

My service.xml file looks like this:

<?xml version=”1.0″ encoding=”UTF-8″?>
<!DOCTYPE service-builder PUBLIC “-//Liferay//DTD Service Builder 6.0.0//EN” “http://www.liferay.com/dtd/liferay-service-builder_6_0_0.dtd”&gt;
<service-builder package-path=”com.aonhewitt.benit.gmc.services”>
<author>Rtbaird</author>
<namespace>mynamespace</namespace>
<entity name=”MailboxItem” local-service=”true” remote-service=”false” data-source=”zzzDataSource” table=”mailboxitem”>
<column name=”mailboxitemid” type=”String” primary=”true” />
<column name=”mailboxid” type=”String” />
<column name=”publicationdate” type=”Date” />
<column name=”docdesc” type=”String” />
<order by=”asc”>
<order-column name=”publicationdate” />
</order>
<finder name=”MailboxId” return-type=”Collection” >
<finder-column name=”mailboxid” />
</finder>
</entity>
</service-builder>

The key here is the data-source attribute on the entity. I will need to define this datasource in spring files. Once you run the service builder, take a look at the service.properties file generated in your source directory. You’ll see references to all the spring-configs files which includes an extension file listed at the end for WEB-INF/classes/META-INF/ext-spring.xml. This is where you will put your spring file overrides. You’ll need to define your data source here as well as override the hibernate session bean.

<bean>
<property name=”location”>
<value>/WEB-INF/jdbc.properties</value>
</property>
<property name=”placeholderPrefix” value=”${jdbc.” />
</bean>
<bean id=”zzzDataSource”>
<property name=”driverClassName” value=”${jdbc.xxx.driverClassName}” />
<property name=”url” value=”${jdbc.xxx.url}” />
<property name=”username” value=”${jdbc.xxx.username}” />
<property name=”password” value=”${jdbc.xxx.password}” />
</bean>
<bean id=”liferayHibernateSessionFactory” class=”com.liferay.portal.spring.hibernate.PortletHibernateConfiguration”>
<property name=”dataSource” ref=”zzzDataSource” />
</bean>

Here I’ve defined a property placeholder which allows you to specify the jdbc properties in a file called jdbc.properties. This file should be created in the WEB-INF directory and look like this. Notice “jdbc” was left off (since the property placeholder defined the prefix):

xxx.driverClassName=com.ibm.db2.jcc.DB2Driver
xxx.url=jdbc:db2:///SCHEMA
xxx.username=username
xxx.password=password
xxx.defaultAutoCommit=false

Now you’ve defined the datasource, defined the database connection properties, and overrode the hibernateSessionFactory to use this data source (main session factory definition is in the hibernate-spring.xml file).

So to recap:

  • service.xml defines your service and what datasource to use for a given entity/table
  • [run service builder]
  • service.properties defines your spring override file – you shouldn’t need to change this
  • ext-spring.xml (you need to create) defines the spring overrides including the hibernateSessionFactory, datasource bean, and property placeholder bean
  • jdbc.properties defines the database connection properties

After publishing my portlet to Tomcat, it is pulling data from an external DB2 database.  Notice I’ve said nothing about creating a datasource inside of Tomcat itself for this database connection.  As surprising as that is, it doesn’t seem to be needed.

Read Full Post »

I’ve received a couple questions regarding the overall process/steps to follow to migrate.  Hopefully this will help clarify the overall process one should follow to get your apps running on Websphere 7.0.

First, review this developerworks migration guide.  It covers most of what you’ll need to do.

I’ll supplement this with calling out the following steps specifically:

  1. If you’re using WSAD/RAD as your IDE, you’ll need to migrate your J2EE projects.  There is a migration guide within RAD 7.5.  Read it, make sure you understand it, and follow it.
  2. Understand what specifications are supported by WAS7. A big difference is JDK 1.6 for example.
  3. Read and understand the specs you are using.  If you have a basic web app, understand the servlet spec.  If you use EJBs, read the EJB spec.  JMS?  Same.  A basic understand of how a servlet or jsp works is not a replacement for understanding the entire specification.  There are many details that should be understood beyond the basics, if nothing else for educational purposes.  If you don’t understand the “rules”, it’s hard to play the game.
  4. Understand your application.  This refers to what pieces of the J2EE specification your application uses, and if you are doing anything in your application that isn’t supported by the specification(s).  I ran into this with creating threads to process work in parallel.  I’ve posted details below.  This will help you identify what areas of your application you need to change.  If you follow the specs, deploying is much easier.
  5. Understand your dependencies.  For example, if you rely on a specific version of some open source libraries, make sure they are supported by JDK 1.6.  Some libraries (bouncycastle for example) have different versions depending on the JDK you’re using.
  6. Redesign/code anything you need to change per the specs.  Rebuild your app using JDK 1.6.
  7. If you are using RAD, create and configure a local test server.  If you are not, download, install, and setup Websphere Developers Edition.
  8. Deploy your app to the server
  9. Thoroughly test every part of your application.  If your app is complex, the odds are good you’ll have missed something.  The only way to ensure it works is to run it.

One thing I ran into mentioned above was an issue related to creating our own threads to process work in parallel, or fire off background processes to load data the application uses.  The servlet spec prohibits applications from creating their own threads and accessing JNDI resources.  Websphere 6 (and prior) allows this.  Websphere 7 now enforces it, so some of our processes would fail because the threads performing work (JDBC calls for example) weren’t managed by websphere. Here’s the exception:

[3/22/10 10:18:51:968 CDT] 00000034 SystemOut     O javax.naming.ConfigurationException: A JNDI operation on a “java:” name cannot be completed because the server runtime is not able to associate the operation’s thread with any J2EE application component.  This condition can occur when the JNDI client using the “java:” name is not executed on the thread of a server application request.  Make sure that a J2EE application does not execute JNDI operations on “java:” names within static code blocks or in threads created by that J2EE application.  Such code does not necessarily run on the thread of a server application request and therefore is not supported by JNDI operations on “java:” names. [Root exception is javax.naming.NameNotFoundException: Name comp/env/jdbc not found in context “java:”.]

Websphere allows you to process parallel work by using it’s Asynchronous Beans facility.  To get our app to work, we created a work manager utility class to manage the threaded work within the container’s context.  Instead of calling Thread.start(), call MyWorkManager.start(<runnable>,).  This will submit the runnable work to the Websphere work manager for execution on a separate thread pool thread.  That work manager will need to be configured in the Websphere admin console.  Here’s the code for our utility class:
import javax.naming.InitialContext;
import com.ibm.websphere.asynchbeans.Work;
import com.ibm.websphere.asynchbeans.WorkItem;
import com.ibm.websphere.asynchbeans.WorkManager;

public class MyWorkManager
{
/**
* static reference to work manager
*/
private static WorkManager sManager = null;

/**
* Indicator for initialized
*/
private static boolean sInitialized = false;

/**
* Only public entity. Send Thread/Runnable to this method to launch
*
* @param aRunnable Thread to run
* @throws Exception
*/
public static void start(Runnable aRunnable) throws Exception
{
new MyWorkManager(aRunnable, false);
}

public static void start(Runnable aRunnable, boolean isDaemon) throws Exception
{
new MyWorkManager(aRunnable, isDaemon);
}

/**
* Returns/initialized reference to WorkManager
*
* @return WorkManager
*/
private static WorkManager getWorkManager()
{
if ( sInitialized == false )
{
sInitialized = true;
if(sManager == null)
{
try
{
InitialContext ctx = new InitialContext();
String jndiName = “wm/myworkmanager”;
if ( jndiName != null && jndiName.length() > 0 )
{
sManager = (WorkManager)ctx.lookup(jndiName);
}
else
{
//log error
}
}
catch(Exception ex)
{
throw ex;
}
}
}
return sManager;
}

/**
* Private constructor. Calling this starts the thread in the appropriate manner
*
* @param aRunnable
* @throws Exception
*/
private MyWorkManager(Runnable aRunnable, boolean isDaemon) throws Exception
{
WorkManager wm = getWorkManager();
if ( wm != null )
{
ThreadWorker tw = new ThreadWorker(aRunnable);
WorkItem wi = wm.startWork(tw, isDaemon);
}
else
{
throw new Exception(“Unable to retrieve WorkManager”);
}

}

/**
* Work wrapper for the underlying Runnable thread
*
*/
public class ThreadWorker implements Work
{
/**
* Reference to Runnable object
*/
private Runnable mChild;

/**
* Constructor
*
* @param aRunnable Runnable object
*/
public ThreadWorker(Runnable aRunnable)
{
mChild = aRunnable;
}

/* (non-Javadoc)
* @see javax.resource.spi.work.Work#release()
*/
public void release()
{

}

/* (non-Javadoc)
* @see java.lang.Runnable#run()
*/
public void run()
{
if ( mChild != null )
{
mChild.run();
}
}

};
}

Read Full Post »

The application I manage at work is a client/server application written entirely in java.  My company for years has been an IBM shop, so we have a large Websphere presence which is where the server is deployed.  The application had been running on Websphere 5.1 for a few years and was fairly recently migrated to Websphere 6.0 to remain on a supported version of Websphere.  Because the end of life for Websphere 6.0 is September 2010, we’re starting to plan for another upgrade now (we have major releases in January and June, so we’re targeting the June ’10 release for the upgrade).  Websphere 6.1, if IBM holds to it’s pattern of every 2 years or so will remain supported until September 2012, however there’s no current end of life date documented yet (link).  To get the longest life possible, I’m looking at Websphere 7.0 as the target platform for our June ’10 upgrade.

We have RAD 7.5 in house and a couple members of my team have installed it.  I’ve been working on getting a local WAS 7.0 server up and running and getting our app deployed on it.  There are some major differences between Websphere 5.1/6.0 and 7.0.  I won’t go into details as those are readily available on IBM’s website, but would like to share some of my observations and pain so far.

Application Background: The server side of our application is effectively broken down into 2 pieces.  One component is what we call a provision server that is essentially a cache of configuration data read from DB2.  This configuration information contains rules which drive how the second component operates.  The second component is the main workhorse app which receives a request, and creates a response based on configuration data retrieved from the provision server (if necessary) and data retrieved from any number of other applications we interface with.  We have 2 provision server jvms for load balancing and fail over and roughly 20 app engine jvms spread across 2 data centers (the app engine hosts roughly 3500 end users and we target 200 users per jvm…roughly).

Unsolved Problem 1 – Remote EJB calls across separate local jvm/profiles doesn’t work: Now that you have a high level view of our applications architecture, here’s my first dilema which I haven’t found a solution to.  Websphere now has the concept of profiles.  Basically a profile equates to a jvm instance.  It’s a little more than that, but that’s a good enough understanding for now.  So if you want 2 distinct/separate JVMs configured differently, you would need to create 2 profiles and create servers associated with each profile.  In all our lifecycles, we have distinct jvms setup for provision and app engine – we don’t cluster the app engine with the provision server because we want our dev/test lifecycles to mirror production, and production is separate because we don’t want a 1:1 correlation of provision server to app engine as the provision server is memory intensive and 2 jvms can handle the entire app engine load very effectively.  So I want to replicate that with my RAD 7.5 setup – 1 app engine jvm and 1 provision server jvm running locally within RAD 7.5.  That requires 2 separate profiles to be created, then a server defined and associated for each one.  No problem.  Where I run into problems is at runtime.  The app engine makes remote (cross-jvm) EJB calls to the provision server.  That requires a JNDI lookup of an EJB remote home object.  For some reason, jvm 1 cannot see any JNDI objects that are stored in jvm 2.  When I do an initial context and dump out the contents, all I ever get are the local JVM’s name server items.  But if I point the local server at one of our test lifecycle provision servers, it sees those just fine.  I have no idea why 1 local jvm can’t access another local jvm’s name server.  I’m not sure if it’s because of the base version of Websphere that’s running, or some other limitation of the development environment, but that is one hurdle I can’t get over.  So my workaround is to just deploy the provision server and app engine in the same jvm as local ejb calls work just fine.

Solved Problem 2 – creating a secure socket for an outbound ssl SOAP request: The app engine is a portal of sorts.  It will call any number of external systems to retrieve data and aggregate that data as needed based on the request.  There are several system we currently interface and several protocols we use to do so…SOAP over SSL, EJB, JDBD for example.  We use apache soap (old, but still works) to call several external systems, one of which is the main system we interface with.  In Websphere 5.1 and 6.0, we set our own JKS truststore for the request using the javax.net.ssl.truststore property.  This truststore contains the SSL certificates of our target URL.  It just worked.  Now we move to Websphere 7.0 and the same requests which work in a local WAS 6.o server no longer work.  After much digging and reading of documentation, it turns out WAS 6.1 (and 7.0) changed how SSL security was handled.  Long story short, when WAS sees a secure socket being created, it assumes responsibility for securing that connection (Big Brother?) instead of letting you do your own thing.  Now, there are ways around it, but the point is it is NOT backwards compatible.  The quick fix for this was to put the SSL certs in Websphere’s default truststore (go to the admin console, under security and then ssl configuration and you can find a whole bunch of related config).  There are several articles on this and I highly recommend reading the Websphere Application Server V7.0  Security Guide for background on this.  It is extremely helpful.

These are 2 of the biggest pain points I’ve hit so far, but I have a ways to go before I can say the app is fully certified on Websphere 7.0.  If I run into any more issues, I’ll update this post.

Oh, and before I forget to mention, when migrating from RAD 6 to RAD 7+, don’t forget to MIGRATE your JEE projects.  There are project metadata differences between the 2 which aren’t compatible.  Found this out the hard way.

Read Full Post »

One of the projects I’m working on requires the securing of all the servers and transports used in a message flow involving a JEE/Websphere MQ/Lotus Notes SMTP server infrastructure.  The javamail portion is a standalone java app running on Solaris which is triggered by MQ (not running within Websphere).  The message flow looks something like this:

Webapp running on websphere 5.1 -> MQ -> Transformation (MQ triggered standalone java app on Solaris) -> MQ -> Javamail (MQ triggered standalone java app on Solaris) -> SMTP -> external

The Javamail to SMTP server hop is secured via TLS (Transport Layer Security) using the SSLv3 protocol.

At first it seemed fairly straightforward. The documentation for javamail states that it does support SSL and TLS, however another developer on my team spent 2 days trying to get it to work, we discovered how poorly javamail is documented, in particular getting a secured connection using TLS and SSLv3 to work. Several websites found via google searches discuss it, but none seem to have a working example. One site talks about creating a custom SSLSocketFactory (not needed), and a couple others simply recommend reading the Javamail FAQ and SSLNOTES.txt that come with the javamail download. I found the SSLNOTES.txt to be most helpful, but did not provide working examples or the detail necessary to allow for a quick implementation. It still took a lot of tweaking to get a working solution, so I am posting it here for future reference as well as to help others who need to provide similar capabilities.

The key was setting the correct properties and specifying the correct protocols to use.


/**
* This method sends an email using TLS
*
* @param strTo To Addresses
* @param strCc CC Addresses
* @param strFrom From Address
* @param strSub Subject
* @param strMsg Message
*
* @throws IOException Description
*/
public void SendMailTLS(String strTo, String strCc, String strFrom,
String strSub, String strMsg)
throws IOException
{

//Set the properties required for TLS/SSL handshake
Properties props = new Properties();
System.setProperty(“javax.net.debug”, “ssl,handshake”);
props.put(“mail.smtp.host”, “<put your smtp server here>”);
props.put(“mail.smtp.starttls.enable”, “true”);
props.put(“mail.smtp.ssl.protocols”,”SSLv3 TLSv1″);

Session session = Session.getInstance(props);

session.setDebug(true);

//start sending the messages
try
{
//Instantiate new mime message and fill it with the required info
Message msg = new MimeMessage(session);

//set From
msg.setFrom(new InternetAddress(strFrom.trim()));

//set To
InternetAddress address[] = { new InternetAddress(strTo.trim()) };
msg.setRecipients(Message.RecipientType.TO, address); //To Recipients
msg.reply(false);

//set CC
if (!strCc.equals(“”))
{
InternetAddress address1[] = { new InternetAddress(strCc) };
msg.setRecipients(Message.RecipientType.CC, address1); //CC Recipients
}

//set Subject
msg.setSubject(strSub);

//setDate
msg.setSentDate(new java.util.Date());

//set Text
msg.setContent(strMsg, “text/html”);

// hand the message for delivery
Transport.send(msg);

}
catch (MessagingException mex)
{
System.out.println(“Mail Couldn’t Send to : ” + strTo + “ERROR: ” + mex.toString());
mex.printStackTrace();
}
}

Read Full Post »

Like the many other iTunes users who downloaded iTunes 7.x.x, I have been bitten by the faulty software bug. Since upgrading to version 7, my music library sounds like someone is playing track and field with the play and pause buttons. Being a software developer myself, I can’t fault Apple for releasing software that isn’t flawless. It is near impossible to create bug-free software. So something broke in version 7. It happens. The big issue I have with Apple is that we’re on the second patch release 7.0.2 and the problem still has not been fixed. I know they’re getting the feedback based on the number of hits from a google search of “iTunes skips“.  What are they fixing in the patches? It can’t be that hard to compare 6.0.5 with 7 to figure out what might be the problem. It is interesting to me how simply refreshing a web page in Firefox causes iTunes to start regurgitating? It has turned my music library into a garbled, skipping, pile of inaudible bytes.

I have tried the various suggestions on the web like changing your iTunes volume and doing the 16 bit thing, all to no avail. The only thing that works on my computer is reverting to version 6.0.5. Because I expect to have to do this again when the next patch comes out, I thought I’d post the instructions on how to reinstall 6.0.5 for future reference. Hopefully this won’t be needed for 7.0.3, but I’m not holding my breath.

Step 1: Back up your iTunes 7 settings, so that you can keep them around in case you want to go back.

Go into your My Documents folder, then your My Music folder. Copy the iTunes folder inside there to somewhere else. That’ll save your settings.

Step 2: Uninstall iTunes 7. Reboot as it asks you to when it’s done.

Step 3: Download iTunes 6.0.5 from Apple.

Step 4: Install iTunes 6.0.5 by running the installer.

Step 5: Launch iTunes 6. You should get this error message:

The file “iTunes Library.itl” cannot be read because it was created by a newer version of iTunes.

Step 6: Restore your old library.

Go into the My Documents/My Music/iTunes folder. Rename your iTunes Library.itl as iTunes Library.itl.old. Go into the Previous iTunes Libraries folder (MyDocuments\MyMusic\Previous iTunes Libraries). Take the newest dated file and copy it back up to the iTunes folder. Rename it iTunes Library.itl. Run iTunes 6 and you should be all set, with your library restored.

Read Full Post »