Showing posts with label Web Services. Show all posts
Showing posts with label Web Services. Show all posts

Friday, June 11, 2010

How to change the endpoint defined in the WSDL

Why should one do that? There might be several different reasons, I'll write about the one that moved me. We are developing a new integrated enterprise application for a customer that is located in another city: the core of the system is developed in RPG-LE and uses a cool UI that greatly extends the classic "green screen". The system is deployed on an iSeries and exposes Axis2 Web Services through an IBM Websphere Application Server; these services are accessed by a web application hosted in a protected network that is used by local offices all over Italy.

We periodically update their core system in a direct way, but for security reasons we do not have administrative access to their application server, so whenever we release an update we have to contact them and wait for them to republish the Web Services. As, despite of all my efforts to persuade the decisors, this still happens manually (nemo propheta in patria), every now and then we experience strange behaviours in remote clients.

As I still haven't managed to obtain dedicated services instances and databases for tests (see above) I must revert to plain old manual testing. More or less, as I definitely don't want to jump on the bandwagon of keyboard monkeys that seems so in fashion. Lazy as every good programmer should be (if nothing else I still got something of a good programmer) at least I have partly automated the process with a combination of Selenium, wsmonitor and Poster.

What I still missed was the possibility to easily override the endpoint defined in the WSDL I used when I generated the client in NetBeans for a scenario like this: we develop the core, expose the services, generate a client, use it in the remote application, run it and check that everything is working fine, deploy to the customer, ask them to republish the services, generate a client, use it in the remote application, run it and check that everything is working fine and it is not. And if you're wondering, yes there is some echo in this room.

As a matter of fact, every now and then we got as an answer a SOAP fault with a crystal clear message like

java.lang.NumberFormatException: High-order nibble of the byte at array offset 11 is not valid.  Byte value: 40

WTF??? At this point we normally check that the customer properly deployed the services diffing the WSDLs, then eventually contact them, but that's not always as easy as we'd wish. To get further informations (and to speedup the test process) I would like to use Poster to test that the service is working as expected, but for that I need the content to post. That's where wsmonitor would come useful, but it turns out that I cannot update the client through it:

Please enable REST support in WEB-INF/conf/axis2.xml

Before you ask, they wouldn't allow it. So I had to directly generate a client from their anthracite coal grey box (don't call it black, they'd be resented about it) but have it point to my local wsmonitor instead (I'm afraid either NetBeans still has to catch up a little with this or I have to find out how to sort it out) to see the outgoing and incoming messages.

Now the real magic you've been waiting for (well maybe you haven't, but I sure did): the client code generated by NetBeans looks like this snippet:

MyService service = new MyService();
MyServicePortType port =
service.getMyServiceSOAP11PortHttp();

At this point the port refers to the endpoint defined in the remote WSDL. To override it all you need to do is add this line:

((BindingProvider) port).getRequestContext().put(
BindingProvider.ENDPOINT_ADDRESS_PROPERTY,
"http://localhost:12345/path/to/MyService");

So what? as awkward as it might seem, the fastest solutions (obviously as far as I know, which is not much) turned out to generate the client from the original WSDL, debug the client application, start the wsmonitor, change the endpoint on the fly and apply the code changes class as needed, and... ta-daaah! here are the SOAP messages!

From this point on I can happily close everything else and switch to Poster: until a click on the POST button returns me a valid message I don't even waste a second on my IDE or on the client application.

Why did I choose 12345 for the port? Because

...that's the stupidest combination I've ever heard of in my life! That's the kinda thing an idiot would have on his luggage!

Now, if you're yelling

1, 2, 3, 4, 5? That's amazing! I've got the same combination on my luggage!

console yourself, you're not alone :-)

Thursday, May 20, 2010

NetBeans and JAX-WS

A failing hard disk can be a positive thing: at least it forces you to learn new things. After fixing the project I just wrote about, I went straight to the next one, checked it out, fixed all the paths on the database configuration files (this time I was on the ball), cleaned and built, tested it and everything was fine. A big smile was spreading on my face, as now I could really go back to the real stuff.

Until I ran it.

