|
|

[an error occurred while processing this directive]
|
 |
 |
This article demonstrates the capabilities of jBroker Web 2.0 in implementing real-life enterprise applications. The demo builds a simple client for a Document Management System (DMS) that lists the documents for a user on the console, stores a document, and retrieves the document back.
 |
why build a DMS -- and why do it with jBroker Web |
 |
 |
 |
|
Why build a DMS -- and why do it with jBroker Web
Professions like doctor, lawyer, accountant, and so on require heavy use of
documents. The documents are generally paper and stored in folders in file cabinets,
and managing them takes considerable effort and physical space. Electronic document
storage can help by vastly reducing
the storage space required and streamlining document management.
This is where a DMS fits in. A typical DMS carries out functions like storing,
retrieving, and deleting documents. A DMS has two components: the server manages
the documents, and the client interacts with the server to store and retrieve
the documents. Paper documents can be converted into electronic format using
devices like scanners and put into the DMS.
Given the need to build a DMS, it makes sense to make the DMS Web-based, XML-based,
and Java-based-here's why:
| Web-based |
Since a DMS can be used by different users from
various remote places, it makes sense to build the DMS as a service accessible
from the Web. Emerging standards like SOAP and WSDL can be used to build
such Web Services. The Simple Object Access Protocol (SOAP) is an XML-based
standard to access remote objects using XML. The Web Services Definition
Language (WSDL) is also XML based and can be used to define various operations
or functions that a Web Service supports |
| XML-based |
XML is the most widely used standard for information exchange.
|
| Java-based |
Java is the most widely used platform for developing
Internet applications. The Java platform includes standards like J2EE that
provide scalable application containers. It is easy to deploy Java applications
in J2EE as well. |
jBroker Web meets all these requirements, as described next.
|
 |
 |
about jBroker Web 2.0 |
 |
 |
 |
|
jBroker Web is a toolkit for developing Web Service client and server applications.
The SDK contains compilers and tools for building Web Services and a runtime
for executing and testing Web Services. jBroker Web is a 100 percent pure Java
implementation and supports standards such as SOAP,
WSDL, and JAXRPC.
jBroker Web brings the familiar programming model of Java RMI to the world of
Web Services.
How jBroker Web works The figure below shows the two most
widely used compilers from jBroker Web. The rmi2soap compiler takes a Java remote interface as input and produces a SOAP stub and
skeleton for it. The skeleton is Java servlet based. You can implement a Web
Service using the skeleton and deploy it into any J2EE container.
The stub can be used by clients to invoke Web Services remotely. The stub is
a proxy for the remote service, and it defines methods for all operations in
a WSDL or remote interface. When a method is invoked with parameters, the stub
sends a SOAP request to the endpoint specified in the WSDL. The SOAP request
is produced by serializing the in and in/out parameters into XML. The SOAP message
is then sent to the endpoint using HTTP, and the response is received. Finally,
the stub deserializes the out and in/out parameters into Java objects and returns
those objects to the calling method.
Similarly, the skeleton is responsible for listening to requests, deserializing
the in and in/out parameters, dispatching the request to the appropriate method
implementation, serializing the out and in/out parameters, and finally returning
the SOAP response. The wsdl2java compiler produces similar stubs and
skeletons, except that the input to this compiler is a WSDL document rather
than a Java remote interface.
Key jBroker Web features These are the key jBroker Web
features essential for any enterprise application:
- High performance SOAP engine
- WSDL and XML schema compilers
- HTTP session management
- SOAP with attachments
- SOAP message handlers
- Interoperability with other SOAP engines such as .NET
- Easy deployments into J2EE containers
Learn more about jBroker Web.
|
 |
 |
demo: building a DMS Web Service using jBroker Web |
 |
 |
 |
