Constructing Services with J2EE
Building a Web Service with J2EE
Creating a web service as a distributed component that is
portable and interoperable is not a trivial task. As discussed
earlier, you can deploy either regular Java classes or stateless
EJBs as web services. Regular Java classes are packaged in a web
module and EJB web services are packaged in normal ejb-jar
modules.
Given these two deployment options, which one do you use?
Java Class versus Stateless EJB: The Endless Debate
It is a matter of prolonged debate whether you should choose a
regular Java class or EJBs as your technology for building a web
service. Java classes are easier to develop than EJBs, are pure
Java objects, and do not have the "extra baggage" that EJBs do.
However, EJBs provide several nice features, such as declarative
transaction and security, and let the developer concentrate on
building business logic without having to worry about the
infrastructure services.
EJB 3.0 is
greatly simplifying the programming model and in that spec EJBs
will look like regular Java classes.
Packaging Requirement
Whether you decide to use a regular Java class or EJBs, you need
to package several artifacts into your WAR or ejb-jar to expose your
component as a Java web service. Following are the packaging
structures for web services based either on EJB or regular Java
classes.
ejb-jar for an EJB-based web service:
/META-INF/
ejb-jar.xml
webservices.xml
oracle-webservices.xml
mapping-file.xml
wsdl/ the wsdl file
ejb classes (includes endpoint and bean classes)
Web app (.war) for a regular Java web
service:
/WEB-INF/
web.xml
webservices.xml
oracle-webservices.xml
mapping-file.xml
wsdl/ the wsdl file
/classes/(includes endpoint and bean classes)
/lib/
Let us discuss each of the deployment-time artifacts and
descriptors:
- WSDL: As previously described.
- Endpoint interface: The web service endpoint
should implement the
java.rmi.Remote interface, and
every method exposed in the endpoint interface must throw
java.rmi.RemoteException. This end point needs to
registered into the standard deployment descriptor for the module
(ejb-jar.xml or web.xml). Your deployment
descriptor (e.g., ejb-jar.xml) needs to have the following entry:
<service-endpoint>
oracle.ejb21.ws.HelloServiceInf
</service-endpoint>
The following shows the code for the Web service endpoint for a
HelloWorld web service:
public interface HelloServiceInf
extends java.rmi.Remote {
java.lang.String sayHello(java.lang.String name)
throws java.rmi.RemoteException;
}
- Web service deployment descriptors: The J2EE
platform requires a standard deployment descriptor named
webservices.xml. This descriptor specifies the set of
web service descriptions for deployment into the J2EE application
server and their dependencies on container resources and services.
It also specifies the location of the WSDL; mapping.xml, which
contains Java-to-WSDL mapping; and the service endpoint interface
for the HelloWorld web service. An example
webservices.xml is packaged with the code sample
provided in the Resources section.
- Vendor-specific deployment descriptors:
Several implementation-specific references, such as the context root
and endpoint addresses, cannot be specified in the web services
deployment descriptor. Instead, you should specify them in the
vendor-specific deployment descriptor. For example, if you are
using OC4J, you will need to package an oracle-webservices.xml file
in WAR or
ejb-jar or to define these properties.
- Java-WSDL mapping: This file defines the
mappings between WSDL and Java types. There is no standard name for
the mapping file; the web services deployment descriptor determines
its name.
You must package all these artifacts in the WAR or ejb-jar
module before you can deploy your component as a web service. Many
development tools, such as
Oracle JDeveloper, simplify development of web services by
doing mundane tasks such as generating deployment descriptors,
mapping files, etc. Furthermore, most application servers provide
web services assembly tools that take care of the J2EE web service
packaging requirements.
Beyond an understanding of the components that make up a web
service and the associated packaging requirements, there are
architectural issues you must deal with when developing a web
service.
Approaches to Constructing Services
The main challenge in building a web service is to identify the
service with the right granularity. You can either build a new
service, or expose an existing component that is built as a Java
class or EJB and expose that as a service. When building a service,
you can take either the top-down or bottom-up approach:
- Bottom-up approach: This approach allows an
existing Java class or EJB to be exposed as a web service. This is
a very popular method of building services, because it allows you to
reuse your existing business logic without having to rewrite your
applications. If you take this approach, you have to add a web
service end-point interface for the implementation that you want to
expose as a web service, and create a WSDL that describes the web
service as well as other deployment descriptors. Tools provided by
application servers such as Oracle Application Server's web
services assembler tool makes life simpler by generating WSDL,
descriptors such as webservices.xml, and mapping files
for Web services components--freeing developers from manually
creating these files.
- Top-down approach: This is the "pure" approach
for building services, and is more relevant when you are building
your services from scratch. You start by describing the service
with WSDL rather than jumping right into implementation. This
approach is certainly preferred to the bottom-up approach, because
services become more usable, maintainable, and interoperable due to
careful consideration of the operations and messages exposed, as
well as the control you have over the WSDL while developing your
web service. Several J2EE vendors offer tools that make this
approach easier; for example, Oracle Application Server's web
services assembler generates interfaces, deployment descriptors,
and skeleton implementation classes with which you can build your
application.
Interoperability Matters
Obviously, it is imperative that your web services be
interoperable in nature. J2EE 1.4 mandates conformance to the
Basic Profile 1.0 specified by the
Web Services: Interoperability
(WS-I) organization. When building web services, you must test
for interoperability before you deploy them into production.
In addition to the design approaches and a need to field
interoperable services, there are a few best practices that you can
follow to maximize the utility of your web service.
Best Practices
Here are a few best practices for developing web services:
- Avoid overusing web services in your applications. Examine
whether you really need to expose your applications as a web
service.
- Modularity of services is very important. Use a coarse-grained
web service; e.g., a session facade that encapsulates your business
logic to be used as a web service.
- Make sure you design your web service so that it creates
minimal network traffic.
- Adhere to the WS-I Basic Profile. Use JAX-RPC data types as the
method parameters for your web service to give it interoperability
with heterogeneous web services. Avoid types such as
Collections,
HashMaps, and Lists as parameters for your web service if interoperability is important for your application.
- Many of the conventional best practices for J2EE applications
are also relevant to web services. For example, avoid exposing a
component that involves long-running transactions as a web
service.
- Weigh your security requirements for web services against
performance, because security comes with a higher cost. The
performance costs of end-to-end security for web services are quite
high.
The J2EE Blueprint Application
Java
Adventure Builder provides a nice blueprint application for
building Java-based web services application.
Once a web service has been designed, developed, and deployed,
associated client components are generally created to interact with
the given service.
Invoking Web Services
The client for a web service can be any of the following types:
static stub, dynamic proxy, or Dynamic Invocation Interface
(DII).
Building a web service client may be as complex as building a
simple web service. Fortunately, J2EE 1.4 makes it simpler for J2EE
developers to use web services from any type of J2EE component--namely web clients or EJB components.
You can invoke a web service as you would any other resources using JNDI
via the following:
- Define a
service-ref element in the deployment
descriptor for your component. For example, if you access the
HelloWorldService web service from a web module, the module's
web.xml file may contain the following:
<service-ref>
<service-ref-name>service/HelloWorldService</service-ref-name>
<service-interface>oracle.ws.HelloWorldService</service-interface>
<wsdl-file>META-INF/HelloWorldService.wsdl</wsdl-file>
<service-qname>urn:oracle-ws</service-qname>
</service-ref>
- To enable your application to find the web service, you must
specify the web service's location in your vendor-specific
deployment descriptor. For example, if you use OC4J to look up the
web service from your web module, the vendor-specific web
descriptor orion-web.xml should have the following contents
to look up the component:
<service-ref-mapping name="service/HelloWorldService">
<port-info>
<wsdl-port namespaceURI="urn: HelloWorldService"
localpart="HelloWorldServicePort"/>
<stub-property>
<name>javax.xml.rpc.service.endpoint.address</name>
<value>http://localhost:8888/hello/HelloWorldInf</value>
</stub-property>
</port-info>
</service-ref-mapping>
- You must package end-point interface and type classes with your
application prior to deployment in your server. You can make a JNDI
lookup to use a web service:
InitialContext ctx= new InitialContext();
HelloServiceInf hs = (HelloServiceInf)
ctx.lookup("java:comp/env/service/HelloWorldService");
HelloWorld hello= hs.getHelloWorldServicePort();
String myhello = hs.sayHello("Debu Panda") ;
The Future of Java Web Services
Uptake of Emerging Web Services Standards
The web services platform has grown to include reliability,
security, transactions, manageability, policy and so
on. There are several standards that has emerged or emerging
in the web services space. There are several JSRs being worked on in
the Java Community Process to design a new Java API to uptake these
emerging standards and the following table lists some of these
JSRs.
| Java Specification Request |
Goal |
| 181 |
Web Services Metadata |
| 208 |
Java Business Integration |
| 261 |
Java API for XML Web Services Addressing |
| 262 |
Web Services Connector for JMX |
| 265 |
API for using Web Services Policy |
In addition to these evolving standards, we are now getting a
glimpse into the web services support afforded by the next major
release of the J2EE platform.
Simplifying SOA Development with J2EE 5.0
Service-oriented applications are fairly difficult to build
with J2EE, so J2EE 5.0 is designed to make development simpler by
making use of Web Services Metadata annotations defined by
JSR 181.
EJB 3.0 and Web
Services Metadata have the similar goals of providing developer
friendliness.
For developing a simple Java web service in J2EE 1.4, you need
several web service artifacts: WSDL, mapping files, and several
verbose standard and proprietary web services deployment
descriptors. The Web Services Metadata specification is taking a
configuration-by-default approach similar to EJB 3.0 to make
development easier. The Web Services Metadata annotation processor
(or web services assembly tool) will generate these files for you
so you only have to worry about the implementation class.
Here is how a simple Java web service looks when it's developed
using Web Services Metadata:
package oracle.jr181.demo;
import javax.jws.WebMethod;
import javax.jws.WebService;
@WebService(name = "HelloWorldService",
targetNamespace = "http://hello/targetNamespace" )
public class HelloWorldService {
@WebMethod public String sayhello(String name ) {
return "Hello” +name+ “ from jws";
}
}
As I mentioned previously, EJB 3.0 is simplifying the development of
EJBs by using regular Java classes. By making use of EJB 3.0
and Web Services Metadata, developing EJB-based web services is
going to be much simpler. Here is how a simple HelloWorld EJB web
service looks when using EJB 3.0 and web services metadata. You do
not have to worry about creating WSDL, deployment descriptors, etc.,
and the application server will take care of generating these
artifacts during deployment.
package oracle.ejb30.ws;
import javax.ejb.Remote;
import javax.jws.WebService;
@WebService
public interface HelloServiceInf extends java.rmi.Remote{
@WebMethod java.lang.String sayHello(java.lang.String name)
throws java.rmi.RemoteException;
}
The following is the implementation class for the HelloWorld EJB in
EJB 3.0:
package oracle.ejb30.ws;
import java.rmi.RemoteException;
import javax.ejb.Stateless;
@Stateless(name="HelloServiceEJB")
public class HelloServiceBean implements HelloServiceInf {
public String sayHello(String name) {
return("Hello "+name +" from first EJB3.0 Web Service");
}
}
The above example clearly demonstrates that service development
is going to be much simpler with web services metadata and EJB
3.0.
Conclusion
In this article, you learned the basics of building web services
using the J2EE platform. You can start building and deploying your
web services in your favorite J2EE-compliant application servers
such as Oracle Application Server 10g, Sun Java System Application
Sever, etc. today.
Resources
- Example web service used in this
article
- "
How To Develop a Web Service From an Existing Java Class" (
.zip)
- "
How To Develop a Web Service From a WSDL Document" (
.zip)
-
"Service-Oriented Architecture: Beyond Web Services" by Ted Farrell
-
"Service-Oriented Architecture: Parts 1 & 2" by Samudra Gupta
- "
What
is Service Oriented Architecture?" by Hao He
-
OTN Web Services Technology Center
Debu Panda
is a Senior Principal Product Manager of the Oracle Application Server development team.
Return to ONJava.com.