NetBeans Magazine

draindecorumΛογισμικό & κατασκευή λογ/κού

15 Αυγ 2012 (πριν από 5 χρόνια και 3 μήνες)

409 εμφανίσεις

Advanced Web Service

Interoperability In Easy Steps
This article is intended for programmers who are interested in adding additional

qualities to their services, clients or SOA solutions, as well as for beginners in

NetBeans Web Service development. You will learn
how to use NetBeans 6.0 to

develop Java web service clients and services that can interoperate with Microsoft

.NET 3.0 clients and services, how to use encryption and signatures to protect

confidentiality and integrity of message transmission without need for SSL, and

how to use Reliability features to assure none of your application messages is lost

or delivered twice
.
M
ARTIN
G
REBAC
NetBeans 6.0 comes with enhanced support for web services development, reflecting the state of

industry-wide adopted technologies in web services and Service Oriented Architecture (SOA).

NetBeans includes unique and easy to use tools, from visual web service design to enabling

powerful technologies for security, reliability or transactions. Bundled together with ready-to-run

examples, help and documentation, it provides an easy way for beginners in web service

development as well as a broad set of features required by enterprise class solutions and SOA.
METRO Overview
Most of the web service related features in NetBeans are built with use of Project Metro. Project

Metro is the Web services stack (framework) from Sun Microsystems. The stack is integrated in

GlassFish V2, a high-performance, production-quality, Java EE 5 compatible application server.

The individual components of Metro can be divided in two categories:
● JAX-WS Implementation – The core Web services platform
● Project Tango, also referred to as Web Services Interoperability Technology (WSIT)
JAX-WS is the core Web Service platform, including all the SOAP message functionality, and

Project Tango adds
interoperability with Microsoft .NET, Reliability, Security, and Transactions.
Get Ready For Web Services
Implement and Deploy web service
In this example, we will show how to develop a web service. We will enhance this service with

additional capabilities in later chapters. Our service will be able to receive banking orders and store

them in a map (for more simplicity, we'll skip database in this example). First, create an Enterprise

Application in which we will host our web service, by
choosing File -> New Project
and selecting

Enterprise Application
. Click
Next
and name the application
BankApplication
while leaving the

rest with default values. Your wizard screen for Enterprise Application should look similar to

Figure 1.
Notice that the target server is GlassFish v2. You can have it installed with your NetBeans 6 installation if you

choose Full or Web & J2EE download or specifically select GlassFish). If you don't have it, download GlassFish

from
http://glassfish.dev.java.net
, and register it into NetBeans through T
ools -> Servers.
1
/
14
Figure 1
. Creating Enterprise Application
Now create the web service itself in the EJB module. Right-click
BankApplication-ejb
node and

select
New -> Web Service
menu item. In the wizard window, name the web service

BankOrderService
and place it in
package bankorder.service
as shown on
Figure 2
.
2
/
14
Figure 2
. Creating Web Service in an EJB module
After clicking
Finish,
you should see the Visual Designer window for your web service. It is

empty, because we did not define any operations for the service yet. Our application should be able

to receive orders, and we would like to model them as a Java class with 3 field
s for recipient

account number, sender account number, and the actual amount being transferred. We will represent

this data in a class called
bankorder.data.BankOrder.
Create the class as shown on
Listing 1,
and

then use
Refactoring -> Encapsulate Fields
feature in editor to generate setters and getters for all

fields.
Listing 1
. BankOrder.java Class for transferring information about the Banking orders between service and client
package bankorder.data;
public class BankOrder {
private int id;
private String receiverAccount;
private String sender Account;
}
With having the data transfer class ready, we are able to implement the web service itself. Return

to the web service
BankOrderService
we created in previous step, click
Add
Operation in the

visual designer, and fill in the details as shown on
Figure 3.
The operation should return String as a

status code to reflect if the order has been successfully submitted or not, and will take our

BankOrder
data transfer object as a parameter. When you added the operation, select
Source
tab at

3
/
14
the top of the visual designer, which will navigate you to the service source code. There, make sure

the implementation of the
receiveBankOrder()
operation corresponds to L
isting 2.
F
igure 3.
Creating Data Transfer Object
Listing 2
. BankOrderService.java Banking Web Service implementation
p
ackage bankorder.service;
import bankorder.data.BankOrder;
import java.util.HashMap;
import javax.jws.*;
import javax.ejb.Stateless;
@WebService()
@Stateless()
public class BankOrderService {
public static final HashMap bankOrderStorage = new HashMap();

@WebMethod(operationName = "receiveBankOrder")
public String receiveBankOrder(@WebParam(name = "order")
BankOrder order) {
String status = "";
try {
order.setId(bankOrderStorage.size());
bankOrderStorage.put(order.getId(), order);
return "OK";
} catch (Exception e) {
status += e.getLocalizedMessage();
}
return "FAIL" + status;
}
}
Implementing the web service is final step, and we're ready to deploy the web service to

