Handmade Coding

Oz Blogging about hand made programming
Loading...

How to use Google Drive REST API for document conversion?

Google Drive Authorization:

First we need to follow examples at  drive authorization server-side to build a nice proxy for authorization:

import java.io.IOException;
import java.io.InputStreamReader;
import java.security.GeneralSecurityException;

import com.google.api.client.auth.oauth2.AuthorizationCodeFlow;
import com.google.api.client.auth.oauth2.Credential;
import com.google.api.client.extensions.java6.auth.oauth2.AuthorizationCodeInstalledApp;
import com.google.api.client.extensions.java6.auth.oauth2.VerificationCodeReceiver;
import com.google.api.client.extensions.jetty.auth.oauth2.LocalServerReceiver;
import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow;
import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.json.JsonFactory;
import com.oz.drv.api.GoogDrvAuthProxy;
import com.oz.drv.api.GoogDrvConnConfig;

public class GoogDrvAuthProxyImpl implements GoogDrvAuthProxy
{
	/**
	 * Follow instructions at:
	 * <a href="https://developers.google.com/drive/web/auth/web-server">Implementing Server-Side Authorization</a>
	 * Choose "Installed application" option.
	 */
	private static final String PATH_CLIENT_SECRET_JSON =
		"./client_secret.json";
	private final GoogDrvConnConfig drvConnConfig;
	public GoogDrvAuthProxyImpl(final GoogDrvConnConfig drvConnConfig)
	{
		this.drvConnConfig = drvConnConfig;
	}
	@Override
	public Credential authorize(final String user)
	 throws IOException, GeneralSecurityException {
		final JsonFactory jsonFactory = drvConnConfig.getJsonFactory();
		final GoogleClientSecrets clientSecrets =
			GoogleClientSecrets.load(jsonFactory
				, new InputStreamReader(
					ClassLoader.getSystemResourceAsStream(
						PATH_CLIENT_SECRET_JSON)));
		final AuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(
				 drvConnConfig.getTransport()
				,jsonFactory
				,clientSecrets
				,drvConnConfig.getScopes()
			)
			.setDataStoreFactory(drvConnConfig.getDataStoreFactory())
			.setAccessType("offline")
			.build();
		final VerificationCodeReceiver rcvr = new LocalServerReceiver();
		return new AuthorizationCodeInstalledApp(flow, rcvr).authorize(user);
	}
	@Override
	public HttpTransport getTransport() throws GeneralSecurityException, IOException {
		return drvConnConfig.getTransport();
	}
	@Override
	public JsonFactory getJsonFactory() {
		return drvConnConfig.getJsonFactory();
	}
}

How to use Google Drive REST API for document conversion?

Using Google Drive API for file conversion:

Then we can build an example following guide at drive quick-start guide and some tips at downloading files using drive API:

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.security.GeneralSecurityException;
import com.google.api.client.auth.oauth2.Credential;
import com.google.api.client.http.AbstractInputStreamContent;
import com.google.api.client.http.FileContent;
import com.google.api.client.http.GenericUrl;
import com.google.api.client.http.HttpTransport;
import com.google.api.services.drive.Drive;
import com.oz.drv.api.GoogDrvAuthProxy;
import com.oz.drv.api.GoogDrvSvcProxy;
public class GoogDrvSvcProxyImpl implements GoogDrvSvcProxy
{
	private final String appName;
	private final GoogDrvAuthProxy drvAuthProxy;
	public GoogDrvSvcProxyImpl(final String appName, final GoogDrvAuthProxy drvAuthProxy)
	{
		this.appName = appName;
		this.drvAuthProxy = drvAuthProxy;
	}
	private Drive build(final HttpTransport transport, final Credential credential) {
		return new Drive.Builder(transport, drvAuthProxy.getJsonFactory(), credential)
			.setApplicationName(appName)
			.build();
	}
	@Override
	public String insert(final String user, final File file, final String mimeType)
	 throws IOException, GeneralSecurityException
	{
		final HttpTransport transport = drvAuthProxy.getTransport();
		final Credential cred = drvAuthProxy.authorize(user);
		final AbstractInputStreamContent mediaContent = new FileContent(mimeType, file);
		final com.google.api.services.drive.model.File content =
			new com.google.api.services.drive.model.File()
			.setTitle(file.getName())
		;
		return build(transport, cred)
			.files()
			.insert(content, mediaContent)
			.setConvert(true)
			.execute()
			.getId()
		;
	}
	@Override
	public InputStream get(final String user, final String fileId, final String mimeType)
	 throws IOException, GeneralSecurityException
	{
		final HttpTransport transport = drvAuthProxy.getTransport();
		final Credential cred = drvAuthProxy.authorize(user);
		final String downloadUrl = build(transport, cred)
			.files()
			.get(fileId)
			.execute()
			.getExportLinks()
			.get(mimeType)
		;
		if (null == downloadUrl) {
			return null;
		}
		return build(transport, cred)
			.getRequestFactory()
			.buildGetRequest(new GenericUrl(downloadUrl))
			.execute()
			.getContent()
		;
	}
	@Override
	public void delete(final String user, final String fileId)
	 throws IOException, GeneralSecurityException
	{
		final HttpTransport transport = drvAuthProxy.getTransport();
		final Credential cred = drvAuthProxy.authorize(user);
		build(transport, cred)
		.files()
		.delete(fileId)
		.execute()
		;
	}
}

