Receiving Http Request using jPOS

Today i wanna share about Receiving Http Request using jPOS. when we talk about http request, its mean that we can use restful or soap Service. In this post, we will use Restful service as example. Mostly when we use restful service, we use JSON as data format.

Receiving Http Request using jPOS

First, jPOS is TCP based framework. its not possible to receive http request, but it’s possible if we can integrate jPOS with Servlet container like jetty. Jetty will open connection to receive http/s request, and then we can manipulate the data, wether the request is forwarded to another server using another protocols or just processed in internal system.

Like my another tutorials, we will create custom jPOS MBean interface that extends QBeanSupportMBean interface so we can deploy this class by putting xml configuration into Q2 deploy folder.

Before we can Receiving Http Request using jPOS, this is list of dependency library for run this project. Please create maven project or configure your java project to maven project. on eclipse you can configure your java project by right click on your project –> Configure –> convert to maven project.

<dependencies>
		<dependency>
			<groupId>org.eclipse.jetty</groupId>
			<artifactId>jetty-server</artifactId>
			<version>9.2.11.v20150529</version>
		</dependency>
		<dependency>
			<groupId>org.eclipse.jetty</groupId>
			<artifactId>jetty-servlet</artifactId>
			<version>9.2.11.v20150529</version>
		</dependency>
		<dependency>
			<groupId>org.jpos</groupId>
			<artifactId>jpos</artifactId>
			<version>1.9.2</version>
		</dependency>
		<dependency>
			<groupId>org.glassfish.jersey.core</groupId>
			<artifactId>jersey-server</artifactId>
			<version>2.7</version>
		</dependency>
		<dependency>
			<groupId>org.glassfish.jersey.containers</groupId>
			<artifactId>jersey-container-servlet-core</artifactId>
			<version>2.7</version>
		</dependency>
		<dependency>
			<groupId>org.glassfish.jersey.containers</groupId>
			<artifactId>jersey-container-jetty-http</artifactId>
			<version>2.7</version>
		</dependency>
		<dependency>
			<groupId>org.glassfish.jersey.media</groupId>
			<artifactId>jersey-media-moxy</artifactId>
			<version>2.7</version>
		</dependency>
		<!-- http://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core -->
		<dependency>
			<groupId>com.fasterxml.jackson.core</groupId>
			<artifactId>jackson-databind</artifactId>
			<version>2.7.3</version>
		</dependency>
		<!-- http://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
		<dependency>
			<groupId>org.apache.commons</groupId>
			<artifactId>commons-lang3</artifactId>
			<version>3.3.2</version>
		</dependency>
	</dependencies>

package com.didikh.rest;

import org.jpos.q2.QBeanSupportMBean;

public interface QRestServerMBean extends QBeanSupportMBean {
	void setPort(int port);
	int getPort();
}

After we create QRestServerMBean interface, we need to create the implementation class. this class will start jetty server with specific port base on xml parameter that we will create later. This class also get the controller and include it to jetty servlet container. let’s call this class QRestServer.


Please share this post to unlock the QRestServer code below. 😀

package com.didikh.rest;

import java.lang.reflect.Constructor;
import java.util.Iterator;

import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.servlet.ServletContainer;
import org.jdom.Element;
import org.jpos.iso.ISOPackager;
import org.jpos.q2.QBeanSupport;
import org.jpos.q2.QFactory;
import org.jpos.util.NameRegistrar;

/**
 * Starting the jetty server
 * @author Didik Hari
 * @since 26 May 2016
 */
public class QRestServer extends QBeanSupport implements QRestServerMBean {
	private Server server;
	private int port;
	
	public QRestServer() {
		super();
	}
	
	@Override
	protected void startService() throws Exception {
		ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
		context.setContextPath("/");
		context.addServlet(new ServletHolder(new ServletContainer(resourcesConfig())), "/*");
		
		server = new Server(port);
		server.setHandler(context);		
		server.start();
		NameRegistrar.register(getName(), this);
	}
	
	@SuppressWarnings("rawtypes")
	private ResourceConfig resourcesConfig() throws Exception {
		ResourceConfig resourceConfig = new ResourceConfig();

		QFactory factory = getFactory();
		Iterator iterator = getPersist().getChildren("rest-listener").iterator();
		while (iterator.hasNext()) {
			Element l = (Element) iterator.next();
			
			Class<?> cl = Class.forName(l.getAttributeValue ("class"));
			Constructor<?> cons = cl.getConstructor(ISOPackager.class);
			
			String packagerName = l.getAttributeValue ("packager");
			ISOPackager packager = null;
	        if (packagerName != null) {
	            packager = (ISOPackager) factory.newInstance (packagerName);
	        }
	        RestListener listener = (RestListener) cons.newInstance(packager);
	        
			factory.setLogger (listener, l);
            factory.setConfiguration (listener, l);
            
            resourceConfig.register(listener);
		}
		return resourceConfig;
	}

	@Override
	protected void stopService() throws Exception {
		server.stop();
		server.destroy();
		NameRegistrar.unregister(getName());
	}

	@Override
	public void setPort(int port) {
		this.port = port;
	}

	@Override
	public int getPort() {
		return this.port;
	}

}

