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

Friday, November 26, 2010

Web services : cURL

If you need to do some web service client testing, there are a number of tools like SOAPUI but they all involve installing programs etc.

Then I came across this neat tool cURL

To quote from the docs:

"curl is a command line tool for transferring data with URL syntax, supporting DICT, FILE, FTP, FTPS, GOPHER, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS, POP3, POP3S, RTMP, RTSP, SCP, SFTP, SMTP, SMTPS, TELNET and TFTP. curl supports SSL certificates, HTTP POST, HTTP PUT, FTP uploading, HTTP form based upload, proxies, cookies, user+password authentication (Basic, Digest, NTLM, Negotiate, kerberos...), file transfer resume, proxy tunneling and a busload of other useful tricks."

It runs on a wide variety of platforms.

So how do you use it to test a web service?

You need to mock-up what the actual SOAP packet looks like e.g.

to test a web service called TestWS, the information might look like:






123456
Joe
Bloggs





Save this in a file called TestWS.xml.

The command line for cURL would then be:

curl --data @TestWS.xml --header "Content-Type: text/xml" --header "Accept-Encoding: gzip,deflate" --verbose http://host:port/TestWSService


This then sends the HTTP POST which itself contains a SOAP message which invokes the web service.

The verbose option prints out both the request and the response.

Enjoy!

Thursday, November 18, 2010

CXF : Deploying the java_first_jaxws sample direct to Tomcat

Decided I wanted to learn a bit about CXF so downloaded the development kit and has a look at the java_first_jaxws project in the \samples directory.

Before you try and do anything, ensure you have the environment set up correctly.

I created a bat file (as per README) which looks like:


set CXF_HOME=x:\apache-cxf-2.3.0
set JAVA_HOME=x:\Program Files\Java\jdk1.6.0_22
set ANT_HOME=C:\apache-ant-1.8.1

set PATH=%JAVA_HOME%\bin;%ANT_HOME%\bin;%CXF_HOME%\bin;%PATH%
set CLASSPATH=.;%CXF_HOME%\lib\cxf-manifest.jar;.\build\classes

set CATALINA_HOME=x:\Program Files\Apache Software Foundation\Apache Tomcat 6.0.26


which also serves as a useful list of the file versions I have.

One level up from the project you will find a useful file i.e.

common_build.xml

which is worth looking through.

In the actual project directory you will find a build.xml which calls the above.

ant -p


shows:


Main targets:

build build demo client and server
client run demo client
client-servlet run demo client hitting servlet
deploy deploy the application into the container
server run demo server
undeploy undeploy the application from the container
Default target: build


so we first do:

ant build

which builds both the client and the server.

Then we run:

ant server


and

ant client


Note that the client and server run in two separate command prompts.

The client then sends some canned messages to the server:


client:
[java] Hello World
[java] Hello World
[java] Hello Galaxy
[java] Hello Universe
[java]
[java] Users:
[java] 1: World
[java] 2: Galaxy
[java] 3: Universe


and the server receives:


server:
[java] Starting Server
[java] Server ready...
[java] sayHi called
[java] sayHiToUser called
[java] sayHiToUser called
[java] sayHiToUser called
[java] getUsers called


Note that this is running is a "built-in" Jetty server and the URL the client calls is:

http://localhost:9000/helloWorld

OK, that sets the scene for the main thrust of this article which is how to deploy this client to a real instance of Tomcat.

So start up the Tomcat server as usual by running "startup.bat" in the \bin directory.

My installation of Tomcat runs on port 8080 so we need to change Client.java as follows:


//String endpointAddress = "http://localhost:9000/helloWorld";
String endpointAddress = "http://localhost:8080/helloworld/services/hello_world";


Now we run the normal "ant build" and then we run "ant deploy".

This builds the war file and then deploys it to Tomcat (which is where the CATALINA_HOME environment variable comes in.)

Then we run the normal "ant client" and this time, the server output messages will appear in the Tomcat window.

Note that the WSDL can be found at:

http://localhost:8080/helloworld/services/hello_world?wsdl

Where on earth does this URL come from?

As per Creating a WSDL-first web service with Apache CXF or GlassFish Metro, scroll down to Point 2 in the "Additional notes".

Adapting for our project, we get:

http://localhost:8080/helloworld/services/hello_world?wsdl

"localhost:8080" is the host and port of the servlet container.
"helloworld" is the name of the war file.
"services" comes from the url-pattern element in the web.xml file.
"hello_world" comes from the address attribute in the cxf-servlet.xml file (for CXF).

