Você está na página 1de 9

9/26/2014 A Simple Mobile Enterprise Application - CodeProject

http://www.codeproject.com/Articles/394180/A-Simple-Mobile-Enterprise-Application 1/9
10,892,938 members (92,347 online)


Sign in
home quick answers discussions features community help Search for articles, questions, tips
Articles Mobile Development Mobile Development Applications

Rate this: Murray Brooks Davis, 30 May 2012
A Simple Mobile Enterprise Application
How to make a simple, end-to-end, mobile, Java enterprise application including a RESTful web service
and an Android client.
Download server source - 4.5 KB
Download client source - 3 KB
Download server_project.zip - 291.8 KB
Download client_project.zip - 76.1 KB
Introduction
This article shows how to make a simple, end-to-end, mobile enterprise application for developers who
are just learning how to make enterprise applications or are learning how to use a combination of the
components described here in an application. Our example includes a RESTful web service that provides
access to Java entity beans on Oracles Glassfish application server and a simple Android client to
consume it.
Serialization of the entity beans between Android and Glassfish is encoded through JSON. All code is in
Java unless otherwise specified.
Background
Earlier this year (2012), during a student assignment at Humber College in Etobicoke, Ontario, Canada, I
was suddenly struck by the clever idea that one could simultaneously demonstrate the consumption of
our RESTful web services with an Android application and the serialization of Java entity beans through
JSON. It was only a few weeks later that my Java instructor informed me to my dismay that this was not
an original idea even with his own past classes. Nonetheless, I did not find another article on the web that
duplicates all that this one does (although my search may not have been thorough enough); therefore, I
bestow the precious insight herein, gleaned by the sweat of my brow, as a warm light through all
mankind to share. (Self-deprecating, Avengers-inspired sarcasm intended.)
The code shown has been extracted from my assignment and simplified for this presentation.
Using the code
We assume that our audience knows how to make simple examples of a database, an EJB-hosted RESTful
web service, and an Android Activity. However, one should be able to get the gist of the code with just a
little programming experience.
For the NetBeans web service project, I added the free, current, jettison.jar from jettison.codehaus.org. It
includes the JSON STaX implementation, which contains the BadgerFish mapping of JSON to XML.
Data Model

