JAX-RS REST with Swagger in IBM Integration Designer

We have seen over the last 2-3 years an evolution in the way how we are interacting with our services.  This is thanks to mobile devices which don’t have the same processing power like our servers in the data centers and also bandwidth data restrictions might play here an important factor. Enterprise Services in a Service Oriented Architecture use(d) HTTP/SOAP as an interoperability protocol. A lot of software products have Webserviece APIs via SOAP but due to the growing business demand to go mobile these interfaces don’t play very well with our devices. Besides the already mentioned factors the computation cost of SOAP message data serialization is notable, that’s why HTTP/JSON has taken over the Mobile and Cloud world. Though JSON has many obvious advantages as a data interchange format – it is lightweight, human readable, well understood, and typically performs well – it also has its issues (I will save this for another article).

To everyone working with Web services the standard definition file is a WSDL file which basically is a services contract between client and server with well defined objects and schemas, containing either document-oriented or procedure-oriented information. In WebSphere Integration Developer (WID) or now IBM Integration Designer (IID) you can easily create a Web service HTTP/SOAP Binding with a WSDL file or use a HTTP Binding with a builtin JSONDataHander to expose your service as a RESTful service in a couple of clicks. Sadly at this point no one knows how to use our RESTful API and you have to spend time to write additional documentation or define a WADL file, which is incredibly time consuming to create descriptions with.

Fortunately there is swagger.io a framework to help fill the gap. Swagger is a specification for documenting REST APIs. It specifies the format (method, url and representation) to describe REST Web services. It provides also tools to generate the documentation from application code.

IBM BPM 8.5.x  is using WAS 8.5.x as runtime platform, which as part of the official EE6 platform supports JAX-RS. Integration Designer doesn’t support neither JAX-RS nor Swagger as part of the auto-generated Bindings. There is a RFE for this feature. Luckily it supports Web Application development and that’s what I’m going to use to create a JAX-RS Web Interface, declare swagger annotations and call out via a SCA Reference Partner to my Mediation.

We are going to start with the interface, objects and the Stand-alone Reference component. The Name of the standalone ReferencePartner is “CarPartner”.

jaxrs-1

 

jaxrs-1a

Now let’s create a Web Application Module (war)

jaxrs-1b

and link it to our Mediation Module

jaxrs-1c

When cleaning/building your workspace, IID compiles your application so any modifications done in the default WEB module will be erased, that’s another reason for using a separate custom Web Module. From here on, you can start creating your JAX-RS Interface and write the necessary code to initialize swagger and also make the connection to your SCA Component.

In order to give swagger the knowledge of the structure of the schema objects in use for the JAX-RS interface we have to generate JBAX-POJOs/SDO implementation classes because swagger is not designed to understand XSDs. You can do that by switching from default (Business Integration) perspective to Java perspective and use the builtin wizard to generate Java classes.

jaxrs-1d

If you are using Maven or Gradle you can get the swagger libraries from the Maven repo. For the purpose of this walk through I have extracted the necessary jar files from the POM.XML via

mvn install dependency:copy-dependencies

and copied them into the WAR/lib folder. There are also two additional libraries for the CORS filter support which are needed to grant access to swagger-ui.

jaxrs-1e

Let’s assemble everything. There are various ways to initialize swagger. First update the web.xml with the following entries:

<servlet>
<description>
This is the description for the sample servlet
</description>
<display-name>Gateway</display-name>
<servlet-name>com.mygateway.GatewayApplication</servlet-name>
</servlet>
<servlet-mapping>
<servlet-name>com.mygateway.GatewayApplication</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
<filter>
<filter-name>CORS</filter-name>
<filter-class>com.thetransactioncompany.cors.CORSFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CORS</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

 

Create an Application class with the following entries: (more info can be obtained in the swagger documentation)

package com.mygateway;

import io.swagger.jaxrs.config.BeanConfig;
import io.swagger.jaxrs.listing.ApiListingResource;
import io.swagger.jaxrs.listing.SwaggerSerializers;
import java.util.HashSet;
import java.util.Set;
import javax.ws.rs.core.Application;

public class GatewayApplication extends Application {

 public GatewayApplication() {
 BeanConfig beanConfig = new BeanConfig();
 beanConfig.setTitle("PoT SWAGGER - REST GATEWAY");
 beanConfig.setDescription("Test API REST Interface with Swagger Annotations");
 beanConfig.setVersion("0.0.1");
 beanConfig.setSchemes(new String[] { "http" });
 beanConfig.setHost("localhost:9080");
 beanConfig.setBasePath("/Gateway/rest");
 beanConfig.setResourcePackage("com.mygateway");
 beanConfig.setScan(true);
 beanConfig.setPrettyPrint(true);
 }

