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:
- clone the repo above
- run mvn jetty:run
- Now browse to http://localhost:8080 to see the front page
-
There are two parts to the app
- 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.
- 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:
- 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.
- EventBroadcaster – creates a broadcast channel in the ctor. Provides APIs to publish messages on this channel.
- HelloService – basic echo service taken from Maven archetype
- 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
- Snappy web based config – felt great that I could set up a CI build with essentially the repo path alone
- Plugin system!
- Deep maven2 integration (though read on below that this isnt always what works)
- 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
- 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
- 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 hereWith 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. - 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!
- 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());
}
}

