Nifty tidbits

Nifty tidbits and random thoughts on technology and anything else that catches my fancy

Tag Archives: Java

Websocket server using Jetty/Cometd

So I just wrote up a Websocket server using CometD/Bayeux. It’s a ridiculously simple app – but went quite a long way in helping to understand the nitty gritties with putting up a Websocket server and CometD/Bayeux. Thought that I’ll put it up for reference – should help in getting a leg up on getting started with CometD.

The sample’s up on github at https://github.com/raghur/rest-websocket-sample

Here’s how to go about running it:

  1. clone the repo above
  2. run mvn jetty:run
  3. Now browse to http://localhost:8080 to see the front page
  4. There are two parts to the app

    1. A RESTful API at http://localhost:8080/user/{name} – hypothetical user info – get retrieves a user, put creates a user and delete obviously deletes the user.
    2. The websocket server at localhost:8080/cometd has a broadcast channel at /useractivity which receives events whenever a user is added/deleted. The main page at http://localhost:8080 has a websocket client that updates the page with the user name whenever a user is added or removed.

And here’s the nuts and bolts:

  1. BayeuxInitializer – initializes the Bayeux Service and the EventBroadcaster. Puts the EventBroadcaster in the servlet context from where the RESTful service can pick it up to broadcast.
  2. EventBroadcaster – creates a broadcast channel in the ctor. Provides APIs to publish messages on this channel.
  3. HelloService – basic echo service taken from Maven archetype
  4. MyResource – the RESTful resource which responds to GET/PUT/DELETE – nothing major here. If a user is added or deleted, then it pushes a message on the broadcast channel by getting the EventBroadcaster instance from the servlet context.

It’s about as simple as you can get (beyond a Hello world or a chat example). Specifically, I wanted a sample where back end changes can be pushed to clients.

Unit testing Apache CXF RESTful services – code available

So, the original post on the topic written about two and a half years ago had code snippets, but there’s been comments and PMs for the complete code. So last week, as I resurrected this blog, decided to get that code out on github. Unfortunately, that was easier said than done; it has been quite some time and frankly, I’d lost the code. I must’ve switched machines about 3 times in the interim and gone from SVN to github for personal projects. Some hunting around ensued and thankfully, I was able to find the actual code we wrote based on the sample I’d posted. So cleaned that up – and just extracted the unit testing example out of it and pushed it to github – get it here. I haven’t updated any of the dependencies – so this is still running against spring 2.5 and cxf 2.2.3 (I think) and things might’ve changed quite a bit since then (I haven’t used the JAXRS bits of CXF much after that)

Running tests:

        mvn test

Running the server:

        mvn jetty:run

Hudson for CI – Tips, Tricks and insights

Just started using Hudson recently and I’m wowed! It’s head and shoulders above CruiseControl and things that I like a lot are

  1. Snappy web based config – felt great that I could set up a CI build with essentially the repo path alone
  2. Plugin system!
  3. Deep maven2 integration (though read on below that this isnt always what works)
  4. Trending data OOB – essentially giving you nice charts about how your build is doing over time

Now that I’ve said all the very nice things about it, here’s a few things that were hard to figure out/or weren’t immediately apparent. If your maven builds aggregates modules then you’ll find the experience a bit challenging

  1. The generated site doesnt work: Basically, the link is to one of the modules’ site instead of a link to the parent project. This apparently is a known issue and the solution on hudson user list is to run the site:deploy goal and have a link in the project description to point to that url
  2. Code coverage: none of the coverage tools (EMMA, clover etc) support code coverage over a multi module build. Since coverage is very important to me, I eventually resorted to having separate build jobs instead of using the default multi module support. Here’s how my svn structure looks

    /trunk/basebuild #contains the parent pom
    /trunk/project1 # pom refers to ../basebuild/pom.xml
    /trunk/project2 # ditto here

    With the directory structure above, there are build jobs for project1 and project2. Each build job checks out both the project folder (/trunk/project1) and the basebuild folder so that the POM references work.
    One undesirable effect of this set up is that if project 2 depends on project 1, then project 1 build will have to install the artifact to the local repo for the project2 build to work.

  3. Findbugs plugin – Running maven builds with findbugs configured did a Out of Memory (OOM) and failed the build. I tried setting MAVEN_OPTS to -Xmx512M at a bunch of places and nothing worked. Eventually, it turned out that the right place to specify it is in the Hudson COnfigure job page in the build section!
  4. Violations plugin – This is a great little hudson plugin. However, I couldnt get this to work with a inherited POM setup above. Eventually resorted to using Findbugs and PMD hudson plugins individually.

I should mention that I’m running hudson 1.321 with the latest plugins. If you have any tips to share on running hudson – please do drop a link in the comments. Overall, a great big ‘thank you’ to the Hudson folks!

Recipe: Unit testing Apache CXF RESTful services

Recently, decided to use Apache CXF to expose a service with a RESTful API. Part of the reason for choosing REST had more to do with the fact that the client is going to be a mobile client. These days, though mobile devices stacks have come a long way and provide SOAP clients, it still seems prudent to not depend on a whole slew of technologies where plain ‘ole HTTP and JSON might do the trick.
As I started exploring CXF, I liked the JAX-RS implementation and decided to go ahead with it – however, almost immediately, hit a snag when I went on to write test cases. Apache CXF documentation is not quite there and things do require some investigation – at least initially till you get a hang of the framework. As it took time to figure out the solution, it makes sense to share it on blogosphere. Here’s how to go about writing unit tests:

Firstly, the service and the service implementation:

package com.aditi.blackberry.web;

import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Response;