 public Set<class<?>> getClasses() {
 Set<class<?>> classes = new HashSet();

 //JAX-RS interface
 classes.add(GatewayService.class);
 //Add Swagger initialisation classes
 classes.add(ApiListingResource.class);
 classes.add(SwaggerSerializers.class);

 return classes;
 }
}

My JAX-RS class (GatewayService.java) has the same 3 operations as my SCA Interface. Once the HTTP call is initialized a call-out is made via the SCA Partner “CarPartner” to my Mediation and the response is feed though a SDO/JSON data formatter.

@Api(value = "/cars", description = "RESTful API to interact with Car Servcie.")
@Path("/cars")
@Stateless
public class GatewayService extends Application {

 @ApiOperation(value = "Get Car by ID", notes = "Get model details by ID", responseContainer = "Car", response = Car.class)
 @GET
 @Path("/{id}")
 @Produces(MediaType.APPLICATION_JSON)
 public Response getById(
 @ApiParam(value = "Car ID", required = true) @PathParam("id") int id)
 throws Exception {

 // Invoke SCA Stand-alone Reference Partner
 Service service = (Service) ServiceManager.INSTANCE.locateService("CarPartner");
 DataObject car = (DataObject) service.invoke("getCarById",Integer.valueOf(id));
 DataObject res = (DataObject) car.get(0);

 //Use SDO to JSON Converter
 com.ibm.bpe.message.JsonConverter jc = com.ibm.bpe.message.JsonConverter.getInstance();
 String resp = jc.convertObject2JSON(res);

 if (res != null) {
 return Response.ok(resp).build();
 }
 return Response.status(Response.Status.NOT_FOUND).build();
 }
...
...
}

The response class definition points to the SDO Java implementation generated though the wizard.

 response = Car.class

You might ask why I’m using the generated Java classes only for swagger presentation purpose? Well, many ways lead to Rome. You could use for the Response following approach:  EMF EObjects or SDO EDataObjects to Java POJO to JSON, or create a dynamic EMF model from XSDs, or serializae JSON to XML to SDO. I still believe a simple SDO/JSON transformation will give the best performance. On the other hand swagger needs a strong typed definition of your objects, whereby the DataObject implementation is dynamic, hence we use the generated classes for the swagger presentation layer.

After the deployment of the APP to Process Server we can invoke the REST service.

jaxrs-1g

Now it’s time to see the service definition in my local swagger-ui.

swagger2

Advertisements

Swagger-ui with Websphere Application Server

To deploy the swagger-ui on WebSphere Application Server get the source code from github first. Create a Simple Web Project in Eclipse and copy the content of the ‘dist’ folder from the zip archive into WebContent folder. Make sure you have the WebSphere Development Tools plugin installed in Eclipse. You can find it in the Eclipse Marketplace.

Now set the root context to /swagger in ibm-web-ext.xml. Export the project as WAR and deploy on the Application Server.

swagger-ui1

 

To point by default to your own RESTful API with swagger annotations change the url in the index.html file.

swagger-ui2

Capturing HTTP Status Code on One-Way Web Service Operations

I am working on a project using WID/WPS/WESB v6.2.0.2 and was asked recently if a mediation flow could capture HTTP response codes from a back-end web service one-way operation.

Naturally my advice was that if an operation describes neither response nor faults, the client is not expected to care about what happens after the request is posted to the service.

Nonetheless, I set about providing a solution, which I would class as a ‘trick’, and hence worthy of a first post in this appropriately named blog.

In summary, the trick consists in calling the web service using an import with HTTP bindings using SOAP/HTTP data serialisation format and basically lying on the import interface. Shameless, but effective.

So, let me show you the trick in more detail.

Lets pretend we have a CustomerService with an addCustomer one-way operation that accepts a Customer as input. Go ahead and create a library named LB_Customer, an interface named CustomerService and a DataObject called Customer.

Then create a module called CustomerService with a Java SCA component just logging the Customer attributes and a web services export. I chose SOAP1.1/HTTP using JAX-RPC. Well, I had no choice. This is the standard in this project.

So, here’s the assembly:

Here’s the CustomerService interface:

And here’s the Customer data type:

Oh, and the very simple Java component code:

You can go ahead, deploy and test. We’re done with the pretence and we can move on to the real trick.

Now create a mediation module, call it MM_CustomerService and do not make the library a dependency. Within this mediation project create your own copy of the Customer data type and the CustomerService interface, but make the addCustomer operation request-response and create a new Response data type.

Here’s the mediation’s private CustomerService interface:

