Monday, June 16, 2008

DZone Refcardz

I haven't been spending as much time on DZone as I used to (or want to), so I just read about this. It's not breaking news, but I thought it was something worth sharing in case you haven't heard of these yet either.

DZone has begun publishing Refcardz. These are cheat sheets for developers and other technical professionals on various technologies. Refcardz cover things like IDEs or even patterns from the GoF book. It appears they're being released at a rate of once a week, so I'm sure if there isn't one you're interested in yet, it won't be too long. Just subscribe to the feed and keep an eye out.

Friday, June 13, 2008

CXF vs OC4J ... Round 2

Security is a big deal in our deployment environment and one thing being used is all HTTPS connections require Mutual Authentication. This past sprint, one story I worked on involved reproducing the mutual authentication requirement on a mock service implementation in our local test environments (so we're as close as possible to the real deal). This is the same service I talked about last time; one that we're using CXF to create a mock implementation of and client for, from the provided WSDL.

I began by enabling server authentication only, which went well and took no time at all. However, enabling the client authentication threw a huge wrench into the mix. Seriously, the stars had to align to hit us with this one.

The error: Attempting to invoke the service returns a 405 Method Not Allowed and your Apache error log shows SSL Re-negotiation in conjunction with POST method not supported


  • Condition 1: The service you're hitting requires client authentication via an SSL Certificate

  • Condition 2: When using the CXF Client, you point it at the live WSDL
    • When generating client code from a WSDL, by default, the client's default constructor will use the path on the file system to the WSDL; alternatively, another constructor takes the WSDL location as a parameter
    • Details here


  • Condition 3: The service is invoked through Apache; a version lower than 2.2.0.
    • A common setup is Oracle Application Server with Oracle HTTP Server (Apache)

  • Condition 4: You're not in control of the box where the service is deployed



Basically, CXF is initializing the connection with a GET request to retrieve the WSDL. Following this GET, CXF makes a POST request to invoke the service. Switching from a GET to a POST is causing the error. We thought for a minute that if necessary, we could copy the WSDL to the file system (WEB-INF/wsdl/ maybe?) and therefore, CXF wouldn't perform the GET. Then we realized, when CXF parses the WSDL, it retrieves any imports it finds. If one of those is a resource (custom XSD for example), it must perform a GET to retrieve that from the server.... leaving you right back at square one.

We temporarily abandoned our effort here. We need to be 100% sure that the Oracle HTTP Server in our deployment environment hasn't been patched. We'll approach the group that owns the service we're integrating with and see what their thoughts are and whether or not they've had the same issue (this service is still in development). Hopefully we can resolve this w/o moving WSDLs and XSDs to the file system and creating a maintenance nightmare.


Notes:

CXF vs OC4J ... Round 1

My deployment environment was recently switched to Oracle Application Server with Oracle Http Server (OC4J + OHS). Currently, our primary focus is integration with some external SOAP Web Services and we've been using the Apache CXF Project to generate a mock implementation of the service as well as a client from the WSDL.

I'm well aware of common pains of switching between JEE Application Servers, having worked with WebLogic, GlassFish v2, JBoss, and now OC4J. There's the initial learning curve for things like auto/hot-deployment directory, automated deployment w/in your build, getting to know the admin console, and log locations. Unfortunately it's never just that easy. You always end up running into issues around configuration differences and sometimes terrible class path and version nightmares.

The worst part of porting our applications to OC4J was most definitely deploying our Mock Service Implementation and CXF Clients. It's funny, after hitting the first CXF deployment issue I found myself at the CXF App Server Guide. A quick glance down the page indicates I'm in for quite the ride.

I found that in the end, a little more than half of the information on this page was correct... but not everything. Here are the differences I ran into. (Note: I hope I'm capturing everything, I meant to write this a month ago, during the time I was running into these issues, but never got around to it)

1. Shared Libraries and Deployment
I completely skipped the sections Replace the Oracle XML parser with Xerces and Deploying Applications Section.
I ended up having to make a number of modifications to the -Xbootclasspath/p: Java Option inside opmn.xml and by the time it was over and done with, managing shared libraries was unnecessary.

2. Setting System Properties
No matter what I did, OC4J gave me an implementation of javax.xml.parsers.DocumentBuilderFactory that would break CXF. So, I did end up setting a System Property (I know, I know ...). When using CXF to stand up a service, your web.xml will need to identify a listener as such:


<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>

So, I wrote my own ContextLoadListener that extends this one (and modified the web.xml to point to mine). It's just a pass-through, simply making a call to the same method on the listener I'm extending. However, in the contextInitialized method, I set the system property just before calling the super class.

public void contextInitialized(ServletContextEvent event) {
System.setProperty("javax.xml.parsers.DocumentBuilderFactory",
"org.apache.xerces.jaxp.DocumentBuilderFactoryImpl");
super.contextInitialized(event);
}


In the end...
  1. I Followed these Sections from the CXF App Server Guide:

    • Preparing stax-api

    • Get rid of OC4J JAX-WS libraries

    • swapping Oracle wsdl.jar with wsdl4j.jar and jaxb.jar API with jaxb-api-2.0.jar



  2. I Didn't Follow these Sections from the CXF App Server Guide:

    • Replace the Oracle XML parser with Xerces

    • Deploying Applications Section



  3. Ended up with the following -XbootClasspath/p: values:

    -Xbootclasspath^/p:C:\stax-api-1.0.1.jar;C:\xercesImpl-2.8.1.jar;C:\xalan-2.7.0.jar;C:\xml-apis-1.3.02.jar;C:\webservices\wsdl4j-1_6_2\lib\wsdl4j.jar;C:\jaxb-api-2.0.jar


  4. Set one system property in a custom ContextLoaderListener (as shown above)



Other Notes:

  • These steps worked for me with CXF Versions 2.0.2-incubator & 2.0.6

  • If you're on CXF version 2.1, you'll need jaxb-api-2.1 instead of 2.0

  • Download CXF here

  • Download Xerces 2.8.1 here

  • Download WSDL4J here

  • Make a directory to keep custom artifacts as you move through the process

Firefox 3 - Help Set a New World Record

The release date for Firefox 3 has been set, June 17th, 2008.

On Download Day, we're going to shoot for the most software downloads in a 24-hour period and set an official Guinness World Record.

Visit Spread Firefox and pledge your download!

Download Day