How to use Dozer map-id for multiple destinations?

Java source:

Dozer's map-id attribute has to be unique across, but we can still use map-id to define mapping to multiple destinations of the same source. Here is a method that is trying achieve this:

@Component("theMapper")
public class TheMapper {
	@Resource
	private Mapper dozerMapper;
	public SomeDestinationBean map(
		 final SomeSrcBean ssb
		,final AnotherSrcBean asb
		,final String destinationType)
	{
		final SomeDestinationBean sdb = new SomeDestinationBean();
		//Do mapping. Note that map id has to be unique
		dozerMapper.map(ssb, sdb, destinationType+"_ss2sd");
		dozerMapper.map(asb, sdb, destinationType+"_as2sd");
		return sdb;
	}
}

Dozer XML mappings:

How do the dozer mapping configuration look like? This is for the first destination type (dozer-mapping-A.xml):

<?xml version="1.0" encoding="UTF-8"?>
<mappings xmlns="http://dozer.sourceforge.net"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="
	http://dozer.sourceforge.net
	http://dozer.sourceforge.net/schema/beanmapping.xsd"
	<mapping map-id="destA_ss2sd">
		<class-a>SomeSrcBean</class-a>
		<class-b>SomeDestinationBean</class-b>
		<field>
			<a>someSrcStr</a>
			<b>someDestinationStr</b>
		</field>
	</mapping>
	<mapping map-id="destA_as2sd">
		<class-a>AnotherSrcBean</class-a>
		<class-b>SomeDestinationBean</class-b>
		<field>
			<a>anotherSrcDbl</a>
			<b>someDestinationDbl</b>
		</field>
	</mapping>
</mappings>

...And the one for the second destination type (dozer-mapping-B.xml):

<?xml version="1.0" encoding="UTF-8"?>
<mappings xmlns="http://dozer.sourceforge.net"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="
	http://dozer.sourceforge.net
	http://dozer.sourceforge.net/schema/beanmapping.xsd"
	<mapping map-id="destB_ss2sd">
		<class-a>SomeSrcBean</class-a>
		<class-b>SomeDestinationBean</class-b>
		<field>
			<a>someSrcStr2</a>
			<b>someDestinationStr</b>
		</field>
	</mapping>
	<mapping map-id="destB_as2sd">
		<class-a>AnotherSrcBean</class-a>
		<class-b>SomeDestinationBean</class-b>
		<field>
			<a>anotherSrcDbl</a>
			<b>someDestinationDbl</b>
		</field>
	</mapping>
</mappings>

Spring configuration:

I have used spring to hook up the XML mappings to Java source (spring-beans.xml):

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.0.xsd"
<context:component-scan base-package="com.oz.dozer.mapper"/>
<context:annotation-config/>
<bean id="mapper" class="org.dozer.DozerBeanMapper">
  <property name="mappingFiles">
    <list>
      <value>dozer-mapping-A.xml</value>
      <value>dozer-mapping-B.xml</value>
    </list>
  </property>
</bean>
</beans>

TestNG Spring Run:

I have used testng spring context test to connect the dots and test this out:

