|
Welcome to the Enterprise Java Technologies Tech Tips for October 2007. Here you'll get tips on using enterprise Java technologies and APIs, such as those in Java Platform, Enterprise Edition (Java EE). You can now read the Enterprise Java Technologies Tech Tips online as a web log. This issue covers: These tips were developed using an open source reference implementation of Java EE 5 called GlassFish, and the open source NetBeans IDE 5.5.1. You can download GlassFish from the GlassFish Community Downloads page. You can download the NetBeans IDE 5.5.1 from the NetBeans page. You can download the sample archive for the tip Client-Side Polling With Dynamic Faces You can download the sample archive for the tip Testing Interoperability Between Metro and .NET Any use of this code and/or information below is subject to the license terms. Client-Side Polling With Dynamic Faces
By Roger Kitain The world of dynamic web applications offers various ways for a client and server to interact. Two approaches are particularly well suited for situations when information on the server changes frequently. These approaches are:
In HTTP streaming, the client/server connection is left open for an extended period of time so that data is streamed from the server to the client. This approach is also known as server-side push, reverse Ajax, or comet. As information changes on the server, updates are pushed to the client.
With client polling, the browser periodically issues an
The Dynamic Faces framework brings the power of Ajax to traditional JavaServer Faces Technology (often abbreviated as JSF) applications. Ajax function calls are typically made in JavaScript, which can be unfamiliar to Java developers. With Dynamic Faces, you can add Ajax functionality to a JSF application with little or no JavaScript. Dynamic Faces provides a small "out of the box" JavaScript library that you can use with a JSF application. This tip will show you how you can use Dynamic Faces to build a real-time, stock query application that does client-side polling. You'll see that you don't have to do much JavaScript coding. A package that contains the code for the sample application accompanies the tip. The code examples in the tip are taken from the source code of the sample (which is included in the package). The Stock Query Application This tip uses a stock query application to demonstrate client-side polling with Dynamic Faces. First, let's take a look at the user interface (UI) for the application. User Interface
The UI is pretty basic. You enter one or more space-delimited stock symbols in the Symbol text field and click the Search button. In response, the application displays a table of data pertinent to the stocks represented by the symbols you entered. You enter proxy information in the Proxy Host and Proxy Port fields if you are behind a firewall. The most interesting feature of the UI is the Streaming field. The choices are On or Off. If Streaming is set to On, the client polls the server, firing Ajax transactions every 10 seconds (or a specified time interval). The Remote/Local field allows you to choose either Local or Remote. If you select Local, the application uses local data. This is the choice to make if a network connection is not available. If you select Remote, the application calls the Yahoo Stock Quoting service to get the stock data. The size of the result table dynamically changes depending on the number of symbols that you enter. Now let's take a look at the artifacts used in the application. Artifacts There are only three artifacts used in the application:
JSP Page Here's a snippet of the JSP page for the application, <f:view> <html> <head> ... ... <jsfExt:scripts/> <script type="text/javascript"> ... ... include_js('javascripts/stock-faces.js'); </script> </head> <body> <h:form id="form" prependId="false"> ... <h:panelGrid border="1" columns="1" styleClass="panel-input-border"> <h:panelGrid border="1" columns="7"> <h:outputText value="Symbol:"/> <h:inputText id="symbol"/> <h:commandButton id="search" value="Search" onclick="DynaFaces.fireAjaxTransaction( this, {});return false;" actionListener="#{bean.getStockInfo}" /> ... <h:selectOneMenu id="streaming" value="Off" onchange="toggleStreaming()"> ... </h:panelGrid> </h:panelGrid> <h:panelGrid id="stockdata" border="1" columns="8" styleClass="panel-data-border" rendered="false"> ... </body> </html> </f:view> Here are some things to notice in the code snippet:
JavaScript File Here is the JavaScript file, var pollId; /** Delay between requests to the server when polling. */ var pollDelay = 10000; /** Start polling the server */ function start() { pollId = setInterval(poll, pollDelay); } /** Stop polling the server */ function stop() { clearInterval(pollId); } function poll() { queueEvent(); DynaFaces.fireAjaxTransaction(null, {}); } function queueEvent() { var actionEvent = new DynaFaces.ActionEvent("search", DynaFaces.PhaseId.INVOKE_APPLICATION); DynaFaces.queueFacesEvent(actionEvent); return false; } function toggleStreaming() { var menu = document.getElementById("streaming"); var idx = menu.selectedIndex; var streaming = menu[idx].value; if (streaming == "Off") { stop(); } else if (streaming == "On") { start(); } }Here's what the JavaScript code in the file does:
JSF Managed Bean Here's a snippet of the JSF managed bean, /** * This bean has methods to retrieve stock information from * the Yahoo quote service. */ public class Bean { private static final String SERVICE_URL = "http://quote.yahoo.com/d/quotes.csv"; /** * Action method that is used to retrieve stock * information. This method uses two helper methods - one * to get the stock information, and the other to * dynamically build the "data" components for the UI. */ public void getStockInfo(ActionEvent ae) { ... ... stockData = getStockData(symbols); buildUI(stockData); ... } /** * Helper method to get the stock data (remotely). */ private String[] getStockData(String[] symbols) throws IOException, MalformedURLException { String[] data = new String[symbols.length]; for (int i=0; i<symbols.length; i++) { StringBuffer sb = new StringBuffer(SERVICE_URL); ... ... } return data; } /** * Helper method to dynamically add JSF components to * display the data. */ private void buildUI(String[] stockData) { FacesContext context = FacesContext.getCurrentInstance(); UIForm form = (UIForm)context.getViewRoot().findComponent("form"); UIPanel dataPanel = (UIPanel)form.findComponent("stockdata"); ... ... // Create and add components with data values // Symbol ... dataPanel.getChildren().add(outputComponent); // Name ... dataPanel.getChildren().add(outputComponent); // Open Price (if any) ... dataPanel.getChildren().add(outputComponent); ... ... } dataPanel.setRendered(true); }This JSF Managed Bean has an action method,
The action method, Running the Sample Code A sample package accompanies this tip that demonstrates the techniques covered in the tip. You can deploy the sample package on any web container that supports the Servlet 2.5 API, JavaServer Pages (JSP) Technology 2.1, and JavaServer Faces Technology 1.2. These instructions assume that you are using GlassFish. To install and run the sample:
Summary This tip demonstrated how you can combine JSF with Ajax to produce dynamic applications. This application illustrated two features of Dynamic Faces:
You can find out more about Dynamic Faces in the jsf-extensions project. Also see Ed Burns's blog Introducing Project Dynamic Faces. >About the Author Roger Kitain is the JavaServer Faces technology co-specification lead. He has been extensively involved with server-side web technologies and products since 1997. Roger started working on JSF in 2001 as a member of the reference implementation team. He has experience with Java Servlet technology, JSP, and most recently has been involved with different rendering technologies for JSF. Testing Interoperability Between Metro and .NET
By Harold Carr The March 2007 Tech Tip, Securing Web Services Using WSIT introduced Web Services Interoperability Technology (WSIT), an implementation of open web services technologies that enables interoperability between Java EE and .NET. WSIT along with Java API for XML-Based Services (JAX-WS) comprise the stack of web services technologies in GlassFish v2. The web services stack in GlassFish v2 is called Project Metro or Metro for short. Metro is built into Sun Java System Application Server 9.1. Metro also runs in other containers such as Tomcat. WSIT, also called Project Tango, includes features that enable advanced web service interoperability with the .NET Windows Communication Foundation (WCF), a set of technologies for building and running connected systems. WSIT also addresses key aspects of web services interoperability such as reliable messaging, transaction handling, and security. What this means is that any combination of Metro-based and WCF-based clients and services can interoperate with support for reliable messaging, transaction handling, and security. To ensure that the stack of WCF and Metro technologies interoperate properly and provide the proper support, Microsoft and Sun engineers run comprehensive interoperability tests called "plug-fests". You can find out more about the plug-fests, including the scenarios that are tested, by viewing the Web Services Interoperability Plug-Fest Home Page. All tests pass in the current levels of .NET and Metro: .NET 3.0 and Metro 1.0. In this tip, you'll build and run an interoperability test in which a Metro-based client communicates with a WCF-based service. A package that contains the code for the interoperability test accompanies the tip. The code examples in the tip are taken from the source code of the sample (which is included in the package). A Reliable One-Way Interoperability Test The interoperability test you'll build and run in this tip is a "reliable one-way test." This type of test is described in "Scenario #1.1. One-Way Anonymous Client" in the document WCF (Indigo) Introperability Lab: Reliable Messaging. This is a typical enterprise use case where a client sends data to a service for processing but does not wait for a response -- that's why it's called "One-Way". However, the client wants assurances that the messages are received by the service. The message flow in this test is as follows:
Metro-Based Client
Let's start by creating the Metro-based client. You can view the
source code for the client in the file package reliableoneway.client; import org.tempuri.IPing; import org.tempuri.PingService; public class ReliableOneWay { public ReliableOneWay() {} public static void main(final String[] args) { try { PingService service = new PingService(); IPing port = service.getCustomBindingIPing(); msg(null, "BEFORE FIRST MESSAGE"); msg(port, "FIRST MESSAGE"); msg(port, "SECOND MESSAGE"); msg(port, "THIRD MESSAGE"); msg(null, "TERMINATE"); ((com.sun.xml.ws.Closeable)port).close();
Using a reliable messaging (RM)-based web service is no
different than using any SOAP-based web service. First you
create a proxy to the service (see the section Running
wsimport). Here, the service is
These steps are the same steps you would take to use any
SOAP-based web service. The one additional step is calling WSDL
You generate the
The WSDL file is quite large because it is used for other test
scenarios besides scenario 1.1, that is, scenarios that involve
security. The port that this tip uses is named
<wsp:Policy wsu:Id="CustomBinding_IPing_policy"> <wsp:ExactlyOne> <wsp:All> <wsrm:RMAssertion> <wsrm:InactivityTimeout Milliseconds="600000"/> <wsrm:AcknowledgementInterval Milliseconds="200"/> </wsrm:RMAssertion> <wsaw:UsingAddressing/> </wsp:All> </wsp:ExactlyOne> </wsp:Policy>
The The Structure of the Test In this tip, you'll use ant to create the proxy, compile the code, and run the client test. You can also use NetBeans -- for more details, see the WSIT Tutorial.
If you haven't already done so, download and install GlassFish v2.
Then download the sample application for the tip and extract its contents. You should now see the newly extracted
directory as Although this tip demonstrates only one scenario, the directory structure below the interop directory is set up such that common artifacts are factored out to be used with other tests. The directory structure is as follows: common.xml rm build.xml netbeans ReliableOneWayService ... src reliableoneway build.props build.xml client ReliableOneWay.java ... server etc EchoServiceRMCustomOnly.wsdl ReliableOneWay.xsd
At the top level of the directory structure, the
Running wsimport Here is the snippet of code in the <target name="run-reliableoneway"> <ant target="run-wsimport" antfile="src/reliableoneway/build.xml" inheritall="false"/>
Notice that it uses the test.wsdl= http://131.107.72.15/ReliableMessaging_Service_ ... client.dir=client className=reliableoneway.client.ReliableOneWay
The
The
The Compiling the Code and Running the Test The final two steps in the <ant target="compile" antfile="src/reliableoneway/build.xml" inheritall="false"/> <ant target="run-tests" antfile="src/reliableoneway/build.xml" inheritall="false"/>
The compile step runs the Java Programming Language compiler,
javac, on the developer-written code,
Note that sysproperty is set in the <sysproperty key="com.sun.xml.ws.transport.http.client.HttpTransportPipe.dump" value="true"/>This enables the client to send and receive messages. Setting Environment Variables Four export PROXY_HOST=-DproxyHost=my.proxy.example.com export PROXY_PORT=-DproxyPort=8765 export METRO_HOME=/glassfish/b58g export TEST_HOME=~/metro-wcf-interop-tests/rmIf you are not behind a firewall then explicitly set export PROXY_HOST= export PROXY_PORT=
Set Executing the Test If you haven't already done so, start GlassFish by entering the following command: $METRO_HOME/bin/asadmin start-domain domain1Then change to the ant Note: This test is designed to run with JDK 5. If you want to run the test with JDK6, you need to use the Java Endorsed Standards Override Mechanism. Test Results
The output of the test should look similar to the content in the
You can ignore all the [java] WARNING: WSP0075: Policy assertion "{http://docs.oasis-open.org/ws-rx/wsrmp/200702}RMAssertion" was evaluated as "UNKNOWN".
These warnings are from the numerous policies for bindings in
the WSDL that are not used in this test. Similarly, you can
ignore the non-standard SOAP 1.2 binding warning messages in
the
In the output, search for Content-Type: application/soap+xml;charset="utf-8"; action="http://schemas.xmlsoap.org/ws/2005/02/rm/CreateSequence"
The
After the reliable channel is established, the application
message is sent containing <S:Envelope xmlns:..."><S:Header>... <ns2:MessageNumber>1</ns2:MessageNumber>... </S:Header>...<Text>FIRST MESSAGE</Text>... </S:Envelope>
Because this is a oneway message, the response to this message
contains an empty <s:Envelope xmlns:...><s:Header>... <r:SequenceAcknowledgement> <r:Identifier>urn:...</r:Identifier> <r:AcknowledgementRange Lower="1" Upper="1"/>... </r:SequenceAcknowledgement>... </r:SequenceAcknowledgement>This means the lowest message number received by the service was 1 and the highest message number was 1. When there are gaps in the acknowledgement range the client RM infrastructure resends lost messages. It releases message copies (for garbage collection) after those messages have been acknowledged.
Two more application messages are sent with <S:Envelope xmlns:...><S:Header>... <ns2:MessageNumber>2</ns2:MessageNumber>... </S:Header>...><Text>SECOND MESSAGE</Text>... </S:Envelope> <S:Envelope xmlns:...><S:Header>... <ns2:MessageNumber>3</ns2:MessageNumber>... </S:Header>...<Text>THIRD MESSAGE</Text>... </S:Envelope>
The responses contain
<S:Envelope xmlns:...><S:Header>... <ns2:MessageNumber>4</ns2:MessageNumber> <ns2:LastMessage/>... </ns2:Sequence>... <Action xmlns=..."> http://schemas.xmlsoap.org/ws/2005/02/rm/LastMessage </Action>...
The service responds with a <s:Envelope xmlns:...><s:Header> <r:SequenceAcknowledgement>...> <r:AcknowledgementRange Lower="1" Upper="4"/>... </r:SequenceAcknowledgement>... </s:Envelope>If messages are missing the client resends them.
After the client RM infrastructure sends Content-Type: application/soap+xml;charset="utf-8"; action= "http://schemas.xmlsoap.org/ws/2005/02/rm/TerminateSequence"
This lets the service know that it can release all resources
associated with the reliable channel identified by the null: HTTP/1.1 202 AcceptedSummary This tip showed you how to build and run a reliable messaging test in which a Metro-based client communicates with a WCF-based service, in other words, a public WCF endpoint. Of course, you can also run the same interoperability test or other interoperability tests using a WCF-based client or a Metro-based service. Running the tests with different combinations of Metro-based and WSF-based clients and servers should enable you to verify interoperability between Metro and .NET. It will also enable you to become a contributor to the open source Metro project and test the interoperability of the code you contribute. About the Author Harold Carr is the engineering lead for enterprise web services interoperability at Sun Microsystems. Previous to this role, Harold was responsible for RMI-IIOP load-balancing and fail-over in the Sun Java System Application Server. He designed the core architecture used in Sun's CORBA ORB and in the JAX-RPC 2.0 reference implementation and the scalable socket communications architecture used in SJSAS HTTP and IIOP remoting. Harold helped write the OMG Portable Object Adapter specification and was chairperson of the OMG Portable Interceptor specification. Previous to Sun, he did distributed computing research at Hewlett-Packard Research Laboratories and Schlumberger Research Laboratories, was Chief Architect of Visual Lisp technology at Autodesk, and was a logic simulation consultant for Cirrus Logic. He holds a Ph.D., in Computer Science from the University of Utah. Developers Assistance
Need programming advice on Java EE? Try Developer Expert Assistance | ||||||||||
|
| ||||||||||||