( votes)
4.67 5
You must Sign In to use this message board.
articles
9/26/2014 A Simple Mobile Enterprise Application - CodeProject
http://www.codeproject.com/Articles/394180/A-Simple-Mobile-Enterprise-Application 2/9
Database
The underlying database table has just enough fields for the purposes of this article: an identifier, a label,
and an info field to update. Here is the MySQL DDL script snippet that describes it:
Collapse | Copy Code
CREATE TABLE `simpleuser` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`email` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
Entity
I generated the corresponding entity class with the New > Entity Classes from Database command in
NetBeans.
Collapse | Copy Code
public class SimpleUser implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false)
@NotNull
@Column(name = "id")
private Integer id;
@Basic(optional = false)
@NotNull
@Size(min = 1, max = 255)
@Column(name = "name")
private String name;
@Basic(optional = false)
@NotNull
@Size(min = 1, max = 255)
@Column(name = "email")
private String email;
...
}
Business Logic
The RESTful web service provides the basic CRUD access operations to the entity beans, which are the
resources in the REST paradigm: create, retrieve, update, delete.
Glassfish includes Jersey, the Reference Implementation for building RESTful web services in Java. We also
add the JSON/XML mapping provided by BadgerFish in the Jettison library available at
jettison.codehaus.org.
Our web service is implemented by a stateless Enterprise JavaBean, SimpleUserResource. We have also
set the REST ApplicationPath attribute to be rest.
Create
Our adopted REST paradigm calls for resources to be created by the HTTP request POST. This snippet
includes the start of our implementation class.
Collapse | Copy Code
import java.net.URI;
import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.*;
import javax.ws.rs.*;
import javax.ws.rs.core.*;
import javax.ws.rs.core.Response.ResponseBuilder;
import javax.xml.bind.JAXBElement;
import org.codehaus.jettison.json.JSONArray;
@Path("/appuser")
@Produces(MediaType.WILDCARD)
@Consumes(MediaType.WILDCARD)
@Stateless
public class SimpleUserResource {
@PersistenceContext(unitName = "SimpleUserRESTService-warPU")
private EntityManager entityManager;
@Context
private UriInfo uriInfo;
@POST
@Consumes({MediaType.APPLICATION_JSON})
9/26/2014 A Simple Mobile Enterprise Application - CodeProject
http://www.codeproject.com/Articles/394180/A-Simple-Mobile-Enterprise-Application 3/9
public Response createSimpleUser(JAXBElement<SimpleUser> userJAXB) {
// Save the new user to the db.
SimpleUser user = userJAXB.getValue();
user.setId(0); // set the id to nonesense to generate a new id
entityManager.persist(user);
// Refresh the persistence context for the newly generated id.
// Can't just use EntityManager.merge() because the managed instance
// that it returns does not contain the newly generated id, either.
// (Pesist() makes the argument instance managed.)
entityManager.flush();
// Return the HTTP 201 Created response with the new user id.
URI userURI = uriInfo.getAbsolutePathBuilder().path(user.getId().
toString()).build();
return Response.created(userURI).build();
}
...
The @Path attribute specifies the URL path component that indicates to Glassfish that containing HTTP
requests should be directed to this EJB.
The @Consumes and @Produces attributes specify the acceptable MIME types of the content of the HTTP
requests that are received and responses that are sent, respectively. (WILDCARD indicates all types, of
course.) An attribute specified for a method overrides a corresponding one for its class.
The JAXBElement parameters wraps the posted entity bean after BadgerFish has converted the beans
HTTP JSON representation to XML and Project JAXB has converted the XML representation to a
SimpleUser class instance.
Retrieval
Our adopted REST paradigm calls for resources to be retrieved by the HTTP request GET.
There are two basic types of retrieval. One is to retrieve a specific resource.
Collapse | Copy Code
@GET
@Path("{id}/")
@Produces({MediaType.APPLICATION_JSON})
public SimpleUser retrieveSimpleUser(@PathParam("id") int id) {
URI userURI = uriInfo.getAbsolutePathBuilder().build();
if (id < 1) {
ResponseBuilder rBuild = Response.status(
Response.Status.NOT_FOUND).entity(
userURI.toASCIIString());
throw new WebApplicationException(rBuild.build());
}
SimpleUser user = entityManager.find(SimpleUser.class, id);
if (user == null) {
ResponseBuilder rBuild = Response.status(
Response.Status.NOT_FOUND).entity(
userURI.toASCIIString());
throw new WebApplicationException(rBuild.build());
}
return user;
}
The {id} template in @Path specifies that an URL in a HTTP GET request with an extra path component
after appuser indicates that retrieveSimpleUser() will be invoked to handle the request with the
text of that extra component being passed as an integer in the parameter named id.
The returned SimpleUser instance will be converted to XML by JAXB and JSON by BadgerFish before
being sent to the client in the resulting HTTP response.
Another type of retrieval is to fetch the list of resources located at a specific directory.
Collapse | Copy Code
@GET
@Produces(MediaType.APPLICATION_JSON)
public JSONArray retrieveSimpleUsers() {
// Perform query.
Query query = entityManager.createNamedQuery("SimpleUser.findAll");
List<SimpleUser> userList = query.getResultList();
// Translate result list to JSON array.
JSONArray resUriArray = new JSONArray();
for (SimpleUser user : userList) {
UriBuilder ub = uriInfo.getAbsolutePathBuilder();
URI resUri = ub.path(user.getId().toString()).build();
resUriArray.put(resUri.toASCIIString());
}
return resUriArray;
}
9/26/2014 A Simple Mobile Enterprise Application - CodeProject
http://www.codeproject.com/Articles/394180/A-Simple-Mobile-Enterprise-Application 4/9
Article
Browse Code
Stats
Revisions (4)
Alternatives
Comments (7)
The returned array will contain the URIs of the entities as JSON strings, not the entities themselves.
Update
Our adopted REST paradigm calls for resources to be updated by the HTTP request PUT.
Collapse | Copy Code

@PUT
@Consumes({MediaType.APPLICATION_JSON})
public Response updateSimpleUser(JAXBElement<SimpleUser> userJAXB) {
SimpleUser user = userJAXB.getValue();
URI userURI = uriInfo.getAbsolutePathBuilder().
path(user.getId().toString()).build();
try {
// Ensure that this is an update, not an insert, for merge()
// can create a new entity, too.
SimpleUser matchU = (SimpleUser) entityManager.find(
SimpleUser.class, user.getId());
if (matchU == null) {
String msg = "PUT is the wrong HTTP request for creating
new user " + user.getId() + ".";
ResponseBuilder rBuild = Response.status(
Response.Status.BAD_REQUEST).entity(msg);
throw new WebApplicationException(rBuild.build());
}
// Save the current properties of the specified user to the db.
entityManager.merge(user);
return Response.ok().build();
} catch (IllegalArgumentException ex) {
ResponseBuilder rBuild = Response.status(
Response.Status.NOT_FOUND).entity(
userURI.toASCIIString());
return rBuild.build();
}
}
Delete
Our adopted REST paradigm calls for resources to be removed by the HTTP request DELETE.
Collapse | Copy Code
@DELETE
@Path("{id}/")
public Response deleteSimpleUser(@PathParam("id") int id) {
URI userURI = uriInfo.getAbsolutePathBuilder().build();
if (id < 1) {
ResponseBuilder rBuild = Response.status(
Response.Status.NOT_FOUND).entity(
userURI.toASCIIString());
return rBuild.build();
}
// Find the specified user to remove.
SimpleUser user = entityManager.find(SimpleUser.class, id);
if (user == null) {
ResponseBuilder rBuild = Response.status(
Response.Status.NOT_FOUND).entity(
userURI.toASCIIString());
return rBuild.build();
}
entityManager.remove(user);
// Status 204 No Content means that deletion has occurred.
ResponseBuilder rBuild = Response.status(Response.Status.NO_CONTENT);
return rBuild.build();
}
The {id} template in @Path works the same way as for retrieveSimpleUser().
Android Client
Now, brace yourself for the stunning beauty of this Android client application.
9/26/2014 A Simple Mobile Enterprise Application - CodeProject
http://www.codeproject.com/Articles/394180/A-Simple-Mobile-Enterprise-Application 5/9
Tagged as
, +
Java
Dev
Beginner
Intermediate
J2EE
MySQL
Android
Web-
Development
Application
UI
Forms
JSON
Web
Development
REST
Go to top
Displayed in this UI is the entity bean with id=3, name=Dustin Penner, and
email="dustin.penner@simpleuser.org".
Now, a consideration in building this app is how to serialize the bean. A reflexive instinct of the typical
contemporary software developer, trained to use application frameworks, is to reach for a library off the
internet that will handle the serialization to JSON automatically, e.g. Jackson at jackson.codehaus.org. You
know the thinking dont reinvent the wheel; dont create errors by, heaven forbid, programming your
own code; outsource the responsibility to the library maker. However, I think that, in this case, adding a
library to the client is overkill. The SimpleUser entity is *simple* - we can handle it. We can include our
own conversion methods in the entity class, which needs to be imported as a library into the Android
client project anyway. We dont have to be burdened with the overhead of including and updating the
extra library in multitudes of client apps. And, for the purpose of enlightenment, we also get to show
JSON serialization in action in this article.
Lets create an entity to represent the great, young Canadian hockey defenseman, Drew Doughty. The
method in the client sends out a HTTP POST request over a raw HttpURLConnection as follows:
Collapse | Copy Code
private void createUser(SimpleUser user) {
URL url;
HttpURLConnection connection = null;
try {
// Create connection.
String wsUri = getBaseContext().getResources().getString(
R.string.rest_web_service_uri);
url = new URL(wsUri);
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/json");
String userSer = user.getJSONSerialization();
connection.setRequestProperty("Content-Length", Integer
.toString(userSer.getBytes().length));
connection.setUseCaches(false);
connection.setDoInput(true);
connection.setDoOutput(true);
// Send request.
DataOutputStream wr = new DataOutputStream(connection
.getOutputStream());
wr.writeBytes(userSer);
wr.flush();
wr.close();
...
This method also displays the HTTP response from the server with a Toast pop-up, but well dismiss that
as unimportant for this article.
Now lets look at SimpleUsers serialization method.
Collapse | Copy Code
public String getJSONSerialization() {
StringBuilder sb = new StringBuilder();
9/26/2014 A Simple Mobile Enterprise Application - CodeProject
http://www.codeproject.com/Articles/394180/A-Simple-Mobile-Enterprise-Application 6/9
sb.append("{");
sb.append(serializeJSONField("id", Integer.toString(id)) + ",");
sb.append(serializeJSONField("name", name) + ",");
sb.append(serializeJSONField("email", email) + ",");
sb.append("}");
return sb.toString();
}
private String serializeJSONField(String name, String value) {
StringBuilder sb = new StringBuilder();
sb.append("\"");
sb.append(name);
sb.append("\":\"");
sb.append(value);
sb.append("\"");
return sb.toString();
}
Elegant, eh? Thats the nice thing about JSON serialization in comparison with a JAXB XML serialization
little overhead.
Thus, when an Android-wielding hockey fan wants to record forever the name and email of a certain
slick-skating L.A. King, his press of the Create User button will send a textual request like the following,
bypassing any typical firewalls, directly to our web service:
Collapse | Copy Code
POST /SimpleUserRESTService-war/rest/appuser HTTP/1.1
Host: localhost:8080
Accept: */*
Content-Type: application/json
Content-Length: 70
{"id":"0","name":"Drew Doughty","email":"drew.doughty@simpleuser.org"}
After clicking Retrieve All Users, the fan can select the last user id in the spinner and click
Retrieve User Details in order to check his new addition.
Collapse | Copy Code
private void retrieveUserDetails() {
URL url;
HttpURLConnection connection = null;
try {
// Create connection with the selected user.
String wsUri = getBaseContext().
getResources().getString(
R.string.rest_web_service_uri);
Spinner spinner = (Spinner) findViewById(
R.id.retrieveAllSpinner);
String userId = (String) spinner.getSelectedItem();
wsUri += userId;
url = new URL(wsUri);
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setRequestProperty("Accept", "application/json");
connection.setUseCaches(false);
connection.setDoInput(true);
connection.setDoOutput(true);
// Send request.
connection.connect();
int rspCode = connection.getResponseCode();
// Load in the response body.
BufferedReader reader = new BufferedReader(
new InputStreamReader(connection.getInputStream()));
StringBuilder sb = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
sb.append(line);
}
String rspBody = sb.toString();
if (rspCode == HttpURLConnection.HTTP_OK) {
// Deserialize the SimpleUser.
currentUser = new SimpleUser(rspBody);
// Load the detail text view.
TextView detailsTextView = (TextView) findViewById(
R.id.detailsTextView);
String userLabel = currentUser.getName() + " (" +
currentUser.getId() + ")";
detailsTextView.setText(userLabel);
// Load the email edit view.
EditText emailEditText = (EditText) findViewById(
R.id.emailEditText);
emailEditText.setText(currentUser.getEmail());
}
...
This causes the following HTTP request to and response from the server:
Collapse | Copy Code
9/26/2014 A Simple Mobile Enterprise Application - CodeProject
http://www.codeproject.com/Articles/394180/A-Simple-Mobile-Enterprise-Application 7/9
GET /SimpleUserRESTService-war/rest/appuser/4 HTTP/1.1
Host: localhost:8080
Accept: application/json
HTTP/1.1 200 OK
X-Powered-By: Servlet/3.0 JSP/2.2 (GlassFish Server Open Source Edition 3.1.1 Java/Oracle
Corporation/1.7)
Server: GlassFish Server Open Source Edition 3.1.1
Content-Type: application/json
Transfer-Encoding: chunked
Date: Tue, 29 May 2012 19:28:14 GMT
{"email":"drew.doughty@simpleuser.org","id":"4","name":"Drew Doughty"}*
And this response is deserialized in the SimpleUser constructor as follows:
Collapse | Copy Code
public SimpleUser(String jSONSerialization) {
try {
String valStr = extractJSONFieldValue(jSONSerialization, "id");
this.id = Integer.parseInt(valStr);
this.name = extractJSONFieldValue(jSONSerialization, "name");
this.email = extractJSONFieldValue(jSONSerialization, "email");
} catch (UnsupportedEncodingException ex) {
Logger.getLogger(SimpleUser.class.getName()).
log(Level.SEVERE, null, ex);
ex.printStackTrace();
}
}
private String extractJSONFieldValue(String jSONSerialization,
String field) throws UnsupportedEncodingException {
String fieldLab = '"' + field + '"' + ':';
int i = jSONSerialization.indexOf(fieldLab);
if (i < 0)
throw new IllegalArgumentException(
"The JSON serialization is missing field label:" +
fieldLab);
i = jSONSerialization.indexOf('"', i + fieldLab.length());
if (i < 0)
throw new IllegalArgumentException("The JSON serialization " +
"is missing the opening quote for the value for field " +
field);
int j = jSONSerialization.indexOf('"', ++i);
if (j < 0)
throw new IllegalArgumentException("The JSON serialization " +
"is missing the closing quote for the value for field " +
field);
String valStr = jSONSerialization.substring(i, j);
return URLDecoder.decode(valStr, "UTF-8");
}
You should be able to extrapolate from here the necessary methods for retrieving all entities, updating an
entity, and deleting one, so I wont overburden you with more code.
Here is the Android form after the fan has checked his new entry:
9/26/2014 A Simple Mobile Enterprise Application - CodeProject
http://www.codeproject.com/Articles/394180/A-Simple-Mobile-Enterprise-Application 8/9
Murray Brooks Davis
Canada
I'm a software developer in Toronto, Ontario who has programmed and studied mostly Java off and on
since 2000.
Points of Interest
Implementing your own JSON serialization of your database objects over HTTP is fun because it is simple
and can pass through just about any network barriers between your client and server.
License
This article, along with any associated source code and files, is licensed under The Code Project Open
License (CPOL)
Share
About the Author
EMAIL
9/26/2014 A Simple Mobile Enterprise Application - CodeProject
http://www.codeproject.com/Articles/394180/A-Simple-Mobile-Enterprise-Application 9/9
Permalink | Advertise | Privacy | Mobile
Web01 | 2.8.140925.1 | Last Updated 30 May 2012
Article Copyright 2012 by Murray Brooks Davis
Everything else Copyright CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid
Search Comments Go

You may also be interested in...
Developer Tips for Scanning on the Web
The Top 10 Things DBAs Should Know About Toad for IBM DB2
Comments and Discussions
Profile popups Spacing Relaxed Noise Medium Layout Normal Per page 25
Update
First Prev Next
adha dimas
12-Nov-12 17:16
Varun855
18-Jul-12 1:39
Varun855
18-Jul-12 1:40
Selvin
31-May-12 0:38
Murray Brooks Davis
31-May-12 3:49
Selvin
4-Jun-12 21:28
Murray Brooks Davis
5-Jun-12 13:24
Last Visit: 31-Dec-99 18:00 Last Update: 25-Sep-14 19:44 Refresh 1
General News Suggestion Question Bug Answer Joke Rant Admin
Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.
Asking about send json in android
Mobile Enterprise Application
Re: Mobile Enterprise Application
Will not work ...
Re: Will not work ...
Re: Will not work ...
Re: Will not work ...

Você também pode gostar