Summary
REST is about using the principles of the World Wide Web to build applications. REST stands for REpresentational State Transfer. REST offers a simple, interoperable, and flexible way of writing web services that can be very different than the RPC mechanisms like CORBA and WS-*; RESTful web services over HTTP tries to leverage HTTP in its entirety using specific architectural principles such as
- Addressable Resources (Every objects with its own specific URI)
- Uniform Constrained Interface (GET, POST, PUT & DELETE, etc)
- Representation Oriented (Referenced object in different representations [i.e] format)
- Communicate Statelessly (Highly scalable)
If we are provided with a tool to generate such RESTful web services, what more we need in the world (an exaggeration :))
Well the objective of this article is to provide a good start on automated generation of REST Web Services using MDA tool “AndroMDA”. Here we will create a new REST web services project.
The sections are classified in a simple manner to provide an easy understanding on the flow:
- Generating an AndroMDA J2EE Project
- UML Modeling using MagicDraw UML
- Modeling REST Web Services – Service, Method, & Parameter
- Configuration Setup for REST Web Services
- AndroMDA Code Generation, Compilation, & Build
- JAX-RS Data Bindings – Configuring Jackson JSON provider
- Coding on {Web Service}WSDelegate
- REST Web Service Security (JAX-RS – Security) – keeping the best to be covered in a separate article
- Download’s & Generated project from this Article
- Running Sample Demo Project of REST Web Services
Article and Sample Demo Project covers Web Service and Service layer with following framework:
- Apache CXF 2.6.2
- Spring 3.x
Generating an AndroMDA J2EE Project
One of my previous article talked about creating a J2EE project using AndroMDA. Check out the article (How to create Java/J2EE project using MDA tool – AndroMDA?) to get acquaintance with the steps to create a project. In a similar way follow the below given specification to create a project – REST web services using AndroMDA.
Web Services Project Generation Specification:
Type of Application : J2EE
Parent Directory : /Users/jeeva/Documents/andromda/ (Provide your system path)
First name and Last name : Jeevanandam Madanagopal (Provide your name)
Kind of Modeling Tool : UML2
Project Description : REST Web Services using AndroMDA
Project Maven Artifact Id : rest-webservice
Project Version : 1.0-SNAPSHOT
Project Root Package (maven group Id) : com.myjeeva.andromda.demo
Package Type : war
Type of transactional/persistence : spring
Programming Language for Service and DAO : Java
Database backend for the persistence layer : oracle
Workflow engine capabilities : No
Web user interface : No
Web Service Enabled : Yes
SOAP stack : CXF
JAX-WS REST provider/consumer media type : json
The embedded Jetty web server : Yes
Following the above response to the questions will end up getting your project generated successfully.
Let’s verify few essential things before we move to the next step UML modeling.
- Go to your Local Maven Repository and check this path for AndroMDA UML profiles
- {your-maven-repo-path}/org/andromda/profiles/uml2
- Have a look at AndroMDA generated project in the provided directory
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
mac-book-pro:rest-webservice jeeva$ ll total 152 drwxr-xr-x 4 jeeva staff 136B Sep 30 03:30 CXF/ drwxr-xr-x 3 jeeva staff 102B Sep 30 03:30 common/ drwxr-xr-x 4 jeeva staff 136B Sep 30 03:30 core/ -rw-r--r-- 1 jeeva staff 2.7K Sep 30 03:30 m2eclipse.bat drwxr-xr-x 9 jeeva staff 306B Sep 30 03:30 mda/ -rw-r--r-- 1 jeeva staff 68K Sep 30 03:30 pom.xml -rw-r--r-- 1 jeeva staff 0B Sep 30 03:30 readme.txt drwxr-xr-x 4 jeeva staff 136B Sep 30 03:30 webservice/ mac-book-pro:rest-webservice jeeva$ |
UML Modeling using MagicDraw UML
Considering the fact that we are familiar with MagicDraw, I picked up MagicDraw UML 17.0.1 tool to model. Open up the model file in the MagicDraw; as per our article, the location where the model is placed under
1 |
{base-directory}/rest-webservice/mda/src/main/uml/rest-webservice.xml |
While opening model file, MagicDraw will present you question of two Path Variables
1 2 3 |
maven2.repository – value is {path to your local maven repo} andromda3.root – value is {path to your local maven repo} |
For example: (below path as per my machine)
1 2 3 |
maven2.repository => /Users/jeeva/.m2/repository andromda3.root => /Users/jeeva/.m2/repository |
Now, model a couple of Value Objects, one REST web service resource class, few Methods in it.
Configuration Setup for REST Web Services
Note: After making changes to config files, don’t forget to save them 🙂
Open master POM (pom.xml) in your favorite text editor
- Look for following comment line in master POM, below these comment has an exclusion inside cxf-bundle dependencies. We have to comment out exclusions to enable REST dependencies –
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
<!-- Remove exclusion if using Apache Abdera for REST --> <!-- <exclusion> <groupId>org.apache.abdera</groupId> <artifactId>abdera-core</artifactId> </exclusion> <exclusion> <groupId>org.apache.abdera</groupId> <artifactId>abdera-i18n</artifactId> </exclusion> <exclusion> <groupId>org.apache.abdera</groupId> <artifactId>abdera-parser</artifactId> </exclusion> <exclusion> <groupId>org.apache.abdera</groupId> <artifactId>abdera-extensions-main</artifactId> </exclusion> <exclusion> <groupId>org.apache.abdera</groupId> <artifactId>abdera-extensions-json</artifactId> </exclusion> --> |
- CXF module is used to perform; java2ws portion of the build is only there to verify that the cxf code (jaxws annotations and references) generated by AndroMDA is valid for creating wsdl from the services, the result is not really used anywhere else. We are commenting out CXF module since we don’t require such verification for JAX-RS.
comment out <!-- module>CXF</module -->
in the master POM
Open MDA POM (mda/pom.xml) in your favorite editor
- comment out below line to stop deletion of *Impl’s during a code generation
1 2 3 4 5 |
<ant antfile="${project.basedir}/build.xml"> <target name="cleanImpl"/> </ant> |
Open andromda.xml (mda/src/main/config/andromda.xml) in your favorite editor :
- Updating property ‘outputEncoding‘ from ‘ISO-8859-1’ to ‘UTF-8’
1 |
<property name="outputEncoding">UTF-8</property> |
Modeling REST Web Services – Service, Method, & Parameter
Check out one of my article talk about UML Modeling AndroMDA, to acquire the modeling knowledge. This article covers the REST Web Service annotations in AndroMDA UML tag details. As per below package structure & UML diagram.
Let us move on to the third step after successfully completing our modeling!
AndroMDA Code Generation, Compilation, & Build
Just issue the following maven command for Code generation, compilation and Build.
1 2 3 |
mac-book-pro:~ jeeva$ cd {base-directory}/rest-webservice mac-book-pro:rest-webservice jeeva$ mvn install |
Now, wait for Code generation to get complete and you will see below message at the end.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
[INFO] Scanning for projects... [INFO] Reactor build order: [INFO] REST Web Services using AndroMDA [INFO] REST Web Services using AndroMDA MDA [INFO] REST Web Services using AndroMDA Common [INFO] REST Web Services using AndroMDA Core Business Tier [INFO] REST Web Services using AndroMDA Web Services [INFO] ------------------------------------------------------------------------ [INFO] Building REST Web Services using AndroMDA [INFO] task-segment: [install] [INFO] ------------------------------------------------------------------------ ... ... (many lines ....) ... [INFO] ------------------------------------------------------------------------ [INFO] Reactor Summary: [INFO] ------------------------------------------------------------------------ [INFO] REST Web Services using AndroMDA ...................... SUCCESS [5.614s] [INFO] REST Web Services using AndroMDA MDA .................. SUCCESS [43.725s] [INFO] REST Web Services using AndroMDA Common ............... SUCCESS [8.588s] [INFO] REST Web Services using AndroMDA Core Business Tier ... SUCCESS [9.417s] [INFO] REST Web Services using AndroMDA Web Services ......... SUCCESS [33.482s] [INFO] ------------------------------------------------------------------------ [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESSFUL [INFO] ------------------------------------------------------------------------ [INFO] Total time: 1 minute 42 seconds [INFO] Finished at: Sun Sep 30 15:48:23 GMT+05:30 2012 [INFO] Final Memory: 120M/265M [INFO] ------------------------------------------------------------------------ mac-book-pro:rest-webservice jeeva$ |
JAX-RS Data Bindings – Configuring Jackson JSON provider
@Consumes: The @Consumes
annotation is used to specify which MIME media types of representations a resource can accept, or consume, from the client.
@Produces: The @Produces
annotation is used to specify the MIME media types or representations a resource can produce and send back to the client.
If @Consumes/@Produces
is applied at the class level, all the response methods accept the specified MIME types by default. If @Consumes/@Produces
is applied at the method level, it overrides any @Consumes/@Produces
annotations applied at the class level.
MIME Media Types: It represents the data format in which Input (@Consumes
) and Output (@Produces
). It can be application/json, application/xml, text/plain, text/html, image/jpeg, image/png, application/octet-stream, application/x-www-form-urlencoded, etc.
For this demo purpose we stick to media type as JSON, hence we are configuring Jackson JSON library as provider.
Register either JacksonJsonProvider:
1 |
<bean id="jsonProvider" class="org.codehaus.jackson.jaxrs.JacksonJsonProvider"/> |
and add this Maven dependency into webservice/pom.xml:
1 2 3 4 5 6 7 8 9 |
<dependency> <groupId>org.codehaus.jackson</groupId> <artifactId>jackson-jaxrs</artifactId> <version>1.9.10</version> </dependency> |
OR JacksonJaxbJsonProvider (when working with JAXB beans): This article uses below approach
1 |
<bean id="jsonProvider" class="org.codehaus.jackson.jaxrs.JacksonJaxbJsonProvider"/> |
and add these Maven dependency into webservice/pom.xml:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
<dependency> <groupId>org.codehaus.jackson</groupId> <artifactId>jackson-jaxrs</artifactId> <version>1.9.10</version> </dependency> <dependency> <groupId>org.codehaus.jackson</groupId> <artifactId>jackson-xc</artifactId> <version>1.9.10</version> </dependency> |
Finally, refer above created bean as jaxrs:provider in the webservice/src/main/webapp/WEB-INF/applicationContext-CXF.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<jaxrs:server id="SearchService" address="/"> <jaxrs:serviceBeans> <bean class="com.myjeeva.andromda.demo.service.SearchServiceSEIImpl" /> </jaxrs:serviceBeans> <!-- Register custom providers if used in REST Services --> <jaxrs:providers> <ref bean="jsonProvider"/> </jaxrs:providers> </jaxrs:server> |
So, now we have modified the application context; let’s prevent from deletion during a code generation.
Open MDA build file (mda/build.xml) in your favorite editor,
Look for below line inside target ‘cleanWSDL’ and comment it out
1 |
<!-- <include name="webservice/src/main/webapp/**/applicationContext*.xml"/> --> |
Coding on {Web Service}WSDelegate
Now we will add our custom code snippet in the generated skeleton. Let us edit SearchServiceWSDelegate.java
under core module.
Execute below maven commands to get project ready for eclipse
1 2 3 |
mac-book-pro:rest-webservice jeeva$ mvn eclipse:eclipse -f common/pom.xml mac-book-pro:rest-webservice jeeva$ mvn eclipse:eclipse -f core/pom.xml |
Now maven modules are ready to import in eclipse as a project, let’s do it.
Open SearchServiceWSDelegate.java and modify the method ‘performSearch‘ & add the following following code snippet:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
SearchResultVO searchResult = new SearchResultVO(); DocumentVO document1 = new DocumentVO(); document1.setId("MA147LL/A"); document1.setName("Apple 60 GB iPod with Video Playback Black"); document1.setInStock(Boolean.TRUE); document1.setPrice(Double.valueOf(399.0)); document1.getFeatures().add("iTunes, Podcasts, Audiobooks"); document1.getFeatures().add("Stores up to 15,000 songs, 25,000 photos, or 150 hours of video"); document1.getFeatures().add("2.5-inch, 320x240 color TFT LCD display with LED backlight"); document1.getFeatures().add("Plays AAC, MP3, WAV, AIFF, Audible, Apple Lossless, H.264 video"); document1.getFeatures().add("Notes, Calendar, Phone book, Hold button, Date display, " + "Photo wallet, Built-in games, JPEG photo playback, Upgradeable " + "firmware, USB 2.0 compatibility, Playback speed control, " + "Rechargeable capability, Battery level indication"); DocumentVO document2 = new DocumentVO(); document2.setId("6H500F0"); document2.setName("Maxtor DiamondMax 11 - hard drive - 500 GB - SATA-300"); document2.setInStock(Boolean.FALSE); document2.setPrice(Double.valueOf(350.0)); document2.getFeatures().add("SATA 3.0Gb/s, NCQ"); document2.getFeatures().add("8.5ms seek"); document2.getFeatures().add("16MB cache"); DocumentVO document3 = new DocumentVO(); document3.setId("IW-02"); document3.setName("iPod &amp; iPod Mini USB 2.0 Cable"); document3.setInStock(Boolean.TRUE); document3.setPrice(Double.valueOf(11.5)); document3.getFeatures().add("car power adapter for iPod, white"); searchResult.getDocuments().add(document1); searchResult.getDocuments().add(document2); searchResult.getDocuments().add(document3); return searchResult; |
Let’s build it again to reflect our changes!
1 |
mac-book-pro:rest-webservice jeeva$ mvn install |
you will see following success message!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
[INFO] ------------------------------------------------------------------------ [INFO] Reactor Summary: [INFO] ------------------------------------------------------------------------ [INFO] REST Web Services using AndroMDA ...................... SUCCESS [6.115s] [INFO] REST Web Services using AndroMDA MDA .................. SUCCESS [51.900s] [INFO] REST Web Services using AndroMDA Common ............... SUCCESS [8.421s] [INFO] REST Web Services using AndroMDA Core Business Tier ... SUCCESS [6.697s] [INFO] REST Web Services using AndroMDA Web Services ......... SUCCESS [32.196s] [INFO] ------------------------------------------------------------------------ [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESSFUL [INFO] ------------------------------------------------------------------------ |
Download’s & Generated project from this Article
You can clone it from GitHub or download the Zip version. It includes the Demo project (will be used in next section) for running created REST web services.
GitHub (directory ‘rest-webservice’): https://github.com/jeevatkm/generic-repo.git
Download: https://github.com/downloads/jeevatkm/generic-repo/rest-webservice.zip
Running Sample Demo Project of REST Web Services
As you followed the article, now you will be ready to run the REST web services in your machine or alternatively you can download using above GitHub reference and build it.
Let’s execute the below command:
1 |
mac-book-pro:rest-webservice jeeva$ mvn jetty:start -f webservice/pom.xml |
Web service started at http://localhost:9090; Okay hits the following REST URI in your browser (below param value is not used inside the method, it just passed to invoke the method)
1 |
http://localhost:9090/services/searchservice/search/Welcome to Demo Project - www.myjeeva.com |
You will see following data as response in your browser
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
{ "documents":[ { "id":"MA147LL/A", "name":"Apple 60 GB iPod with Video Playback Black", "inStock":true, "price":399.0, "features":[ "iTunes, Podcasts, Audiobooks", "Stores up to 15,000 songs, 25,000 photos, or 150 hours of video", "2.5-inch, 320x240 color TFT LCD display with LED backlight", "Plays AAC, MP3, WAV, AIFF, Audible, Apple Lossless, H.264 video", "Notes, Calendar, Phone book, Hold button, Date display, Photo wallet, Built-in games, JPEG photo playback, Upgradeable firmware, USB 2.0 compatibility, Playback speed control, Rechargeable capability, Battery level indication" ] }, { "id":"6H500F0", "name":"Maxtor DiamondMax 11 - hard drive - 500 GB - SATA-300", "inStock":false, "price":350.0, "features":[ "SATA 3.0Gb/s, NCQ", "8.5ms seek", "16MB cache" ] }, { "id":"IW-02", "name":"iPod &amp; iPod Mini USB 2.0 Cable", "inStock":true, "price":11.5, "features":[ "car power adapter for iPod, white" ] } ] } |
Happy Learning!
You have successfully learned the REST Web Services using AndroMDA tool, right out-of-the-box for your project need. I hope this would be helpful for you!