20-mag-2010 17.53.23 com.sun.xml.ws.transport.http.servlet.WSServletContextListener contextInitialized
INFO: WSSERVLET12: JAX-WS context listener initializing
20-mag-2010 17.53.27 com.sun.xml.ws.transport.http.servlet.WSServletContextListener contextInitialized
GRAVE: WSSERVLET11: failed to parse runtime descriptor: javax.xml.ws.WebServiceException: Unable to create JAXBContext
javax.xml.ws.WebServiceException: Unable to create JAXBContext

(blah blah blah jabber jabber jabber blah blah blah)

Caused by: java.security.PrivilegedActionException: com.sun.xml.bind.v2.runtime.IllegalAnnotationsException: 2 counts of IllegalAnnotationExceptions
my.wonderful.package.MyWonderfulClass is an interface, and JAXB can't handle interfaces.

(ariblah blah blah jabber jabber jabber blah blah blah)

Actually the blah blah part was much longer, but it left me quite disappointed. Everything had always worked fine, and we hadn't touched that codebase for quite a long time. It must have been something about configuration, but NetBeans didn't complain about missing references.

I googled for a while to get some clues, and everything I found required an intricate scaffolding over our classes. Too bad.

The only remaining culprit could only be NetBeans, as Marco pointed out - no, I won't pass to Eclipse, though. And that's final. Neither to Maven, at least for the time being :-)

Comparing a 6.7.1 installation with a 6.8 I found out that the first reported the JAX-WS 2.1 library in the dependencies of the project, while the latter the 2.2 version. At first I missed it, as the first place I checked was obviously the project.properties, that only reported a reference to the ${libs.jaxws21.classpath} variable, which was the version we were actually using. As setting up another project NetBeans kindly informed me that I was using JAX-WS 2.2 but the features I required needed the 2.1 version and I had to use the endorsing mechanism, I was quite ready for something like that, but it all passed by silently and I (wrongly) felt reassured.

I really had to double check... as I realized comparing the build.properties file used by the two IDEs, that referred to the same variable but had different path elements. What a fool! The more I find out, the less that I know...

Tuesday, March 17, 2009

NetBeans and Web Services

NetBeans is a great tool when it comes to web services (just like for all the rest, of course), and creating a web service client is just a couple of clicks away. First of all you right-click on Web Service Reference, expand the New menu item and select Web Service Client...


...then you simply tell the system where the WSDL is located, choose a client style and you're done.


NetBeans prepares a reference to each operation that you can simply drag wherever you need it: NetBeans will create a skeleton for you to customize.


I have just received the happy assignment of documenting all the tests for a system we're realizing on the IBM i5 platform using RPGLE. The project started with more than 600 pages of detailed requirements we delivered more than one year ago, without a single line of code. Now it looks like the customer has decided that we should start developing (at last!), and I wanted (and I still want) to avoid rewriting the Ulysses, as nobody is probably going to read it (probably the same fate shared by our detailed requirements, even if they were actually very good).

Luckily the system must expose all its features via web services, and we must also integrate them in a Java web application, so I thought "well, I have to prepare a facade and test it anyway, why don't I write some fixtures and document the system with Fit tables?"

After some debates with non technical managers, who often prefer a sound ream of paper, I convinced them of the advantages of my solution, then I started working right on it:
  • deploy a new instance of FitNesse (copy and launch would be closer)
  • create a simple test table
  • create a new project in NetBeans for the facade
  • create a new web service client
  • create a new class that uses the web service
  • create a new project in NetBeans for the fixtures
  • add the reference to the facade
  • create a new fixtures for the test table
  • Test!
"Null pointer exception? what do you mean with "Null pointer exception"? Let's check the output...

javax.xml.ws.WebServiceException: Failed to access the WSDL at: file:/C:/my/path/to/Project/xml-resources/web-service-references/SERVICE_WS/wsdl/1.2.3.4_12345/web/services/SERVICE_WS.wsdl. It failed with: C:\my\path\to\Service\xml-resources\web-service-references\SERVICE_WS\wsdl\1.2.3.4_12345\web\services\SERVICE_WS.wsdl (Impossibile trovare il percorso specificato).