|
You can start building Web Service using jBroker Web either from a Java remote
interface or a WSDL document. Since WSDL is tedious to write, it makes sense
to start with a Java remote interface. The remote interface should define all
methods or operations the Web Service requires.
Step 1: create the DocumentManager interface
Below is a very simple DocumentManager interface that has store,
retrieve, delete, and list document methods. It also has
a login method that allows users to log into their account and manage
documents. This interface can be used to generate the Web Services code (stub,
skeleton, and so on) using jBroker Web's rmi2soap compiler.
package dms;
public interface DocumentManager extends java.rmi.Remote
{
void storeDocument(byte[] bytes, String fileName)
throws java.rmi.RemoteException;
String[] listDocuments() throws java.rmi.RemoteException;
byte[] retrieveDocument(String fileName)
throws java.rmi.RemoteException;
void deleteDocument(String fileName)
throws java.rmi.RemoteException;
void login(String userID, String password)
throws java.rmi.RemoteException;
}
|
Step 2: write the server implementation
Once the skeleton is generated, you need to write the concrete implementation
for all methods in the remote interface. One way to write the server implementation
is to derive the implementation class from the generated skeleton and then write
method implementations. The DMS allows the user to log in, so the server has
to be session aware. Since jBroker Web 2.0 generates a skeleton that is servlet
based and implements the javax.xml.rpc.server.ServletEndpointContext
interface from JAX-RPC, you can make use of the HttpSession in the servlet
API for session tracking. As shown in the getSession method, the call
to getEndpointContext returns implementation of the ServletEndpointContext
interface through which you can get the HttpSession.
private HttpSession getSession()
{
return getEndpointContext().getHttpSession();
}
|
The server stores the login information in the HttpSession and checks
for authorization each time a method is invoked. Here are the methods from server
that are used for login purposes:
private final String _loggedin = "user_logged_in";
private void isLoggedIn()
{
HttpSession session = getSession();
Object login = session.getAttribute(_loggedin);
if (login == null)
throw new Error("please login first");
}
public void login(String userID, String password)
throws java.rmi.RemoteException
{
// get the password of the user
String pswd = _userProfiles.getProperty(userID + ".password");
// check if password matches
if (!pswd.equals(password))
throw new Error("password did not match");
// get the HTTP session
HttpSession session = getSession();
// store the userID in the session
session.setAttribute(_loggedin, userID);
session.setAttribute(_uid_prop, userID);
}
|
Here is the storeDocument method from the server:
public void storeDocument(byte[] bytes, String docName)
throws java.rmi.RemoteException
{
try
{
// check if the user is logged in
isLoggedIn();
// get the user id of the logged in user
String userID = getUserID();
// get the file name for the document to be stored
String fileName = getFileName(docName, userID);
// write the bytes to the file
FileOutputStream fos = new FileOutputStream(fileName);
fos.write(bytes);
fos.close();
}
catch(IOException ioe)
{
ioe.printStackTrace();
throw new Error("error storing file:" + ioe.getMessage());
}
}
|
For the complete Server.java listing, see Code listing.
Step 3: write the sample client
Clients for DMS can be written in many ways. You can write a GUI-based client
using Java Swing or an HTML-based client using JavaServer Pages (JSP). Because
the DMS is a Web Service, you could also write the client in an entirely different
language - for example, the
client could be a .NET client.
As planned, this demo builds a simple client that displays information on the
console for the user. It lists the documents and then stores a document and
retrieves it back. Note that because the client takes part in a session, it
has to set the SESSION_MAINTAIN property of the stub. jBroker Web uses
cookies to track sessions. Here is the client method that returns the remote
proxy of the Web Service:
private static DocumentManager getDocumentManager(String[] args)
throws Exception
{
// get the initial context
InitialContext ctx = new InitialContext();
// lookup the service
DocumentManagerService svc = (DocumentManagerService)
ctx.lookup("xmlrpc:soap:dms.DocumentManagerService");
// get the stub for port
DocumentManager docMgr = svc.getDocumentManagerPort();
// set the end point address
((Stub)docMgr)._setProperty(
javax.xml.rpc.Stub.ENDPOINT_ADDRESS_PROPERTY,
args.length > 0 ? args[0] : "http://localhost:9090/dms");
// turn on the session with server
// please note that the client has to explicitly ask to
// take part in the session with the server
((Stub)docMgr)._setProperty(
javax.xml.rpc.Stub.SESSION_MAINTAIN_PROPERTY, Boolean.TRUE);
// return remote interface
return docMgr;
}
|
For the complete Server.java listing, see Code
listing.
|
 |
 |
code listing |
 |
 |
 |