application server (GlassFish). Right-click the
BankApplication
node, and
select
Undeploy &

Deploy
menu item. Once the application is deployed, verify your service by invoking

BankOrderService -> Test Web Service
action. After invocation, your browser window should show

page similar to
Figure 4
.
4
/
14
Figure 4.
Web Service Tester Page
Implement Client to call the web service
We will continue in our sample with Client implementation. The client will be a web application,

which will show a simple form to input the data for a bank order together with Submit button.

Clicking Submit will submit the form data to a processing servlet, which will call the web service

and based on success or failure feedback from service, it will redirect to
success,jsp
or
failure.jsp

pages. To implement what we described, create a simple Web Application by selecting
New Project

-> Web Application
. The name of the application is going to be
WebBankClientApplication.
The

wizard screen is shown on
Figure 5.
Figure 5.
Creating Client Web Application
Continue with creating a Web Service Client. Right-click the
WebBankClientApplication
node,

and select
New -> Web Service
Client. In the wizard window, select the service we implemented by

clicking
Browse
button next to the project field. Please the client to package
bankorder.webclient
.

The details are shown on
Figure 6.
5
/
14
Figure 6.
Creating Web Service Client
Once the client is created, you should see a
Web Service References
node in the project view, and

expanding all nodes underneath should reveal the web service operation. Now let's use the client

and call the web service operation in a processing servlet. The servlet will accept requests coming

from JSP page, and will transform the data from request into our data transfer object called

BankOrder.
Then it will invoke the service with
BankOrder
object as a parameter. Create the

servlet by choosing
New -> Servlet
in your client project context menu, name it
OrderSubmission

and place it to
bankorder.web
package. Then implement the servlet according to
Listing 3.
To

help with web service invocation, drag the
receiveBankOrder()
web service operation from Web

Service References into your servlet source code – directly into
processRequest()
method.

NetBeans will generate the necessary annotations and web service invocation code for you.
Listing 3
. OrderSubmission.java Processing servlet, processRequest() operation implementation
response.setContentType("text/html;charset=UTF-8");
try {
bankorder.webclient.BankOrderService port = service.getBankOrderServicePort();
bankorder.webclient.BankOrder order = new bankorder.webclient.BankOrder();
order.setAmount((String)request.getParameter("amount"));
order.setReceiverAccount((String)request.getParameter("recAcc"));
order.setSenderAccount((String)request.getParameter("senderAcc"));
java.lang.String result = port.receiveBankOrder(order);
if (result.equals("OK")) {
response.sendRedirect("success.jsp");
} else {
response.sendRedirect("failure.jsp");
}
} catch (Exception e) {
System.err.print(e);
response.sendRedirect("failure.jsp");
}
Next, create the pages where the servlet redirects to. Their names shall be
failure.jsp
and

success.jsp
. Contents for both is in
Listing 4
and
5
.
6
/
14
Listing 4
. failure.jsp Failure notification page
...
<body>
<h2>Service invocation failed!
Check server log for more info.</h2>
</body>
...
Listing 5
. success.jsp Success notification page
...
<body>
<h2>Bank Order successfully submitted!</h2>
</body>
...
As a last step, we're missing the web form to fill the bank order data into. The form can reside in

the default i
ndex.jsp
which is already created in your project.
Listing 6
shows the form, which will

submit the data to already implemented
OrderSubmission
servlet.
Listing 6
. index.jsp Form for entering bank order data (account numbers, amount)
...
<body>
<form name="OrderSubmission" action="OrderSubmission" method="POST">
Amount: <input type="text" name="amount" value="100" /><br/>
Sender Account: <input type="text" name="senderAcc" value="5678" /><br/>
Recipient Account: <input type="text" name="recAcc" value="1234" /><br/>
<input type="submit" value="Submit" name="Submit" />
</form>
</body>
...
And we're ready! Run the web application, enter some data, click Submit and observer the

message flow in GlassFish output window.
To see the messages and HTTP requests and responses flowing between services and clients, add following

Java options to your GlassFish domain.xml ($GLASSFISH_DIR/domains/domain1/config/domain.xml):
<jvm-options>-Dcom.sun.xml.ws.transport.http.HttpAdapter.dump=true</jvm-options>
<jvm-options>-Dcom.sun.xml.ws.transport.http.client.HttpTransportPipe.dump=true</jvm-options>
Enhancing your service/client with Security and Reliability

The work we have done so far was in the grounds of the web service implementation. However, to

make our example look a bit more real, we need to assure several things. It would be very bad if

