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:
- 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.
- Understand what specifications are supported by WAS7. A big difference is JDK 1.6 for example.
- 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.
- 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.
- 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.
- Redesign/code anything you need to change per the specs. Rebuild your app using JDK 1.6.
- If you are using RAD, create and configure a local test server. If you are not, download, install, and setup Websphere Developers Edition.
- Deploy your app to the server
- 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();
}
}
};
}
Hi, I am upgrading from 6.1 to 7 and everything works fine except the webservice calls. I am getting an error like this: javax.xml.soap.SOAPException: WSWS4119E: An attempt was made to set a SOAPHeaderElement that was not namespace qualified. The SOAPHeaderElement localName is AuthenticationInfo; prefix is : namespace is .
Do you have any idea how to fix this?
Thanks,
XZ
Without more context, hard to say. Sounds like something isn’t following the SOAP spec if it’s requiring a namespace qualifier. Perhaps you’re running into classpath conflicts with IBM’s internal web service classes. Can you paste the whole error/stack trace? I just had an issue making a SOAP call to an external web service using axis, but that was related to the JSSE security configuration and the SSL handshake failing.
for javax.xml.soap.SOAPException: WSWS4119E: An attempt was made to set a SOAPHeaderElement that was not namespace qualified.
in the jvm custom properties , declare com.ibm.ws.webservices.disableSOAPNamespaceValidation
value=true