The QRestServer class automatically register the object to NameRegistrar once the jetty server start and unregister while the Q2 server is shutdown. So, you can get the object by calling NameRegistrar.get(key) method.

In my case, i need to inject jPOS packager to controller class, so i can use it for further actions. Create class called RestListener that will hold the packager, and any controller that implement RestListener class can access it.

package com.didikh.rest;

import org.jpos.iso.ISOPackager;
import org.jpos.util.LogSource;
import org.jpos.util.Logger;

/**
 * This class is used for manual packager injection (future usage)<br/>
 * limit: one Listener only have one packager
 * @author Didik Hari
 *
 */
public class RestListener implements LogSource {
	protected ISOPackager packager;
	protected Logger logger;
	protected String realm;
	
	public RestListener(ISOPackager packager) {
		this.packager = packager;
	}

	@Override
	public void setLogger(Logger logger, String realm) {
		this.logger = logger;
		this.realm = realm;
	}

	@Override
	public String getRealm() {
		return this.realm;
	}

	@Override
	public Logger getLogger() {
		return this.logger;
	}
	
}

And this is the example of XML configuration to deploy this modul. call it 70_example-rest-server.xml and place it to your jPOS Q2 deploy directory.

<qbean name="test" logger="Q2" realm="jpos-rest" class="com.didikh.rest.QRestServer">	
	<attr name="port" type="java.lang.Integer">7070</attr>
	
	<rest-listener class="com.didikh.rest.controller.TestController" logger="Q2">
	</rest-listener>
</qbean>

the class attribute in rest-listener tag is a class that extends RestListener, this will receive any http/s request. Below is the example of the Controller class.

package com.didikh.rest.controller;

import java.sql.Timestamp;
import java.util.Date;

import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import org.apache.commons.lang3.StringUtils;
import org.eclipse.jetty.util.StringUtil;
import org.hibernate.Session;
import org.jpos.core.Configurable;
import org.jpos.core.Configuration;
import org.jpos.core.ConfigurationException;
import org.jpos.iso.ISOPackager;
import org.jpos.util.LogEvent;
import org.jpos.util.LogSource;
import org.jpos.util.Logger;
import org.jpos.util.NameRegistrar;
import org.jpos.util.NameRegistrar.NotFoundException;

import com.didikh.rest.QRestClient;
import com.didikh.rest.RestListener;

@Path("/jpos-rest/v1/")
public class TestController extends RestListener implements LogSource, Configurable {

    public TestController(ISOPackager packager) {
	super(packager);
    }

    @POST
    @Path(value = "account-status")
    @Produces(MediaType.APPLICATION_JSON)
    public Response accountStatus(final String input) {
	try {
		String responseJson = "[{'msg':'this is response'}]";
		return Response.status(200).entity(responseJson).build();
	} catch (Exception e) {
		e.printStackTrace();
	}
	return Response.status(204).build();
    }

    @Override
    public void setConfiguration(Configuration cfg)
		throws ConfigurationException {
	// TODO getting the config
    }
}

This example of code maybe error on import section, because i modify this class on the dashboard blog, not on the eclipse IDE. I think its all of Receiving Http Request using jPOS Tutorials, thank you for visiting my blog. if you have any question, concern or correction we can discuss it on comment section.

Receiving Http Request using jPOS
Receiving Http Request using jPOS
Receiving Http Request using jPOS
Receiving Http Request using jPOS
Receiving Http Request using jPOS
Receiving Http Request using jPOS
Receiving Http Request using jPOS
Receiving Http Request using jPOS
Receiving Http Request using jPOS
Receiving Http Request using jPOS
Receiving Http Request using jPOS
Receiving Http Request using jPOS
Receiving Http Request using jPOS

13 comments

  1. Hi Didik,

    Your blogs help me understand JPOS much better
    Thanks for your examples.
    I have question regarding this Jetty module interface with jPOS.
    get this error:

    org\jpos\aggregator\rest\QRestServer.java:5: error: package org.eclipse.jetty.server does not exist
    import org.eclipse.jetty.server.Server;
    I am new to jPOS.
    I have downloaded Jetty and Jetty-All.jar file.
    I dont know how to include Jetty in jPOS build. You are help could be useful to me

    Regards,
    Venkat

    1. Hi Venkat,

      i just update this post and add required library to run the project, please configure your project to maven project for automatically download dependency library.
      please let me know if you are still getting this error.

      Regards,
      Didik

  2. I get this error when write QRestServer.java
    The method getPort() of type QRestServer must override a superclass method QRestServer.java
    The method setPort(int) of type QRestServer must override a superclass method QRestServer.java

  3. Hi Didik,
    May i know how can i set the Q2 servers to accept OPTIONS header? before i switch to use rest json method due to CORS.

  4. hi @Didik..I have a REST web service in Jersey on a tomcat container..Can i use your example to pack messages to IS08583..What do i need to change.. My endpoint produces JSON also

    1. hi ed, sorry for late response.. i think you can create a class like XMLPackager that support pack/unpack from xml to iso8583,
      here JSONPackager from jpos repository that convert json to iso8583.

Leave a Reply

Your email address will not be published. Required fields are marked *