@Path("/chat")
@Produces("application/json")
public interface ChatWebService {

 @POST
 @Path("connect")
 public Response connect(@FormParam("user")String username, @FormParam("pass")String password);
}

The service implementation:

package com.aditi.blackberry.web;

import javax.ws.rs.Produces;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;

@Produces("application/json")
public class ChatWebServiceImpl implements ChatWebService {

 public Response connect(String username, String password) {
 if(username ==null || "".equals(username) ||
 password ==null || "".equals(password)) {
 return Response.status(Status.BAD_REQUEST).build();
 }
 String[] response = {username, password};
 return Response.ok(response).build();
 }
}

The corresponding spring context xml (applicationContext.xml) is:

<?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:p="http://www.springframework.org/schema/p"
	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:jaxrs="http://cxf.apache.org/jaxrs" xmlns:cxf="http://cxf.apache.org/core"
	xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-2.5.xsd


http://www.springframework.org/schema/aop


http://www.springframework.org/schema/aop/spring-aop-2.5.xsd


http://www.springframework.org/schema/tx


http://www.springframework.org/schema/tx/spring-tx-2.5.xsd

       http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd
       http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd">

	<import resource="classpath:META-INF/cxf/cxf.xml" />
	<import resource="classpath:META-INF/cxf/cxf-extension-jaxrs-binding.xml" />

	<bean id="logInbound" class="org.apache.cxf.interceptor.LoggingInInterceptor" />
	<bean id="logOutbound" class="org.apache.cxf.interceptor.LoggingOutInterceptor" />
	<!--
     logging
     -->
	<cxf:bus>
		<cxf:inInterceptors>
			<ref bean="logInbound" />
		</cxf:inInterceptors>
		<cxf:outInterceptors>
			<ref bean="logOutbound" />
		</cxf:outInterceptors>
		<cxf:inFaultInterceptors>
			<ref bean="logOutbound" />
		</cxf:inFaultInterceptors>
	</cxf:bus>
	<jaxrs:server id="jaxrsservice" address="${server.address}" >
		<jaxrs:serviceBeans>
			<ref bean="chatwebservice" />
		</jaxrs:serviceBeans>
		<jaxrs:providers>
			<ref bean="flexjsonprovider"/>
		</jaxrs:providers>
	</jaxrs:server>
	<bean id="flexjsonprovider" class="com.aditi.blackberry.web.FlexJsonMessageBodyWriter" />
	<bean id="chatwebservice" class="com.aditi.blackberry.web.ChatWebServiceImpl" />
</beans>

A few things to note here – logging is turned on using interceptors and the jaxrs server is defined. I’m also using flexJson to convert arbitrary objects to json – so a MessageBodyWriter bean is also injected into the jaxrs server node. The most important thing is that we havent included either the cxf-servlet.xml config for the cxf-extension-http-jetty.xml. Essentially, what we want to do is for the actual build, include cxf-servlet.xml and for the test runs, run the service on the bundled jetty server.

So, go ahead and define a applicationContext-web.xml:

        <bean id="propertyConfigurer"
		class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:/build.properties" />
	</bean>
	<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
	<import resource="classpath:/applicationContext.xml" />

This is the context xml that we’ll provide to the ContextLoaderListener in our web.xml.

For the test cases, define applicationContext-test.xml – this is the context xml which we’ll load from the test cases.

	<bean id="propertyConfigurer"
		class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:/test.properties" />
	</bean>
	<import resource="classpath:META-INF/cxf/cxf-extension-http-jetty.xml" />
	<import resource="classpath:/applicationContext.xml" />
	<jaxrs:client id="chatclient" address="${server.address}" serviceClass="com.aditi.blackberry.web.ChatWebService">
		<jaxrs:headers>
			<entry key="Accept" value="application/json"></entry>
		</jaxrs:headers>
	</jaxrs:client>

As you see, we also define a jaxrs:client for the test context xml.

There’s one final issue to address – which is that we would ideally like the urls we use to access the service to be the same. The spring jaxrs:server binding takes an address attribute which defines the url the service is hosted on. For deployment onto an external container, this takes the form of “/myservice” – a path element relative to the context location. For the internal jetty hosted service, it takes the full http path (http://localhost:port/my/path/to/service). The easiest way is to have this set using a property reference in spring and have the applicationContext-web.xml and applicationContext-test.xml load different property files as shown in above.

For completeness, here’s the web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

	<display-name>CXF REST Example</display-name>
	<description>CXF REST Example</description>

	<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:/applicationContext-web.xml</param-value>
	</context-param>
	<listener>
	<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>

	<servlet>
		<servlet-name>CXFServlet</servlet-name>
		<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
		<load-on-startup>1</load-on-startup>
	</servlet>

	<servlet-mapping>
		<servlet-name>CXFServlet</servlet-name>
		<url-pattern>/*</url-pattern>
	</servlet-mapping>

</web-app>

And finally, here’s a junit test case:

base class:

package com.aditi.blackberry.web;

import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:/applicationContext-test.xml" })
public abstract class AbstractApiTest {

	@Autowired
	@Qualifier("chatclient")
	protected ChatWebService proxy;
}

A test case for the connect API:

package com.aditi.blackberry.web;

import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;

import org.junit.Assert;
import org.junit.Test;

public class ConnectApiTest extends AbstractApiTest{
	@Test
	public void testConnect() {
		Response resp = proxy.connect("raghu", "password");
		Assert.assertTrue(resp.getStatus() == 200);
		System.out.println(resp.getEntity().toString());
	}
}
Follow

Get every new post delivered to your Inbox.

Join 262 other followers