@ContextConfiguration("classpath:spring-beans.xml")
public class TheMapperTestNg extends AbstractTestNGSpringContextTests {
	@Autowired
	private TheMapper theMapper;
	@Test
	public void mappingTest() {
		final SomeSrcBean ssb = new SomeSrcBean();
		final AnotherSrcBean asb = new AnotherSrcBean();
		final String someSrcStr = "TESTING!!";
		final String someSrcStr2 = "TESTING2!!";
		ssb.setSomeSrcStr(someSrcStr);
		ssb.setSomeSrcStr2(someSrcStr2);
		final double anotherSrcDbl = 666.66d;
		asb.setAnotherSrcDbl(anotherSrcDbl);
		final SomeDestinationBean sdb1 =
			theMapper.map(ssb, asb, "destA");
		AssertJUnit.assertEquals("Some str"
			, sdb1.getSomeDestinationStr(), someSrcStr);
		AssertJUnit.assertEquals("Another dbl"
			, sdb1.getSomeDestinationDbl(), anotherSrcDbl);
		final SomeDestinationBean sdb2 =
			theMapper.map(ssb, asb, "destB");
		AssertJUnit.assertEquals("Some str 2"
			, sdb2.getSomeDestinationStr(), someSrcStr2);
		AssertJUnit.assertEquals("Another dbl"
			, sdb2.getSomeDestinationDbl(), anotherSrcDbl);
	}
}


Active MQ Proof of Concept

This is a proof of concept blog about Active MQ using Tomee+ JMS, Servlet, Endpoint on the server side, and Angular, JS web sockets on the client side. Java testing is done via JUnit, Mockito. Javascript testing is done via Jasmine. Let's first start out by describing the maven setup of the project... 1. Maven Compiler plugin (the usual) version 3.1 and the project requires JDK 1.7 and up:

      <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.1</version>
        <configuration>
          <source>1.7</source>
          <target>1.7</target>
        </configuration>
      </plugin>

2. a) Jasmine Maven plugin simplifies integrating JS testing into maven test lifecycle goal (Notice the executions tag):

      <plugin>
        <groupId>com.github.searls</groupId>
        <artifactId>jasmine-maven-plugin</artifactId>
        <version>1.3.1.5</version>
        <executions>
          <execution>
            <goals>
              <goal>test</goal>
            </goals>
          </execution>
        </executions>
      </plugin>

2. b) We add some custom configuration to Jasmine Maven plugin to support Angular testing with a selenium chrome driver (angular-mocks helps with mocking the angular plumbing), and we have a customized JS source directory (default is src/main/javascript):

      <plugin>
        <groupId>com.github.searls</groupId>
        <artifactId>jasmine-maven-plugin</artifactId>
        <version>1.3.1.5</version>
        <configuration>
          <webDriverClassName>
	   org.openqa.selenium.chrome.ChromeDriver
	  </webDriverClassName>
          <preloadSources>
            <source>${jquery.load.path}/jquery.js</source>
            <source>${angular.load.path}/angular.js</source>
            <source>${angular.load.path}/angular-mocks.js</source>
          </preloadSources>
          <jsSrcDir>${project.basedir}/src/main/webapp/js</jsSrcDir>
        </configuration>
        <executions>
          <execution>
            <goals>
              <goal>test</goal>
            </goals>
          </execution>
        </executions>
      </plugin>

3. a) Last piece is a TOMEE maven plugin that helps with packaging/deploying to a TOMEE server and starting debugging

      <plugin>
        <groupId>org.apache.openejb.maven</groupId>
        <artifactId>tomee-maven-plugin</artifactId>
        <version>1.7.1</version>
      </plugin>

3. b) We add reload synchronization configuration to TOMEE maven plugin that automates hot code deploy (Java, JS or HTML changes) to a TOMEE+ server at debug mode:

      <plugin>
        <groupId>org.apache.openejb.maven</groupId>
        <artifactId>tomee-maven-plugin</artifactId>
        <version>1.7.1</version>
        <configuration>
          <tomeeVersion>1.7.1</tomeeVersion>
          <tomeeClassifier>plus</tomeeClassifier>
          <synchronization>
            <extensions>
              <extension>.class</extension>
              <extension>.js</extension>
              <extension>.html</extension>
            </extensions>
          </synchronization>
          <reloadOnUpdate>true</reloadOnUpdate>
        </configuration>
      </plugin>

