Jetty, Jersey and MySQL inside Eclipse
This article gives a step by step set of instructions to set up Eclipse to run a Jetty application container using Jersey RESTful annotations and talk to a MySQL database. You would have thought that with all these technologies being really popular there would be loads of really helpful documentation and help but in reality the forums of the internet are overflowing with people having trouble with this. So let’s start from the beginning and see if we can’t work through it together - ok with me doing all the work.
For the purposes of simplicity we’ll be installing all the software into the
c:\java
folder.
First up we’ll install Eclipse. We are going to create a Dynamic Web Project. We must install the JEE build of Eclipse because it comes with all the supporting dependencies that we need so there won’t be many additional plugins we’ll have to install. Just for your records I did this with Java EE IDE for Web Developers Helios Service Release 2 Build id: 20110218-0911.
- Head over to the Eclipse download page at: http://www.eclipse.org/downloads/
- We want the Eclipse IDE for Java EE Developers which comes in at a whopping 206 MB, one of the larger builds. Thanks to my lovely 50MB Virgin broadband it only takes a couple of seconds!
- Unzip the downloaded package eclipse-jee-helios-SR2-win32.zip into
c:\java\eclipse
. - Run up Eclipse and select
c:\java\workspace
as the …erm workspace!
- Load Eclipse in.
- From the menu bar select Help -> Install New Software…
- Click the Add… button to add a new repository.
- For the Name enter Run Jetty Run
- for the Location enter
http://run-jetty-run.googlecode.com/svn/trunk/updatesite - then click Ok.
- Eclipse will go to the repository and download a list of the installable that can be downloaded. Expand them all and check the option with the highest version number. At the time of writing it is: Run Jetty Run 1.2.1.1.
- Click Finish to download and install it.
- Project name = carshare
- Target runtime = <None>
- Dynamic web module version = 3.0
- Configuration = JavaServer Faces v2.0 Project (this is really up to you)
- Select Next
- On the Web Module page, check the box for Generate web.xml deployment descriptor. This creates a starting
web.xml
file for you. Without this, the system is difficult to configure down the line. - If you selected JavaServer Faces v2.0 Project then you will have to choose an implementation to use. Click the download button (which looks like a floppy disc with a down arrow next to it) and select Apache’s Myfaces JSP Core-2.0 implementation. The first time I did this it said “failed to open zip", so I tried again and it worked!
- Clicked Finish and let it whoor away.
c:\java\jersey-archive-1.6
and copy all the jar files from c:\java\jersey-archive-1.6\lib
to c:\java\workspace\carshare\WebContent\WEB-INF\lib
.
While we are here we’ll install the MySQL driver jar as well.
- Hop over to MySQL’s connector/J download page: http://dev.mysql.com/downloads/connector/j/
- If you can read tar.gz files then you might as well get that version because it is 200K smaller.
- Uncompress it and copy the mysql-connector-java-5.1.15.jar file into
c:\java\workspace\carshare\WebContent\WEB-INF\lib
- Right click on the src root package and create a new package calling it
uk.co.bigsoft.carshare
. - Once the package is created, right click on it and select New -> Class.
- Call the class
Person
. - Enter the following java code into the
Person
class:package uk.co.bigsoft.carshare; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; @Path("/person") public class Person{ @GET @Path("/list") @Produces(MediaType.TEXT_HTML) public String sayHtmlHello() { return "<html><body><h1>" + "Hello MrN" + "</h1></body>"; } }
- Save the class.
- @Path - to get to this class go to
/person
, to go to thesayHtmlHello()
method go to/person/list
. - @GET - type of request. So you can have @POST, @DELETE and @PUT.
- @Produces - take the return type and renders it automatically into the type you specify. If you change the
MediaType
toAPPLICATION_JSON
and return a POJO instead, Jersey will automatically convert it to JSON without any extra coding. There is also a @Consumes to handle data coming inwards.
c:\java\workspace\carshare\WebContent\WEB-INF\web.xml
to include the following XML.
<servlet>
<servlet-name>Jersey REST Service</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>uk.co.bigsoft.carshare</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Jersey REST Service</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
The package uk.co.bigsoft.carshare
is the top level package. All classes and sub-packages will be searched for classes that have been annotated with …erm annotations! All @Paths will appear under the /rest/
URL, so with the example above the URL path will be /rest/person/list
.
If you have done it correctly you will see Jersey REST Service under <eclipse-project> -> Deployment Descriptor: uk.co.bigsoft.carshare -> Servlets and
/rest/* -> Jersey REST Service under <eclipse-project> -> Deployment Descriptor: uk.co.bigsoft.carshare -> Servlet Mappings.
Now we are ready to run. From the menu select Run -> Debug Configurations. Highlight Jetty Webapp, right click and select New. Everything will be automagically filled in for you so just click Debug.
Jetty will start up inside Eclipse so using your favourite browser navigate to: http://localhost:8080/carshare/rest/person/list
and you should see the text “Hello MrN".
Happy that everything is in place we can configure the webapp to talk to MySQL. This took me all day to solve. For such a common set of technologies there is little or no documentation. The information I found was on forums, mail lists and Stack Overflow. All the information I found was wrong and it was just a fluke I hit the right answer with a bit of trial and error.
We have already installed the MySQL Connector/j so all that is left to do is add the configuration. We are going to add MySQL as a JNDI datasource. Edit the c:\java\workspace\carshare\WEB-INF\web.xml
in Eclipse and add the following lines:
<resource-ref>
<description>My DataSource Reference</description>
<res-ref-name>jdbc/carshare</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource>
That defines a resource called jdbc/carshare and the interface it uses, but we need to define what the resource actually looks like. This part of the configuration is somewhat container specific so we need to put it into a separate file. All the documentation says to use WEB-INF/jetty-env.xml
but this is actually ignored by Jetty so you have to call it c:\java\workspace\carshare\WEB-INF\jetty-web.xml
.
Next, create the following context definition:
<?xml version="1.0"?>
<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://jetty.mortbay.org/configure.dtd">
<configure class="org.mortbay.jetty.webapp.WebAppContext">
<new id="carshare" class="org.mortbay.jetty.plus.naming.Resource">
<arg></arg>
<arg>jdbc/carshare</arg>
<arg>
<new class="com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource">
<set name="Url">jdbc:mysql://localhost:3306/carshare</set>
<set name="User">mrn</set>
<set name="Password">hard2crack</set>
</new>
</arg>
</new>
</configure>
And now for the final stage. We need to call an instance of the datasource into existence from inside our RESTful class.
All the documentation I read said you just have to add:
InitialContext ctx = new InitialContext();
ds = (DataSource) ctx.lookup("java:comp/env/jdbc/carshare");
to your code and it would all work. Well every time a called new InitialContext()
it returned an empty (or blank) Context
so my lookup always failed. To get around this you need to add a c:\java\workspace\carshare\WEB-INF\lib\jndi.properties
containing some magic “make-it-work” lines
java.naming.factory.url.pkgs=org.mortbay.naming
java.naming.factory.initial=org.mortbay.naming.InitialContextFactory
Add jetty-name-ver.jar
and jetty-plus-ver.jar
to WEB-INF/lib
as well.
Finally the name I was getting the exception: java:comp/env/jdbc/carshare javax.naming.NameNotFoundException; remaining name ‘env/jdbc/carshare’All the Jetty documentation says that if you name the resource jdbc/carshare then Jetty’s context will automatically add the
java:comp/env
so it fits in with other application containers. This was not my experience. The only name I could look up was jdbc/carshare. So I changed the code to the following and all was good.
InitialContext ctx = new InitialContext();
ds = (DataSource) ctx.lookup("jdbc/carshare");
There is no way I could have done this without the help of the following articles and a bit of luck!
Jersey + eclipse: http://www.vogella.de/articles/REST/article.html
Install run-jetty-run: http://code.google.com/p/run-jetty-run/wiki/GettingStarted
http://stackoverflow.com/questions/2131798/jetty-mysql-connection-pool-configuration-error-javax-naming-namenotfoundexcepti2 comments
Comment from: riatiger [Visitor]
Nice article, but looks like it is unfinished. Can you please complete example and show how to load data from database and send in back to client?
Comment from: davidnewcomb [Member]
The next time I’m doing that kind of work I’ll update the article, but it won’t be any time soon. Maybe your suggestion can be an exercise for the reader.
Form is loading...