If we look into the web.xml file (you'll need to look at the war file in the ...\samples\java_first_jaxws\build\war directory), we find:

servlet-name = cxf
url-pattern = /services/*

If we look into the cxf-servlet.xml file (in the wsdl directory), we find:


jaxws:server id="jaxwsService" serviceClass="demo.hw.server.HelloWorld" address="/hello_world"


Enjoy!

Thursday, January 28, 2010

Metro : Printing / dumping out the contents of a SOAP packet

I've used Metro a lot and I've always battled to have decent logging.

In the web service, I normally log all the inputs and the outputs and all the exceptions. Wouldn't it be easier if you could just log all the requests and responses which would guarantee that you had all the information all of the time?

I just couldn't figure out how.

Until I came across "MessageDumpingFeature". You find this in the Glassfish \lib directory in the webservices-rt.jar file.

If you've generated web services using Metro, you find the code below very familiar. All you really need to do is replace:

service.getWebServiceName();

with

service.getWebServiceName(messageDumper);

The code looks like:

 

import com.sun.xml.ws.assembler.MessageDumpingFeature;

... snip ...

messageDumper = new MessageDumpingFeature();

ServiceName service = new ServiceName();
WebServiceName port = service.getWebServiceName(messageDumper);
// TODO initialize WS operation arguments here
java.lang.String xxx = "yyy";
java.lang.String yyy = "zzz"
// TODO process result here
ResultName result = port.doWebService(xxx, yyy);

String request = messageDumper.nextMessage();
String response = messageDumper.nextMessage();

System.out.println (request);
System.out.println (response);

... snip ...

} catch (Exception ex) {
String request = messageDumper.nextMessage();
String response = messageDumper.nextMessage();

System.out.println (request);
System.out.println (response);
}


It prints out both normal responses and SOAP Faults.

A request would be dumped like:

 
<?xml version="1.0" ?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body>
<ns2:doWebService xmlns:ns2="http://namespace/">
<xxx>yyy</xxx>
<yyy>zzz</yyy>
</ns2:doWebService>
</S:Body>
</S:Envelope>


A valid response would be dumped like:

 
<?xml version="1.0" ?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body>
<ns2:doWebService xmlns:ns2="http://namespace/">
<return>
<aaa>bbb</aaa>
<bbb>ccc</bbb>
</return>
</ns2:doWebService>
</S:Body>
</S:Envelope>


A SOAP fault would be dumped like:

 
<?xml version="1.0" ?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body>
<S:Fault xmlns:ns4="http://www.w3.org/2003/05/soap-envelope">
<faultcode>S:Server</faultcode>
<faultstring>SomeErrorString</faultstring>
<detail>
<ns2:SomeException xmlns:ns2="http://namespace/">
<message>SomeErrorMessage</message>
</ns2:SomeException>
</detail>
</S:Fault>
</S:Body>
</S:Envelope>


Of course, instead of dumping out the request / response, it could be written to a file instead.

Enjoy!

Thursday, January 07, 2010

SOAPUI : Adding a wsdl

Assume a WSDL like:

http://host:port/ApplicationServer/Service

Sometimes when you are adding a WSDL like the above you get an error:

SOAPUIException: Error inporting wsdl

Try qualifying the URL i.e.

http://host:port/ApplicationServer/Service?wsdl

Enjoy!

Wednesday, January 06, 2010

SOAPUI : NoClassDefFoundError

Using SOAPUI 3.0.1 to test web services created using Netbeans, JAX-WS and Metro.

When I try and run the TestRunner, I get:


java.lang.NoClassDefFoundError: org/apache/commons/cli/CommandLineParser


My solution was to edit soapui.bat (in the /bin directory) and add:

set JAVA_HOME=C:\Program Files\Java\jdk1.6.0_16

at the top.

Then, instead of running soapui.exe from the desktop shortcut, I open a command prompt and run soapui.bat from there manually.

Problem solved.

Enjoy!

Tuesday, January 05, 2010

Metro : Sniffing the traffic with JAX-WS, Netbeans and Metro

I often use Fiddler to view / log browser traffic.

From the web site: "Fiddler is a Web Debugging Proxy which logs all HTTP(S) traffic between your computer and the Internet. Fiddler allows you to inspect all HTTP(S) traffic, set breakpoints, and "fiddle" with incoming or outgoing data. Fiddler includes a powerful event-based scripting subsystem, and can be extended using any .NET language."

However, it doesn't work when you want to look at Java web service (SOAP) traffic generated by the JAX-WS support in Netbeans (i.e. Metro).

I have a number of command line tools that I use to generate various types of traffic with a command line like:


java -jar SomeProgram.jar


To get Fiddler to work, you need to change the command line to:


java -DproxySet=true -DproxyHost=127.0.0.1 -DproxyPort=8888 -jar SomeProgram.jar


Fiddler uses port 8888 as default.

Enjoy!

Tuesday, October 20, 2009

Metro : JAX WS catalogue

One of the problems with using Netbeans to generate web services using Glassfish / Metro is that when you want to create a new Web service client, you are asked to select the web service which is normally on your local machine.

This means that the web service has an address like http://localhost:8080 and it then becomes a problem when you deploy to other environments.

One way around this is to use a catalog to resolve the addresses at run time. The file is called jax-ws-catalog.xml and it's placed in the META-INF directory.

It looks like e.g.

 
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" prefer="system">
<rewriteSystem
systemIdStartString="http://localhost:8080/"
rewritePrefix="http://some url:some port/"/>
<rewriteURI
uriStartString="http://localhost:8080/"
rewritePrefix="http://some url:some port/" />
</catalog>


This searches for any URL that starts with "http://localhost:8080/" and replaces this with "http://some url:some port/" e.g.

http://localhost:8080/webserver/WebService

becomes

http://some url:some port/webserver/WebService

The ant build files in Netbeans use the -catalog option to point to a file called catalog.xml in the project root directory. You can apply the same principles to this file to resolve addresses at compile time.

Some useful links:

Using a JAX-WS Catalog

How to write an XML catalog file

Global URI re-writing with jax-ws-catalog

Enjoy!