4. Following maven dependencies are added to the project. Log4j is the usual logging library. Javax servlet, websocket and JMS are needed for server-side setup. GSON is a JSON library. JUnit, and mockito are needed for java testing. Jasmine and Selenium are needed for client-side JS testing:

  <dependencies>
	<dependency>
		<groupId>log4j</groupId>
		<artifactId>log4j</artifactId>
		<version>1.2.17</version>
	</dependency>
	<dependency>
		<groupId>javax.servlet</groupId>
		<artifactId>javax.servlet-api</artifactId>
		<version>3.1.0</version>
	</dependency>
	<dependency>
		<groupId>javax.jms</groupId>
		<artifactId>javax.jms-api</artifactId>
		<version>2.0.1</version>
	</dependency>
	<dependency>
		<groupId>javax.websocket</groupId>
		<artifactId>javax.websocket-api</artifactId>
		<version>1.1</version>
	</dependency>
	<dependency>
		<groupId>com.google.code.gson</groupId>
		<artifactId>gson</artifactId>
		<version>2.3.1</version>
	</dependency>
	<dependency>
		<groupId>junit</groupId>
		<artifactId>junit</artifactId>
		<version>4.11</version>
		<scope>test</scope>
	</dependency>
	<dependency>
		<groupId>org.mockito</groupId>
		<artifactId>mockito-all</artifactId>
		<version>1.10.19</version>
		<scope>test</scope>
	</dependency>
	<dependency>
		<groupId>com.github.searls</groupId>
		<artifactId>jasmine-maven-plugin</artifactId>
		<version>1.3.1.5</version>
		<scope>test</scope>
	</dependency>
	<dependency>
		<groupId>org.seleniumhq.selenium</groupId>
		<artifactId>selenium-chrome-driver</artifactId>
		<version>2.3.1</version>
		<scope>test</scope>
	</dependency>
 </dependencies>

Next, let's take a look at the client-side...

1) We will start out with HTML for the Producer page:

We include angular library at the head, and add angular app/controller JS at the bottom of HTML body by convention. There is a simple form with a text area and submit button. Text area is required for the form and the button is disabled unless the form text area has something in it. On the bottom of the form, we have a small space for feedback from the server:

<!DOCTYPE html>
<html ng-app="producerApp">
<head>
 <meta charset="ISO-8859-1">
 <title>Producer</title>
 <script
 src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"
 ></script>
</head>
<body>
 <div ng-controller="producerCtrl">
  <form name="produceForm" ng-submit="produce()">
   <h2>Message</h2>
   <p>
   <textarea ng-model="message" name="message" rows="25" cols="40" required>
   </textarea>
   </p>
   <p>
   <button type="submit"
   ng-disabled="produceForm.$pristine ||!produceForm.$dirty"
   >Produce</button>
   </p>
  </form>
  <div>{{feedback}}</div>
 </div>
 <script src="js/producerApp.js"></script>
 <script src="js/producerCtrl.js"></script>
</body>
</html>

2) Next, let's take a look at HTML for the Consumer page:

Again, we include angular library at the head, and add angular app/controller JS at the bottom of HTML body by convention. There is a simple read-only text area where messages we listen to will show up:

<!DOCTYPE html>
<html ng-app="consumerApp">
<head>
 <meta charset="ISO-8859-1">
 <title>Consumer</title>
 <script
 src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"
 ></script>
</head>
<body>
 <div ng-controller="consumerCtrl">
  <h2>Message(s)</h2>
  <p>
  <textarea ng-model="message" name="message" rows="25" cols="40" readonly>
  </textarea>
  </p>
 </div>
 <script src="js/consumerApp.js"></script>
 <script src="js/consumerCtrl.js"></script>
</body>
</html>

3) Next, we move onto Angular.JS for the Producer page:

Here is the producer angular app:

/**
 * Producer App
 */
var app = angular.module("producerApp", []);

...and the producer controller which talks to the JMS producer servlet to send the message and get a feedback of message receipt:

/**
 * Producer Controller
 */