And here’s the Response data type, also private to the mediation:

The private Customer data type is an exact copy of the one in the library used by the target service.

At this point it might be worth showing you my business integration view, so you can check all your bits and pieces are in the right place:

Now comes the hack. You have to make sure the CustomerService interface which is part of the MM_CustomerService mediation project has the same namespace as the one in the library. So go ahead and change it. Go to the interface properties and change the namespace to http://LB_Customer/CustomerService. I told you there was some lying involved.

Now you can assign this interface to your mediation flow component, both as an interface and a reference. Then drop an import into the assembly, wire it to the mediation flow component’s reference and accept the creation of a matching interface on the import.

Right-click on the import and select Generate Binding…-> HTTP Binding. You will have to provide the endpoint URL. You can copy it from the binding tab on the properties for the web services export on the CustomerService assembly.

Here’s a screenshot of the complete assembly:

Go to the properties for the HttpImport, Binding tab, and select SOAP (HTTP) as the default data format. You will need to check the box to show deprecated data formats.

Here’s how you select the data binding:

And here’s the main Binding Properties tab:

Finally go to the Method bindings tab, select the addCustomer bound method and change the HTTP method from GET to POST.

Now let’s implement the mediation flow.

The request flow is a doddle. We simply let the message pass through:

The response flow requires a couple of XML transformations for the out and fail terminals:

The two transformations operate at message root level and map the StatusCode and ReasonPhrase from the smo HTTPHeader to the response body:

You can build, and deploy the two modules now.

Then test the mediation flow component. I’m assuming you’re more than familiar with the integration test client.

What happened?

On this first run I can see in the Events pane that we invoked the http import and that the response fail terminal was fired, routing the response flow to the MapFail xml transform. You can also see the response values. HTTP status code 500

So this is rather good news! Yes, something is not quite right yet but it proves that we are doing what we are supposed to. Capturing HTTP response codes for a service which is, in WSDL/SOAP terms, one-way.

If you have a Console view to hand, you can flounder around for an explanation to this minor frustration, but I’d rather just save you time and show you the relevant log section:

So, it looks like we are missing a SOAPAction header.

I’m still in fits about understanding the purpose of this header. But I understand that there must be a SOAPAction HTTP header for this to work.

So, go back to the properties for the HTTP Import and add an HTTP header named SOAPAction. I used a single white space for its value as there must be a value present.

Now rebuild, republish and retest.

Sweet! We get a 200 OK and we can see in the log the target service doing the sysouts!

And one last thing you may want to do is to stop the CustomerServiceApp (on the Servers view) and retest. You will get the anticipated 404 Not Found:

That’s it, hope you enjoyed this magic trick and feel free to contribute comments and observations, particularly if you get a chance to try something similar on v7.

ttfn

Changing a SOAP Endpoint on an Outgoing Message using JAX-WS

This tip comes from Arancha Ocana Diaz-Ufano, who did all the hard work to figure it out!

In WebSphere ESB, there are many ways of changing the endpoint of a SOAP message outbound from a mediation flow, and the normal way is to use the dynamic endpoint support.  To be clear, this is recommended way.

However, there is another technique, and that’s to use a JAX-WS handler (assuming you’re using a JAX-WS Web Services binding) on the outbound message. This might be useful if, for example, you absolutely cannot modify a mediation flow that’s been given to you, you cannot modify the endpoint at administration time (for example, from the administration console), or you want to do the override in a generic fashion across a large number of mediation flows.

The key is knowing the magic incantation to put in your JAX-WS handler. And here it is:

mySOAPMessageContext.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, "http://myhost:9080/MyEndPoint");

Thanks again to Arancha for allowing us to publish this tip.

WS-Addressing Headers in WebSphere ESB v6.2

I wrote previously about how WS-Addressing headers could be accessed in a WebSphere ESB mediation flow, by writing a JAX-RPC handler to intercept them and insert them into a custom SOAP header.

However, in WebSphere ESB 6.2, this is much easier – these headers will now automatically appear as part of the ServiceMessageObject at /headers/WSAHeader. They are effectively read-only; any changes that you make will not affect outgoing messages.

Importing resources from the web into WebSphere Integration Developer

If you have a WSDL or XSD schema that has already been published to the web that you need to use in WebSphere Integration Developer you can import it straight from the web by choosing the File>Import>HTTP option and specify the URL rather than download the file and import it from the filesystem.

Monitoring SOAP messages in WebSphere Integration Developer

If you are developing a module or mediation module with web services bindings you may be interested in monitoring the SOAP message(s) received at an export or sent from an import. To find out how to do this, read the rest of this post.
Read more of this post