your bank order requests have been lost during transmission and you wouldn't know about it. Also,

it would be wrong if banking orders are executed in a different order than you submit them.

Reliability features of Metro will help us here, but the list of complaints against the basic

implementation is longer.
From security perspective, we need to make sure that only certain users are able to submit the

orders. Also, when they are sending the orders, we should make sure the communication is

encrypted so that nobody can read what kind of banking orders are we submitting, and we need to

use signing of messages to assure that the message has not been tampered with on the route from

service to client and back.
Performance is also important, so we'd not like to establish the secure session for each message, but

do it only once, send more messages during the session and then terminate it, or set timeout when

the session should terminate.
To help with these additional requirements on our service implementation, we'll use the WSIT

NetBeans plugins, which are directly included in NetBeans Full or Web & Java EE bundles. To

invoke the WSIT functionality for your web service, click
Advanced...
button in the bottom of the

7
/
14
Visual WS designer, or right-click your web service in project explorer window and select
Edit WS

Attributes
action. You should see a dialog corresponding to
Figure 7
.
Figure 7.
Quality Of Service Settings in NetBeans 6.0
Reliability
Let's start with solving the first two complaints first. To assure the messages are not lost on the

wire, click the
Reliable Message Delivery
checkbox, as shown on
Figure 8
. Right below that, click

Deliver Messages In Exact Order
to solve the seconds complaint. That sets up the reliability

features of project Metro. Close the dialog, redeploy the service
BankApplication
and the client,

and submit several orders again.
8
/
14
Figure 8.
Setting up Reliability and Ordered Message Delivery
If you look closely to your application, you might notice the dialog created one configuration file, called
wsit
-
bankorder.service.BankOrderService
under project's
src/conf
folder. The file includes the settings in the form of

Policy expressions, understood by WSIT implementation.
With this setup, you can observe the message communication has changed a bit. In the message

log, you may find the messages contain new headers, such as those from
Listing 7.
Some

namespace declarations are removed from there for more clarity.
Listing 7
. Message Headers with Reliable Messaging turned on
<MessageID>uuid:eb7be0e5-00c4-40b1-a9f0-9557caadd9c5</MessageID>
<RelatesTo >uuid:fcd8cf00-3f97-49b6-a290-58fb7c8afdd5</RelatesTo>
<ns2:Sequence>
<ns2:Identifier>uuid:bd42d7f6-56e1-47a7-ae63-772c691c5bf5</ns2:Identifier>
<ns2:MessageNumber>1</ns2:MessageNumber>
</ns2:Sequence>
<ns2:AckRequested>
Presence of those headers means that Reliable Messaging is active. You might notice the Sequence

identifiers and MessageIDs. Those are used to assure proper delivery so that the Metro runtime

knows which message to resend if it has been lost, and also how to order the messages correctly on

receiving side.
Security - Service
Now focus on the security requirements. NetBeans allows you to secure your service in one step.

Return back to the
Quality Of Service
dialog, choose
Secure Service
option as shown on
Figure 9

and redeploy the application. That's all you need to do on service side to secure your service. If you

try to invoke your client again, you'll see it fails because it does not specify required credentials for

the service.
Figure 9.
Setting up Security on service
For development purposes, NetBeans with Metro provides certificates to be used. These development credentials are

used if you click
Use Development Defaults
checkbox, which is chosen by default. For your production purposes, you will

need a real certificates issued by appropriate certificate authorities.
In real world, security considerations are much more broad, so the default settings might not apply

for your real life scenario. NetBeans 6 defines several Security Profiles, which are designed for

different security scenarios. The default profile is called
Username Authentication With

Symmetric Keys.
The profile uses message level security, and protects your application for

integrity and confidentiality, which means that the communication between service and client is

encrypted, and signed. With this profile, symmetric key cryptography is used – it relies on a single,

shared secret key that is used to both sign and encrypt a message. Symmetric keys are usually faster

9
/
14
than public key cryptography. For this profile, the client does not possess any certificate/key of his

own, but instead sends its username/password for authentication. The client shares a secret key with

the server. The shared, symmetric key is generated at runtime and encrypted using the service's

certificate. The client must specify the alias in the truststore by identifying the server's certificate

alias.
From other profiles, you may choose different security mechanisms with message level security or

SSL transport, using SAML tokens, or using Secure Token Service (STS). STS profiles are used to

introduce 3
rd
party into the client-service communication. Client authenticates with the 3
rd
party

(STS provider), and further requests to the service are made using security tokens issued by the 3
rd

party.
Each security profile can be configured more through
Configure
button. The settings do correspond to the

profile chosen, but for most non-SSL based security profiles you can specify the key lengths used (128-
256bit), configure Secure Conversation and other settings. Secure Conversation is switched on automatically