app.controller("producerCtrl", function($scope, $http, $location) {
	$scope.jmsMode = "PUBLISH_TO_TOPIC";
	$scope.jpsUrl =
	 "http://localhost:"+$location.port()+"/_testing_/JPS/produce.do";
	$scope.message = "";
	$scope.feedback = "";
	$scope.produce = function() {
		$http.post($scope.jpsUrl, {
			 mode : $scope.jmsMode
			,msg: $scope.message
		})
		.success(function(data, status, headers, config){
			$scope.feedback = "Success: "+data;
		})
		.error(function(data, status, headers, config){
			$scope.feedback = "Error: "+data;
		});
	};
});

4) On the consumer client side we have the following Angular.JS:

The consumer app:

/**
 * Consumer App
 */
var app = angular.module("consumerApp", []);

...and the consumer controller that establishes a web socket connection to the message consumer server endpoint to listen to any messages:

/**
 * Consumer Controller
 */
app.controller("consumerCtrl", function($scope, $location) {
	$scope.endpointUrl =
	 "ws://localhost:"+$location.port()+"/_testing_/endpoint";
	$scope.message = "";
	var webSocket = new WebSocket($scope.endpointUrl);
	webSocket.onerror = function (event) {
		$scope.message = event.data;
		$scope.$apply();
	};
	webSocket.onopen = function(event) {
		webSocket.send("Connected");
	};
	webSocket.onmessage = function(event) {
		if (event && event.data) {
			var jsonObj = JSON.parse(event.data);
			$scope.message = $scope.message + '\n'
				+ jsonObj.timeStamp + ': '+ jsonObj.msg;
			$scope.$apply();
		}
		webSocket.send("listen");
	};
	$scope.$on('$destroy', function() {
		webSocket.close(); //Close web socket connection
	});
});

Now, for the server-side...

1) The JMS producer servlet is a simple servlet that defines a JMS topic and a connection factory resources (via TOMEE+ injection binding). 

public final class JmsProducerServlet extends HttpServlet {
...
	@Resource(name = "foo")
	private Topic fooTopic;
	@Resource
	private ConnectionFactory jmsConnFactory;
...

On a POST from the client side: 

   @Override
   protected void doPost(HttpServletRequest req, HttpServletResponse resp)
    throws ServletException, IOException
   {
   ...

a) Creates/starts a JMS connection

	jmsConn = jmsConnFactory.createConnection();
	jmsConn.start();

b) Creates a JMS session (no transaction, auto acknowledge message sent)

	jmsSession =
	  jmsConn.createSession(false,Session.AUTO_ACKNOWLEDGE);

c) Parses the JSON request (via Gson) to extract message to be sent

	final Request jsonReq =
		gson.fromJson(req.getReader(), Request.class);

d) Creates a non-persistent message producer for the JMS topic

	final MessageProducer producer =
		jmsSession.createProducer(fooTopic);
	producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);

e) Creates/sends the JMS message envelope and put the message in that was extracted

	// Create a message
	final TextMessage message = jmsSession.createTextMessage(msg);
	// Tell the producer to send the message
	producer.send(message);

f) Returns a feedback to caller

	//Write back ack to response
	pw.println(SUCCESS_MSG);

2) The JMS consumer server endpoint also utilizes TOMEE+ binding to create the same JMS topic by name and a connection factory resource:

@ServerEndpoint(value = "/endpoint")
public final class JmsConsumerServerEndPoint {
...
	@Resource(name = "foo")
	private Topic fooTopic;
	@Resource
	private ConnectionFactory jmsConnFactory;
...

a) On a web socket open request from the client-side:

    @OnOpen
    public void onOpen(final Session session) {

It creates/starts a JMS connection and session (again no transaction, auto acknowledge message receipt):

	jmsConn = jmsConnFactory.createConnection();
	jmsConn.start();
	jmsSession =
	 jmsConn.createSession(false, javax.jms.Session.AUTO_ACKNOWLEDGE);

b) On a web socket request to listen:

    @OnMessage
    public String onMessage(final String message, final Session session) {
     ...
     switch (message) {
     case "listen":

It creates a JMS consumer of the topic and waits to receive the message:

	// Create a MessageConsumer from the Session for the Topic or Queue
	final MessageConsumer consumer =
	  jmsSession.createConsumer(fooTopic);
	// Wait to receive the message
	final Message msg = consumer.receive();

When there is a JMS message to be consumed, it wraps it up into a JSON response and sends it back to the client:

	...
        else if (msg instanceof TextMessage)
	{//Send back msg text to response
	    resp = new Response((TextMessage)msg);
	}
	...
	return new Gson().toJson(resp);

c) It is a good idea to clean up the JMS resources on closing of the web socket:

   @OnClose
   public void onClose(final Session session, final CloseReason closeReason) {
	...
	try {
		if (session.isOpen()) {
			session.close();
		}
		if (jmsSession != null) {
			jmsSession.close();
		}
		if (jmsConn != null) {
			jmsConn.stop();
			jmsConn.close();
		}
	}
	catch (JMSException | IOException e) {
		logger.debug("Problem closing resources", e);
	}
   }

How about some Java Unit Testing...

1) We utilize mockito annotations to mock out the JMS communication portion of the JMS producer servlet to test the behavior:

@RunWith(MockitoJUnitRunner.class)
public class TestJmsProducerServlet {
	@Mock(name = "jmsConnFactory")
	private ConnectionFactory mockJmsConnFactory;
	@InjectMocks
	private JmsProducerServlet servlet;
	@Mock
	private HttpServletRequest mockReq;
	@Mock
	private HttpServletResponse mockResp;
	@Mock
	private Connection mockJmsConn;
	@Mock
	private Session mockJmsSession;
	@Mock
	private MessageProducer mockProducer;
	...
	@Before
	public final void beforeTest() throws Exception {
		Mockito
		.when(mockJmsConnFactory.createConnection())
		.thenReturn(mockJmsConn);

		Mockito
		.when(mockJmsConn.createSession(
			Mockito.anyBoolean(), Mockito.anyInt()))
		.thenReturn(mockJmsSession);

		Mockito.when(mockJmsSession.createProducer(
			Mockito.any(Destination.class)))
		.thenReturn(mockProducer);
	}
	...

2) Same goes for the JMS consumer endpoint:

@RunWith(MockitoJUnitRunner.class)
public class TestJmsConsumerServerEndPoint {
	@Mock(name = "jmsConnFactory")
	private ConnectionFactory mockJmsConnFactory;
	@InjectMocks
	private JmsConsumerServerEndPoint endPoint;
	@Mock
	private Session mockSession;
	@Mock
	private MessageConsumer mockConsumer;
	...

How about some Javascript Jasmine Testing...

We utilize angular-mocks.js to mock out the angular client/server communication:

/**
 * Testing client-side producer
 */
describe('Producer Controller', function() {
	var $httpBackend, $rootScope, createController;
	beforeEach(module('producerApp'));
	beforeEach(inject(function($injector) {
		// Set up the mock http service responses
		$httpBackend = $injector.get('$httpBackend');
		// Get hold of a scope (i.e. the root scope)
		$rootScope = $injector.get('$rootScope');
		// The $controller service is used
		//to create instances of controllers
		var $controller = $injector.get('$controller');
		createController = function() {
			return $controller('producerCtrl'
				, {'$scope' : $rootScope });
		};
	}));
	afterEach(function() {
		$httpBackend.verifyNoOutstandingExpectation();
		$httpBackend.verifyNoOutstandingRequest();
	});

Here is a test of the post the message to producer servlet:

	it('should send a successful post message to JMS Producer Servlet (JPS)', function() {
		var testToken = 'TESTING!!';
		$httpBackend.expectPOST(testToken
			, {mode : testToken, msg: testToken})
		   .respond(testToken);
		createController();
		$rootScope.jmsMode = testToken;
		$rootScope.jpsUrl = testToken;
		$rootScope.message = testToken;
		$rootScope.produce();
		$httpBackend.flush();
		expect($rootScope.feedback)
		   .toEqual("Success: "+testToken);
	});

You can download a compressed version of the whole project here.

How do you run it? Depends on the IDE, I use Eclipse maven launcher to package it:

... and here is my launcher to start TOMEE+ in debug mode (listening to any changes in source code to reload):


About


Producing high-end quality, fully-tested software units based on constant collaboration with our customers to deduce exact specifications.

Striving to understand the business workflows to design custom-tailored software to fit the needs from management/owner level to end-users of our clients.