Server.java
package dms;
import java.io.*;
import java.util.*;
import javax.servlet.http.*;
public class Server extends DocumentManager_ServiceSkeleton
{
private final String _loggedin = "user_logged_in";
/** Check if user is logged in. If not logged in throw Error */
private void isLoggedIn()
{
HttpSession session = getSession();
Object login = session.getAttribute(_loggedin);
if (login == null)
throw new Error("please login first");
}
/** Get the HTTP session */
private HttpSession getSession()
{
return getEndpointContext().getHttpSession();
}
private final String _uid_prop = "uid";
/** Get the userID of the user of the session */
private String getUserID()
{
return (String) getSession().getValue(_uid_prop);
}
/** Store the bytes into a file */
public void storeDocument(byte[] bytes, String docName)
throws java.rmi.RemoteException
{
try {
// check if the user is logged in
isLoggedIn();
// get the user id of the logged in user
String userID = getUserID();
// get the file name for the document to be stored
String fileName = getFileName(docName, userID);
// write the bytes to the file
FileOutputStream fos = new FileOutputStream(fileName);
fos.write(bytes);
fos.close();
} catch (IOException ioe) {
ioe.printStackTrace();
throw new Error("error storing file:" + ioe.getMessage());
}
}
/** List the document for a user */
public String[] listDocuments() throws java.rmi.RemoteException
{
isLoggedIn();
String userID = getUserID();
// get the directory name where user's documents are stored
String dirName = getUserDirectory(userID);
File dir = new File(dirName);
// get the file names of all the files in the directory
File[] files = dir.listFiles();
String[] fileNames = new String[files.length];
for (int i =0; i < files.length; i++)
fileNames[i] = files[i].getName();
return fileNames;
}
/** Retrieve the document and return the bytes from it */
public byte[] retrieveDocument(String docName)
throws java.rmi.RemoteException
{
String fileName = null;
try {
isLoggedIn();
String userID = getUserID();
// get the file name of the document
fileName = getFileName(docName, userID);
// read the file and return the bytes read
FileInputStream fis = new FileInputStream(fileName);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int c;
while((c = fis.read()) != -1) baos.write(c);
byte[] bytes = baos.toByteArray();
fis.close();
return bytes;
} catch(IOException ioe) {
ioe.printStackTrace();
throw new Error("error reading file "+fileName+":"+
ioe.getMessage());
}
}
/** Delete the document */
public void deleteDocument(String docName)
throws java.rmi.RemoteException
{
String fileName = null;
isLoggedIn();
String userID = getUserID();
fileName = getFileName(docName, userID);
File file = new File(fileName);
file.delete();
}
/** Login into the user account */
public void login(String userID, String password)
throws java.rmi.RemoteException
{
// get the password of the user
String pswd = _userProfiles.getProperty(userID + ".password");
// check if password matches
if (!pswd.equals(password))
throw new Error("password did not match");
// get the HTTP session
HttpSession session = getSession();
// store the userID in the session
session.setAttribute(_loggedin, userID);
session.setAttribute(_uid_prop, userID);
}
/** Get the file name of the document for a user */
private String getFileName(String name, String userID)
{
// get the user directory name
String fileName = getUserDirectory(userID);
// return the document file name
return fileName + File.separator + name;
}
/** Get the user directory name */
private String getUserDirectory(String userID)
{
String fileName = _dbPath + File.separator + userID;
File file = new File(fileName);
if (!file.exists()) file.mkdir();
return fileName;
}
/** Name of the directory where user directories exists */
private final static String _dbPath;
static {
String dbPath = System.getProperty("dbpath");
// if not specified then user the pwd
if (dbPath == null) dbPath = ".";
_dbPath = dbPath;
}
private static Properties _userProfiles = new Properties();
static {
try {
// read the properties file which contains information
// about users. It has 3 properties for each user.
// <userID>.password, <userID>.firstName and <userID>.lastName
// where <userID> is the userID of the user.
FileInputStream fis = new FileInputStream("users.properties");
_userProfiles.load(fis);
} catch(Throwable e) {
e.printStackTrace();
}
}
}
|
Client.java
package dms;
import java.io.*;
import javax.xml.rpc.Stub;
import javax.naming.InitialContext;
public class Client
{
private static String _userID = "docmgt-user";
private static String _pswd = "docmgt-pswd";
private DocumentManager _docMgr = null;
public static void main(String[] args) throws Exception
{
Client client = new Client();
client.run(args);
}
private void run(String[] args) throws Exception
{
// get the remote object
_docMgr = getDocumentManager(args);
// login into user's account
_docMgr.login(_userID, _pswd);
String[] files = null;
// list the documents for user
files = _docMgr.listDocuments();
listDocuments(files);
// get bytes of the file to send
String fileName = "LICENSE.html";
byte[] bytes = getBytes(fileName);
// store the document
_docMgr.storeDocument(bytes, fileName);
// list the documents for user
files = _docMgr.listDocuments();
listDocuments(files);
// retrieve the document
bytes = _docMgr.retrieveDocument(fileName);
// save document as file
try {
FileOutputStream fos = new FileOutputStream("lic.html");
fos.write(bytes);
fos.close();
} catch(Throwable e) {
e.printStackTrace();
}
// delete document
_docMgr.deleteDocument(fileName);
// list the documents for user
files = _docMgr.listDocuments();
listDocuments(files);
}
/** Get the proxy for web service */
private static DocumentManager getDocumentManager(String[] args)
throws Exception
{
// get the initial context
InitialContext ctx = new InitialContext();
// lookup the service
DocumentManagerService svc = (DocumentManagerService)
ctx.lookup("xmlrpc:soap:dms.DocumentManagerService");
// get the stub for port
DocumentManager docMgr = svc.getDocumentManagerPort();
// set the end point address
((Stub)docMgr)._setProperty(
javax.xml.rpc.Stub.ENDPOINT_ADDRESS_PROPERTY,
args.length > 0 ? args[0] :"http://localhost:9090/dms");
// turn on the session with server
// please note that the client has to explicitly ask to
// take part in the session with the server
((Stub)docMgr)._setProperty(
javax.xml.rpc.Stub.SESSION_MAINTAIN_PROPERTY, Boolean.TRUE);
// return remote interface
return docMgr;
}
/** Print the file names to the console */
private void listDocuments(String[] files) throws Exception
{
if (files.length == 0) {
System.out.println("No document found!");
} else {
for (int i = 0; i < files.length; i++)
System.out.println(files[i]);
}
}
/** Get the bytes from a file */
static byte[] getBytes(String fileName) throws Exception
{
FileInputStream fis = new FileInputStream(fileName);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int c;
while((c = fis.read()) != -1) baos.write(c);
return baos.toByteArray();
}
}
|
|
 |
|
 |
 |
 |