That's strange... we'd already use this reference and jar trick in other projects and it worked perfectly well... following tonyx's advice I tried to work out the reference to the wsdl file, directly cabled in one of the NetBeans generated classes. After some experimenting I managed to tell NetBeans to always refer to the online wsdl for classes generation: you simply right-click your reference, select the menu item Edit web service attributes and from the wsimport options you add the option wsdllocation with the URL of the wsdl as a value.



Now my FitNesse instance happily colors my test table! Ops... red cells? the service is not working as expected... well, when do you want to know you have a problem? As soon as possible, which is now. Hey, you there, RPGLE guys... take a look at this! :-)

Thursday, June 12, 2008

IBM i5 exposed

Following the post on web services interoperability, we've now deployed in production our first web service based on a legacy software written in rpgle and resident on an IBM i5. I will review the principal passages of the procedure.

First, we used WDSC to generate a Java class which extends com.ibm.connector.as400.ProgramCallBean, which is basically a class that wraps a call to the rpgle program. The class comes with a .pcml file, which defines the name of the rpgle program and the parameters to be used, and a .config file, which describes the properties used to connect to the i5 system.

Then we created a new project on NetBeans IDE in which we imported everything; we created some domain classes, defined an interface for the new service, created a fake and a real implementation and kindly asked the IDE to generate a Web Service for us (yes, if you're wondering it was all test driven).

We deployed the application on an Apache Tomcat, created (always with NetBeans IDE) a client for the service and tested it. Everything worked all right.

To expose the service to our customers, we deployed the application in the DMZ and opened the correct ports on the firewall:
  • 449 for the port mapper
  • 8475 for remote command
  • 8476 for sign on
We kept all the other ports suggested by IBM closed as we don't need them open... yet.

Thursday, May 15, 2008

NetBeans and WDSC

As a follow up to the previous post: we've decided to simplify the process sticking to my old and beloved NetBeans (nothing against WDSC but I don't know it - yet). So we created a a project with a simple wrapper class that only calls the rpgle operation, then I saved it and imported it in NetBeans.

Aaaahhh, now we're going somewhere!

Tuesday, May 13, 2008

Web Services Interoperability?

After some discussions I've finally managed to persuade the iSeries administrator to expose some of his applications as services instead of giving other teams accounts to access the databases. We chose a test program, discussed a little, agreed on data and operations, and moved to our favourite IDEs (WDSC in his case, NetBeans in mine).

Time required to build a web service in WDSC starting from an RPGLE program: about 30 minutes, due to the fact that we never tried it before.

Time required to build a client in NetBeans importing the WSDL published on the integrated Websphere: about 5 minutes.

Time required to actually integrate the client and the server: we are still trying to figure that out... the client reports a connection error (but it managed to retrieve the WSDL and generate all the necessary stuff without any problem), the server reports a not better specified moduleData null error (but we managed to locally test the service all right), we report a serious headache.

As always, the devil lies in the details. But where exactly is too often unknown.

Naturally, exporting the WAR file and installing it on a Tomcat instance results in a long and incomprehensible stack trace (did you really think it could be so easy?).

So we tried another approach: we installed an Apache Tomcat instance on the WDSC and selected it as the target runtime for a new application. Magically it all worked fine (after we manually edited the WSDL which reported a wonderful localhost in the wsdlsoap:address attribute), even when we installed the same war file on another server with another Tomcat instance.

The next activity will consist in deploying the application on the Tomcat that resides in the DMZ... All we have to find out is what to open on the firewall. But, for now, let's call it a day.

Monday, March 10, 2008

Web Service SOA Programming with Passion! Certificate

Thanks to Stanislaw Styszynski my certificate has arrived. Time to ask for a raise?

Friday, March 7, 2008

Free Web Service SOA Programming with Passion! Online Course

The certificate will not be ready for another five days, but it looks like I've completed the wonderful (and free!) Web Service SOA Programming (with Passion!) online course. As always, Mr. Sang Shin has done a great job, so I cannot but invite you to attend the 4th session, which will start on May 1st, 2008.

This is Mr. Shin's second online course I've completed, and I'm actually taking the (free) Java EE (J2EE) Programming (with Passion!) course, even if I'm a little behind the schedule.

And, as always, Passion!