when Reliable Messaging is used, and improves performance of secure communication between service and

client significantly where multiple messages are transferred. With Secure Conversation, the security context is

established only once, and further communication happens using derived keys. One of the configuration

dialogs is shown on
Figure 10
.
Figure 10.
Security Profile configuration dialog
Whole description of the configuration, security requirements and possibilities would be enough

for a whole book or two, so for further information you can consult the Metro documentation,

10
/
14
where you'll find the list of security profiles with descriptions to easily find which profile match

your needs.
Security – Client
Once we secured the service, our client is not allowed to communicate with it anymore, because it

requires the credentials. To fix it, we need to let the client know about the new service capabilities.

These capabilities are advertised in service WSDL in form of Policy assertions, such as on
Listing

8
.
Listing 8
. Policy assertions describing Reliability settings on service – Reliability enabled, Ordered Delivery enabled
<wsp:Policy wsu:Id="BankOrderServicePortBindingPolicy">
<wsp:ExactlyOne>
<wsp:All>
<ns3:RMAssertion/>
<ns7:Ordered/>
<ns8:UsingAddressing/>
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy>
Right-click your WS client under Web Service References node, and select
Refresh Client.
Choose

also an option to replace service WSDL with new version in the next dialog. With this update, client

is aware of service security capabilities, but it still doesn't have required credentials. To set them,

right-click the client node again, and select
Edit WS Attributes
action. The client
Quality Of Service

dialog is shown on
Figure 11
.
11
/
14
Figure 11.
Setting up Security on client
For development purposes, select
Use development defaults
button, click
OK,
redeploy your client

application and try to submit several banking orders again. Check GlassFish log for the messages.

You'll notice they are encrypted, and you can no longer read the real values being transfered.
The development defaults option sets automatically the required certificate aliases, and also creates

and specifies the login credentials for
wsitUser
. Static specification of username credentials is not

preferred in a lot of security settings. For that purpose, you can verify or pass the credentials

dynamically using callback handlers. To specify callback handlers, you need to switch the

Authentication Credentials
combo box from Static to Dynamic, and specify location of your handler

classes. More information about this type of authentication/verification can be again found in Metro

documentation.
Note that you don't need to change your service implementation at all to enable Reliability, Security, or other features!
12
/
14
Conclusions
In this article, we tried to show the web service development features of NetBeans 6 from basic

web service development, to adding more advanced enterprise-class features in a few clicks. For

further reading, I'd recommend NetBeans documentation, tutorials, faqs, or documents on Metro

web site. If you have specific questions or would like to give us feedback, please use Metro or

NetBeans public forums.
Important concepts
Credentials –
A set of claims used to prove the identity of a client. They contain an

identifier for the client and a proof of the client's identity, such as a password. They

may also include information, such as a signature, to indicate that the issuer

certifies the claims in the credential.
Direct Authentication –
A type of authentication where the service validates

credentials directly with an identity store, such as a database or directory service.
Impersonation –
The act of assuming a different identity on a temporary basis so

that a different security context or set of credentials can be used to access the

resource.
Message Layer Security –
Represents an approach where all the information that

is related to security is encapsulated in the message. In other words, with message

layer security, the credentials are passed in the message.
Mutual Authentication –
This is a form of authentication where the client

authenticates the server in addition to the server that authenticates the client.
Security Token –
A set of claims used to prove the identity of a client. They contain

an identifier for the client and a proof of the client's identity such as a password.

They may also include information, such as a signature, to indicate that the issuer

certifies the claims in the credential. Most security tokens will also contain additional

information that is specific to the authentication broker that issued the token.
Transport Layer Security –
Represents an approach where security protection is

enforced by lower level network communication protocols (such as SSL).
Trusted subsystem (domain) –
This is a process where a trusted business identity

is used to access a resource on behalf of the client. The identity could belong to a

service account or it could be the identity of an application account created

specifically for access to remote resources.
Links
http://glassfish.dev.java.net
GlassFish application server main web site.
http://websvc.netbeans.org/wsit
NetBeans WSIT Plugin (Project Tango) related web site
https://wsit.dev.java.net/docs/tango-overview.pdf
Article with more information about Metro, JAX-WS and Project Tango.
http://blogs.sun.com/mgrebac
Martin Grebac's blog
Bio
Martin Grebac
(
martin.grebac@sun.com
) is a staff engineer at Sun Microsystems, Inc. He worked on JSP debugging and J2EE

refactoring features in NetBeans, led Java EE 5 Wed Services efforts in NetBeans 5, and raised WSIT support in later releases. He

is a member of GlassFish Web Technologies and Standards team, focusing on Tools integration of web technologies around Project

Metro, and involved in other GlassFish integration efforts, such as with Groovy and Grails.
13
/
14
14
/
14