Metro v2.0 has been released
A new version of the open-source Java web services stack Metro v2.0 has been released today. This new release brings several notable new features, such as Configuration Management (check the short info), Persistent RM, experimental Declarative tubeline assembler (see here) as well as new enhancements in WS-Security, Trust and SecureConversation areas.
For the full documentation of all Metro features check the Metro user guide. Metro v2.0 runs on Tomcat, GlassFish V2 and is also shipped with GlassFish V3 — the first application server to support Java EE 6 — which was, same as Metro v2.0, released today.
Metro Reliable Messaging Configuration Summary
I finally found time to write up a summary of all features that can be configured in Metro Reliable Messaging. Please check the tables bellow. Enjoy...
RM Configuration Namespace
| Prefix | Namespace |
|---|---|
| wsp | http://www.w3.org/ns/ws-policy |
| wsrmp10 | http://schemas.xmlsoap.org/ws/2005/02/rm/policy |
| wsrmp | http://docs.oasis-open.org/ws-rx/wsrmp/200702 |
| net30rmp | http://schemas.microsoft.com/net/2005/02/rm/policy |
| net35rmp | http://schemas.microsoft.com/ws-rx/wsrmp/200702 |
| sunrmp | http://sun.com/2006/03/rm |
| sunrmcp | http://sun.com/2006/03/rm/client |
| metro | http://java.sun.com/xml/ns/metro/ws-rx/wsrmp/200702 |
Reliable Messaging Configuration
| Feature name | Description | WS-RM 1.0 compatible assertion | WS-RM 1.1+ compatible assertion |
|---|---|---|---|
| Enable Reliable Messaging + version | Specifies that WS-ReliableMessaging protocol MUST be used when sending messages. Defines also the version of the WS-RM protocol to be used. | /wsrmp10:RMAssertion | /wsrmp:RMAssertion |
| Sequence Inactivity Timeout | Specifies the time interval beyond which either RM Source or RM Destination may terminate the RM sequence due to inactivity. The default setting is 600,000 milliseconds (10 minutes). A web service endpoint will always terminate session whose inactivity timeout has expired. Specified in milliseconds. | /wsrmp10:RMAssertion/wsrmp10:InactivityTimeout | /net35rmp:InactivityTimeout |
| Acknowledgement interval | Specifies the duration after which the RM Destination will transmit an acknowledgement. If omitted, there is no implied value. Specified in milliseconds. | /wsrmp10:RMAssertion/wsrmp10:AcknowledgementInterval | /net35rmp:AcknowledgementInterval |
| Retransmission Interval | Specifies how long the RM Source will wait after transmitting a message and before retransmitting the message. If omitted, there is no implied value. Specified in milliseconds. | /wsrmp10:RMAssertion/wsrmp10:BaseRetransmissionInterval/sunrmcp:ResendInterval | /metro:RetransmissionConfig/metro:Interval |
| Retransmission Interval Adjustment Algorithm | Specifies that the retransmission interval will be adjusted using a specific (e.g. exponential back-off) algorithm. |
("Exponential backoff" algorithm only) | /metro:RetransmissionConfig/metro:Algorithm |
| Maximum Retransmission Count |
| N/A | /metro:RetransmissionConfig/metro:MaxRetries |
| Close sequence timeout | By default, the call to proxy.close() will not return until all messages have been acknowledged. RM close timeout is the interval (in milliseconds) that the client runtime will block waiting for a call to close() to return. If there are still unacknowledged messages after this interval is reached, and the call to close has returned, an error will be logged about messages being lost. |
(client side only) | /metro:CloseSequenceTimeout |
| Acknowledgement request interval | Defines the suggested minimum time that the sender (RM Source) should allow to elapse between sending consecutive Acknowledgement request messages to the RM Destination. | /sunrmcp:AckRequestInterval | /metro:AckRequestInterval |
| Bind RM sequence to security token | Defines the requirement that an RM Sequence MUST be bound to an explicit token that is referenced from a wsse:SecurityTokenReference in the CreateSequence message. | N/A | /wsrmp:RMAssertion/wsp:Policy/wsrmp:SequenceSTR |
| Bind RM sequence to secured transport | Defines the requirement that an RM Sequence MUST be bound to the session(s) of the underlying transport-level protocol used to carry the CreateSequence and CreateSequenceResponse message. (When present, this assertion MUST be used in conjunction with the sp:TransportBinding assertion.) | N/A | /wsrmp:RMAssertion/wsp:Policy/wsrmp:SequenceTransportSecurity |
| Exactly once delivery | Each message is to be delivered exactly once; if a message cannot be delivered then an error MUST be raised by the RM Source and/or RM Destination. The requirement on an RM Source is that it SHOULD retry transmission of every message sent by the Application Source until it receives an acknowledgement from the RM Destination. The requirement on the RM Destination is that it SHOULD retry the transfer to the Application Destination of any message that it accepts from the RM Source until that message has been successfully delivered, and that it MUST NOT deliver a duplicate of a message that has already been delivered. | default | /wsrmp:RMAssertion/wsp:Policy/wsrmp:DeliveryAssurance/wsp:Policy/wsrmp:ExactlyOnce |
| At Most once delivery | Each message is to be delivered at most once. The RM Source MAY retry transmission of unacknowledged messages, but is NOT REQUIRED to do so. The requirement on the RM Destination is that it MUST filter out duplicate messages, i.e. that it MUST NOT deliver a duplicate of a message that has already been delivered. | N/A | /wsrmp:RMAssertion/wsp:Policy/wsrmp:DeliveryAssurance/wsp:Policy/wsrmp:AtMostOnce |
| At Least once delivery | Each message is to be delivered at least once, or else an error MUST be raised by the RM Source and/or RM Destination. The requirement on an RM Source is that it SHOULD retry transmission of every message sent by the Application Source until it receives an acknowledgement from the RM Destination. The requirement on the RM Destination is that it SHOULD retry the transfer to the Application Destination of any message that it accepts from the RM Source, until that message has been successfully delivered. There is no requirement for the RM Destination to apply duplicate message filtering. | /sunrmcp:AllowDuplicates | /wsrmp:RMAssertion/wsp:Policy/wsrmp:DeliveryAssurance/wsp:Policy/wsrmp:AtLeastOnce |
| InOrder delivery | Messages from each individual Sequence are to be delivered in the same order they have been sent by the Application Source. The requirement on an RM Source is that it MUST ensure that the ordinal position of each message in the Sequence (as indicated by a message Sequence number) is consistent with the order in which the messages have been sent from the Application Source. The requirement on the RM Destination is that it MUST deliver received messages for each Sequence in the order indicated by the message numbering. This DeliveryAssurance can be used in combination with any of the AtLeastOnce, AtMostOnce or ExactlyOnce assertions, and the requirements of those assertions MUST also be met. In particular if the AtLeastOnce or ExactlyOnce assertion applies and the RM Destination detects a gap in the Sequence then the RM Destination MUST NOT deliver any subsequent messages from that Sequence until the missing messages are received or until the Sequence is closed. | /sunrmp:Ordered | /wsrmp:RMAssertion/wsp:Policy/wsrmp:DeliveryAssurance/wsp:Policy/wsrmp:InOrder |
| Flow Control | Enables or disables the flow control feature. When enabled, this feature works in conjunction with the Max Buffer Size setting to determine the maximum number of messages for sequence that can be stored at the endpoint awaiting delivery to the application. Messages may have to be withheld from the application if ordered delivery is required and some of their predecessors have not arrived. If the number of stored messages reaches the threshold specified in the Max Buffer Size setting, incoming messages belonging to the sequence are ignored. | /net30rmp:RmFlowControl | /net30rmp:RmFlowControl |
| Maximum Flow Control Buffer Size | If Flow control is enabled, this value specifies the number of request messages that will be buffered in the RM session. The default setting is 32. For more information, see the description of the Flow Control option. | /net30rmp:RmFlowControl/net30rmp:MaxReceiveBufferSize | /net30rmp:RmFlowControl/net30rmp:MaxReceiveBufferSize |
| Maximum concurrent RM sessions | Specifies how many concurrently active RM sessions (measured based on inbound RM sequences) the SequenceManager dedicated to the WS Endpoint accepts before starting to refuse new requests for sequence creation. | N/A | /metro:MaxConcurrentSessions |
| Reliable Messaging Persistence | Specifies whether the runtime should use persistent sequence and message storage or not. | N/A | /metro:Persistent |
| Sequence manager maintenace task execution period | Specifies the period (in milliseconds) of a sequence maintenance task execution. Sequence maintenance task takes care of terminating inactive sequences and removing the terminated sequences from the sequence repository. | N/A | /metro:MaintenanceTaskPeriod |
This information is now available via official Metro User Guide too.
Intercepting web service calls with a custom Metro Tube
In this blog, I am going to show you how to write a custom tube for intercepting web service messages and how to configure Metro to route all the web service traffic through this custom tube.
As you may know, the upcoming Metro v2.0 release will quietly introduce a new "Declarative tubeline assembler" feature that lets advanced Metro users to write their own Tubes and specify custom tubelines for web services in their applications. The reason why we are not advertising this feature is that we feel there's still some important work to be done in terms of consolidating all existing Metro configuration files and stabilizing some internal APIs enough to expose them publicly. So, before I continue with the blog that is clearly targeted at developers who like to live on the edge of new technologies, I need to clearly state the following "Safe Harbor" Statement:
Metro APIs discussed in this blog post are internal to Metro, evolving and may change in the future Metro releases without a prior warning. Use it at your own risk.
Good, so now that you have been properly warned (and scared), we can finally continue. As I have said, Metro 2.0 has this notion of declarative approach to assembling the web service processing tubeline, which you can imagine as a set of low-lever (and thus powerful) filters that are applied to each SOAP request/response that flows to/from a web service endpoint or its client. The standard set of tubes that comes with Metro takes care for all run-time processing including security, reliability, transactions, message validation, XML-Java and Java-XML transformations, business logic invocation etc.
The concept of tubes has been there in Metro for a quite a long time now. And, as I mentioned before, the concept is VERY powerful - many times more powerful than the standard JAX-WS handlers. Leveraging this concept at a user level was however difficult as there was no easy way how to insert a custom tube into a web service endpoint tubeline and thus effectively override the default Metro tubeline. The declarative tubeline assembler has changed that. It is now possible to write your own tube factories and use them in customizing the processing tubeline on the endpoint level basis. Let's have a look at one of the potential use cases.
In this use case, I am about to develop an interceptor capable of intercepting all calls to all web service endpoints deployed on the application server instance regardless of the application in which they are deployed. I am using GlassFish v2 with latest build of Metro v2.0 installed on it.
I will start with a simple "echo" test service application. By invoking this service I will be able to verify that my interceptor kicks in and really works. The code of the service is pretty simple and straightforward:
@WebService() public class Echo { /** * Web service operation */ @WebMethod(operationName = "echoMessage") public String echoMessage(@WebParam(name = "message") final String message) { return "Echoed: " + message; } }
Once the service is deployed I can create the client application to invoke it. I am using NetBeans web project and for simplicity I embed the service invocation code directly to the index.jsp page. The code looks like this:
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>JSP Page</title> </head> <body> <h1>Hello World!</h1> <%-- start web service invocation --%><hr/> <% try { com.sun.metro.samples.tubeinterceptor.testservice.EchoService service = new com.sun.metro.samples.tubeinterceptor.testservice.EchoService(); com.sun.metro.samples.tubeinterceptor.testservice.Echo port = service.getEchoPort(); String result = port.echoMessage("Hello"); out.println("Result = " + result); } catch (Exception ex) { out.println("Exception = " + ex.toString()); } %> <%-- end web service invocation --%><hr/> </body> </html>
When I select "Run" from the client's project context menu, the project gets deployed and the index page gets displayed with the result of invocation:
So far, it is a simple WS sample, nothing new, nothing special. Let's start with the interesting stuff then - I am going to create a new project containing my interceptor.
To intercept the Metro messages, first I need to create a custom implementation of the JAX-WS Tube interface. I will extend my implementation from AbstractFilterTubeImpl class. This class provides some common logic and provides default implementations for methods in the Tube interface. In my implementation I am just adding some logging messages that inform that the interceptor has been invoked. Here's the code:
final class InterceptorTube extends AbstractFilterTubeImpl { private static final Logger logger = Logger.getLogger(InterceptorTube.class.getName()); static enum Side { Client, Endpoint } private final Side side; private InterceptorTube(InterceptorTube original, TubeCloner cloner) { super(original, cloner); this.side = original.side; } @Override public InterceptorTube copy(TubeCloner cloner) { return new InterceptorTube(this, cloner); } InterceptorTube(Tube tube, Side side) { super(tube); this.side = side; } @Override public NextAction processRequest(Packet request) { // TODO: place your request processing code here logger.info(String.format("Message request intercepted on %s side", side)); return super.processRequest(request); } @Override public NextAction processResponse(Packet response) { // TODO: place your response processing code here logger.info(String.format("Message response intercepted on %s side", side)); return super.processResponse(response); } @Override public NextAction processException(Throwable throwable) { // TODO: place your error processing code here logger.info(String.format("Message processing exception intercepted on %s side", side)); return super.processException(throwable); } @Override public void preDestroy() { try { // TODO: place your resource releasing code here } finally { super.preDestroy(); } } }
Of course, your interceptor can do something really fancy with the intercepted messages; it can filter or modify the payload, process message headers, add new message headers, change or fork processing flow, your imagination is the only limit.
The next step is to implement a new TubeFactory class that will be used by Metro run-time code to instantiate my InterceptorTube during the tubeline creation. Again, here's the code:
public class InterceptorTubeFactory implements TubeFactory { private static final Logger logger = Logger.getLogger(InterceptorTubeFactory.class.getName()); public Tube createTube(ClientTubelineAssemblyContext context) throws WebServiceException { logger.info("Creating client-side interceptor tube"); return new InterceptorTube(context.getTubelineHead(), InterceptorTube.Side.Client); } public Tube createTube(ServerTubelineAssemblyContext context) throws WebServiceException { logger.info("Creating server-side interceptor tube"); return new InterceptorTube(context.getTubelineHead(), InterceptorTube.Side.Endpoint); } }
Normally, you would probably want to implement some logic that would decide whether or not the tube should be created, based on a presence of a particular WebServiceFeature or any other information from the tubeline assembly context, but in this scenario it is sufficient to just create a new interceptor tube whenever the factory method is invoked.
Now having both - tube and its factory - in place, I need to wire them with the Metro run-time. First of all, I have to create a custom metro.xmlconfig file that includes my interceptor tube factory and place it under META-INF directory inside my interceptor library jar. The easiest way to do that is to copy and modify the default Metro config file (metro-default.xml) which resides in webservices-rt.jar. Here's the resulting config file:
<metro xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns='http://java.sun.com/xml/ns/metro/config' version="1.0"> <tubelines default="#intercepted-tubeline"> <tubeline name="intercepted-tubeline"> <client-side> <tube-factory className="com.sun.xml.ws.assembler.jaxws.TerminalTubeFactory" /> <tube-factory className="com.sun.xml.ws.assembler.jaxws.HandlerTubeFactory" /> <tube-factory className="com.sun.xml.ws.assembler.jaxws.ValidationTubeFactory" /> <tube-factory className="com.sun.xml.ws.assembler.jaxws.MustUnderstandTubeFactory" /> <tube-factory className="com.sun.xml.ws.assembler.jaxws.MonitoringTubeFactory" /> <tube-factory className="com.sun.xml.ws.assembler.jaxws.AddressingTubeFactory" /> <tube-factory className="com.sun.xml.ws.tx.runtime.TxTubeFactory" /> <tube-factory className="com.sun.xml.ws.rx.rm.runtime.RmTubeFactory" /> <tube-factory className="com.sun.xml.ws.rx.mc.runtime.McTubeFactory" /> <tube-factory className="com.sun.xml.wss.provider.wsit.SecurityTubeFactory" /> <tube-factory className="com.sun.xml.ws.rx.testing.PacketFilteringTubeFactory" /> <tube-factory className="com.sun.metro.samples.tubeinterceptor.tube.InterceptorTubeFactory" /> <tube-factory className="com.sun.xml.ws.dump.MessageDumpingTubeFactory" /> <tube-factory className="com.sun.xml.ws.assembler.jaxws.TransportTubeFactory" /> </client-side> <endpoint-side> <tube-factory className="com.sun.xml.ws.assembler.jaxws.TransportTubeFactory" /> <tube-factory className="com.sun.xml.ws.dump.MessageDumpingTubeFactory" /> <tube-factory className="com.sun.metro.samples.tubeinterceptor.tube.InterceptorTubeFactory" /> <tube-factory className="com.sun.xml.ws.rx.testing.PacketFilteringTubeFactory" /> <tube-factory className="com.sun.xml.wss.provider.wsit.SecurityTubeFactory" /> <tube-factory className="com.sun.xml.ws.rx.mc.runtime.McTubeFactory" /> <tube-factory className="com.sun.xml.ws.assembler.jaxws.AddressingTubeFactory" /> <tube-factory className="com.sun.xml.ws.rx.rm.runtime.RmTubeFactory" /> <tube-factory className="com.sun.xml.ws.tx.runtime.TxTubeFactory" /> <tube-factory className="com.sun.xml.ws.assembler.jaxws.MonitoringTubeFactory" /> <tube-factory className="com.sun.xml.ws.assembler.jaxws.MustUnderstandTubeFactory" /> <tube-factory className="com.sun.xml.ws.assembler.jaxws.HandlerTubeFactory" /> <tube-factory className="com.sun.xml.ws.assembler.jaxws.ValidationTubeFactory" /> <tube-factory className="com.sun.xml.ws.assembler.jaxws.TerminalTubeFactory" /> </endpoint-side> </tubeline> </tubelines> </metro>
As you can see, I have inserted a reference to my custom tube factory into the chain of default Metro tube factories. The place of insertion depends on what you want to achieve and at what stage of processing you want to intercept. My factory is inserted very close to transport which lets my interceptor tube to see message in the same form as they are transferred over the wire. And now to the last piece. I want to make sure that Metro loads my config file for all web services in all applications deployed in the application server. Since Metro uses a classloader to load config files, I need to find a proper location where to put my library and perhaps modify the application server's classpath. As one may expect, the proper location for my library in GlassFish v2 is in ${AS_HOME}/lib, where the run-time Metro jar resides. Also I need to make sure that my jar gets loaded before Metro jars, so I need to update GlassFish classpath settings and add my library to the classpath prefix:
And now I just properly configure the logging levels to be able to see the relevant logging messages in the server log...
com.sun.metro.samples.tubeinterceptor.tube -> INFO javax.enterprise.resource.webservices.assembler -> FINER javax.enterprise.resource.webservices -> INFO
...and restart the server. When I run the client again, in the server log I can see the following log messages which verify that my interceptor has been invoked for both, client and endpoint side in both request and response directions:
... deployed with moduleid = TestServiceApp Metro monitoring rootname successfully set to: com.sun.metro:pp=/,type=WSEndpoint,name=/TestServiceApp-EchoService-EchoPort Default metro-default.xml configuration file located at: 'jar:file:/Users/m_potociar/dev/glassfish/glassfishv2-ur2/lib/webservices-rt.jar!/META-INF/metro-default.xml' Application metro.xml configuration file located at: 'jar:file:/Users/m_potociar/dev/glassfish/glassfishv2-ur2/lib/InterceptorLib.jar!/META-INF/metro.xml' Creating server-side interceptor tube deployed with moduleid = TestClientApp Trying to load 'metro-default.xml' via parent resouce loader 'com.sun.xml.ws.client.ClientContainer$1@13ffd111' Default metro-default.xml configuration file located at: 'jar:file:/Users/m_potociar/dev/glassfish/glassfishv2-ur2/lib/webservices-rt.jar!/META-INF/metro-default.xml' Trying to load 'metro.xml' via parent resouce loader 'com.sun.xml.ws.client.ClientContainer$1@13ffd111' Application metro.xml configuration file located at: 'jar:file:/Users/m_potociar/dev/glassfish/glassfishv2-ur2/lib/InterceptorLib.jar!/META-INF/metro.xml' Creating client-side interceptor tube Message request intercepted on Client side Message request intercepted on Endpoint side Message response intercepted on Endpoint side Message response intercepted on Client side ...
And that's it. I have successfully created and configured a custom interceptor tube that intercepts all web service message processing on the server. The sample ZIP containing all three NetBeans projects is available here.
Off-line Metro installer for GlassFish v3
Right now Metro provides official off-line installation scripts for GlassFish v2 and Tomcat as part of the standalone Metro bundle. If you want to use latest Metro with GlassFish v3, you should update Metro installation via GlassFish v3 Update Center.
While updating Metro installation on GlassFish v3 via Update Center is really strongly encouraged and preferred way for most Metro users, there are cases when it would be really good to be able to update Metro on GlassFish v3 using an off-line installer. Off-line installer is especially helpful when trying to install Metro built from sources or trying to test latest nightly build of Metro that may not be available through the GlassFish v3 Update Center yet.
Unfortunately, there was no such installer available in the Metro bundle... until now. I have just added a first experimental version of such installer to the Metro workspace and it should be available for use with the Metro v2.0 nightly build tomorrow. Here's how to invoke the installer from the Bash command line, once you download and unpack the Metro bundle:
cd <metro-bundle-dir> export AS_HOME=<gfv3-install-dir>/glassfish ant -f metro-on-glassfish-v3.xml install
Simple, isn't it? For more information on the Ant targets available in the script file, just type
ant -f metro-on-glassfish-v3.xml help
I hope you will enjoy this small improvement, yet remember – this is an experimental installer, use it at your own risk. And don't forget to send me any issues you may encounter with the installer!
First proposal of WSIT and Metro mavenization
For a longer time we have been thinking about Metro and WSIT mavenization. The day has come close. I have put together a first draft of the proposal. Metro is an open-source project and so is WSIT, as one of the main parts of Metro project. So community feedback is really encouraged and more than welcome. Please have a look at the proposal draft and send me your comments.
Thank you in advance.
Hello new blog!
I am moving my old blog. It has been a while since I first started to play with this idea, but now I actually decided to take action, register my own domain and install my own blog engine. Last thing that convinced me to really do it was a chat with Martin, who has started his own internet domain and blog recently and told me how easy it was.
There are multiple reasons for me to abandon the old blog:
- The blog engine on the old blogging site simply failed to provide an easy to use administration UI
- The choice of plugins and themes was poor and it was near impossible to install any new plug-ins or setup a nice theme
- Overall, I didn't feel I have the full control of the blog
- The connection to the old blog's administration page tends to be reeeaaaalyyy slow, in fact I am just now trying to log in to write my last blog entry there and it's been more than 2 minutes since I pressed the "Log in" button but the page hasn't loaded yet
- And last but not least, I always wanted to have my blog hosted on my personal domain anyway
What do I expect from this change? Well, definitely improvements in points 1-5 and more importantly, I hope that — with the new blog running on a very user-friendly blog engine — I start blogging more often. So, let's see...
Jazoon 2009 – Day 2
My today's schedule was little bit more relaxed than yesterday. It started with a great keynote delivered by Danny Coward which evolved around new and noteworthy things we can expect in the coming JDK 7 and recently released JavaFX 1.2.
Maybe it's just me, but I allways eagrly await what's new in the upcoming JDK release. The things that I use to like most may sometimes seem subtle (such as new short syntax of a for loop introduced in JavaSE 5), but at the end of the day those are the things that really make my coding much more comfortable and my code shorter and thus easier to read. So I guess my favorite features for the JDK 7 evolve around Project Coin, where "coin" stands here for a synonym of "small" or "subtle", and such are the changes in the Java language this project introduces. To mention few:
Using Strings in case statements
With JDK 7 you are (finally) able to use Strings in case statements directly:
String color = "red" switch (color) { case "red" : // do red stuff break; case "green" : // do green stuff break; case "blue" : // do blue stuff break; default: // do default stuff break; }
Improved type inference
If you ever tried to really leverage generics in your code you soon ran into initializations like the one bellow:
Map<String, List<ItemClassWithSomeLargeName>> mapOfItems = new HashMap<String, List<ItemClassWithSomeLargeName>>();
I always wondered why it is required to repeat the type information <String, List<ItemClassWithSomeLargeName>> in the constructor invocation. I was not alone aparently. Josh Bloch even suggested a possible elegant solution leveraging a factory method pattern.
Finally with JDK 7, the above code is a history, as JDK 7 lets us do the following:
Map<String, List<ItemClassWithSomeLargeName>> mapOfItems = new HashMap<>();
The 'Elvis' operator
Are you tired of biolerplate code related to null checks such as the next one?
public synchronized void countPageHit(String pageName) { Integer countVal = hitCounts.get(pageName); if (countVal == null) { hitCounts.put(pageName, 0); } else { hitCounts.put(pageName, ++countVal); } }
Well, call Elvis for help and he'll let you do this instead:
public synchronized void countPageHit(String pageName) { // if there are no hit counts stored in the map, // use 0 as a current count value Integer countVal = hitCounts.get(pageName) ?: 0; hitCounts.put(pageName, ++countVal); }
Of course, there are other notable changes coming with JDK 7, such as modules to solve current visibility vs. accessibility issues, more work on letting dynamic languages to run as efficiently as possible in the VM, new and extended I/O APIs (new filesystem API, file notifications, directory operations, asynchronous I/O) and new "Garbage First" Collector very suitable for a wide variety of applications, to name a few.
As for the JavaFX 1.2, this latest release brings support of more platforms (* = new):
- Desktop platforms (Windows, MacOS, Linux* (beta), OpenSolaris* (beta))
- TV (a television from LG*)
- Mobile Phones (Apart from the existing developer emulator, there are commercially available developer phones with JavaFX runtime burned into them coming: HTC Diamond*, LG, Sony Ericsson*)
The new JavaFX 1.2 SDK also brings additional, fully skinnable (via CSS) UI components, full-screen mode, improved data handling (RSS, Atom support, ...) and greatly improved performance - around 40%up for desktop, 20% up for mobile, code size 30% down in an average JavaFX application. The performace improvement is really signinficant - a favorite Bubblemark benchmark test delivered these results on the stage:
- Microsoft Silverlight - ~90fps
- Adobe Flex - 58fps
- JavaFX 1.2 - 124fps
And this is just astonishing: JavaFX is 1.37 times faster than Silverlight and 2.13 times faster than Adobe Flex! I am pretty sure that with the new set of tools for designers, new APIs and components it will be driving even more attention of RIA as well as desktop application developers.
Now, I did spend lots of time and space writing about a single session, but for me as a Java developer it was simply the most interesting talk of the day. Still, I need to add that I attended several other great and interesting sessions today: a talk on OSGi and Java Modularity by Peter Kriens and Harold Carr's talk on Metro Web Services Security Usage Scenarios are the two talks definitely worth mentioning.
Now that the official part of today's conference program is over, I am looking forward to hanging around, talking to people as well as having some beers at tonight's Jazoon party.
Cheers!
Jazoon 2009 – Day 1
I went to sleep really late last night so I had some troubles getting up today. And thus I missed the 15-minute opening session by Christian Frey. I arrived just in time for the James Gosling's keynote. James's keynote was really packed with information. He talked about lots of stuff what Sun is doing in the software and mainly Java field, including GlassFish v3 and its profiles, latest release of NetBeans, project Kenai - Sun's full-featured project and source repository that will soon reach its first final release. He also talked about Real-time Java, Java for cellphones, mentioned coming JavaSE 7 release and touched briefly JavaFX platform. Looking back, I really wonder how he was able to cram so many topics into a 60-minutes presentation. Actualy, if you want more details on the James's keynote, please, take a look at my notes.
After the two keynotes a series of technical sessions have started. Obviously, I could not attend all of them (I am really very bad in being in two places at the same time by design), so the next lines give a short look at those that I attended.
The first technical session was done by Kirk Pepperdine from Kodewerk Ltd. on Concurrency and Performance in Java. The main premise an motivation for the presentation was - the Moore's law. A common mistake people often do is they confuse speed with frequency and put this law into connection with a CPU frequency, but in fact it is number of transistors in the CPU that is supposed to double once every 18 months. Latest evolution in the CPU field confirms that. What may be less obvious, at present, Moore's law basically suggests that currently we can expect new processors with doubling number of cores approximately every 18 months, which inherently poses questions on how to effectively leverage such parallelism and brings us eventually to concurrency issues. After a short intro into the problem area, Kirk introduced some of the new concurrency-efficient data structures he has been working on for some time. I have to say that I got little bit lost several times during the talk as I was missing some more context that would connect the slides and pieces of Kirk's talk together. Nevertheless, I left the room with an impression that Kirk's data structures may become pretty useful soon. And even though Java already provides a very useful library of concurrency-efficient classes developed by Doug Lea, it's still a pitty that Kirk's structures didn't make it into JDK (yet). Hopefully we'll see them in JDK in some later release.
Last morning session by Neal Ford of ThoughtWorks, Inc. on "Design Patterns" in Dynamic Languages was really refressing. I am not an active user of dynamic languages such as Groovy or Ruby yet, but after the initial denial phase I am getting more and more excited about them, especially Groovy. In his talk Neal touched several standard patterns know from the "Gang of Four" book (iterator, command, strategy, template, interpreter, decorator and adapter) as well as introduced two patterns specific to dynamic languages, namely "null object" and "arridifier" patterns. Probably the two main messages of the talk were that modern dynamic languages can significantly reduce the amount of the boiler-plate code a deveoper needs to write. That makes the code both faster to write and easier to read and understand. The second main thought is that it does not make sense to use standard design patterns in the GoF book as recipes that have to be followed precisely. This of course applies to statically typed languages as well, but is greatly emphasized when one starts using a dynamic language. Also, all aforementioned standard patterns can be adjusted to fit a dynamic language in a way that their implementation requires less code and feels more natural in the dynamic language environment.
In the first afternoon session Ognen Ivanovski from Netcetera presented his 1-year experiences with development of iPhone applications from a perspective of a Java developer. Overall nice introductory session. I had very similar feelings (a mix of frustration, confusion, joy and amazement) when I first put my hands on Objective C and Apple's iPhone SDK. Ognen's comparison of Eclipse (evidently his beloved IDE) to xCode (Apple's IDE) and NetBeans (well, my preferred Java IDE) really startled me though. In the comparison, Eclipse came out to be far superior to both xCode and NetBeans. The problem is that Ognen's arguments used in favor of Eclipse over NetBeans are not valid for several years now. I don't want to go into argument which of these IDEs is really better. I guess the lesson to learn here is just that if you actually don't know enough about something (or haven't seen/used it in the last couple of years), don't try to compare it...
The next session I attended was about build and collaboration tools, presented by Jason van Zyl. This talk evolved around Maven, OSGi repositories and tools folks in Sonatype develop around them. Interesting thing was that, among other things, they are developing also plugins for Hudson because they would like to see Hudson to become a standard open-source tool for build & release process and development collaboration.
One more interesting talk I saw today was from SAP guys on exposing devices and sensors in a RESTful way. As part of the presentation they were demonstrating SunSPOTs with an embedded web server that was capable of handling REST request and producing json responses. The SunSPOTs were accessible via something they called "Smart (or was it Intelligent?) gateway", which was essentially just an HTTP proxy. With this RESTful API it was possible to browse all registered SunSPOTs and retrieve all the data about each particular SunSPOT's status using HTTP GET. Also it was possible to control the devices and do things like lighting the LEDs, changing colors etc. Thinking about it, it would be a nice project to try to embed Jersey into a SunSPOT and do something similar.
Last two talks (1, 2) of the day were without a question the cherry on the top of the cake. Very, VERY interesting and entertaining at the same time. Because of their topics it does not have any sense to try to condense them into few sentences. But I am sure that everybody who stayed there to see them would agree that they were more than worth it. ...btw. did you know that there are armed military robots deployed on the North-South Korean borders that are supposed to shoot people without a valid RFID on sight?
GlassFish Day in Zurich, Switzerland
Today I presented project Metro at GlassFish Day event which took place in Zurich, Switzerland as part of the larger Jazoon 2009 conference. From what I can say the event was very successful. We had great speakers and I think that the whole event was very well attended and received.
Alexis did a great introduction by providing insight into where we are with GlassFish at present as well as where are we heading. In the second session he showcased clustering with GlassFish and the GlassFish Enterprise Manager - a really nice and useful tool that lets GlassFish administrators monitor various aspects of GlassFish instances and presents the collected data in a very comprehensible graphical ways - an ideal tool for all customers who "have more money than time".
The third morning session was dedicated to Roberto and his preview of the new features in the upcoming JavaEE 6 release. I think the guys in the JSR expert group did a really good job in making the enterprise java developer's life MUCH easier. The coming APIs seem to be very flexible and easy to use and learn. From what I can tell, this isn't "yet another update", this is probably the first JavaEE release where I have a good feeling about its completeness, flexibility and maturity. Great thing also is that this JavaEE release not only adds new stuff but it also recognizes obsolete technologies, which will be pruned and eventually removed from the specification. Among technologies currently on the prune list are JAX-RPC (hurray!), Entity EJBs (is there anyone brave enough still using them anyway?) and few others. These technologies either never really caught up or have already been practically replaced by their modern counterparts anyway. As for the features which I am particularly interested in and happy about are dependency injection specified by JSR 299 (Web Beans) and Servlet 3.0. Also I am very glad that JAX-RS - Java API for RESTful Web Services (JSR 311) made its way into JavaEE 6 as well.
The last session before lunch was my Metro talk. I provided a short overview of Metro, its features and architecture and dedicated most of the session to practical demonstrations including development of simple SOAP web service and client as well as few other demos showcasing advanced Metro features, such as message-level security, reliable messaging and streaming large data over SOAP web services.
After the lunch Alexis did his "GlassFish Survival Guide" talk focusing on installation, profiles, most useful administration commands as well as other useful tips which are good to know when starting with GlassFish. Those are the tips which can help you to avoid something I call unnecessary "aha!" moments and which can save you a lot of time.
In the next session, Jerome went through the new and noteworthy stuff coming in the planned GlassFish v3 release. This release, which is planned for September this year, is getting closer and closer and truly brings the next-generation GlassFish AS. The new application server - or "application container" would be probably more accurate - will be OSGi-fied, highly modular and extensible and will bring support for additional languages and frameworks, such as Ruby on Rails or Groovy. Those of you, who are interested in trying it out right now, you can download the latest GlassFish v3 Preview release - a really fancy name for a beta release, isn't it
.
After the interesting talk on the tooling support for JavaEE 6 features presented by Ludo and Roman came the last talk of the day - the one that I was eagerly awaiting - the talk on JSF 2.0 presented by Ed Burns. If there was ever an API that needed a major update it would definitely be JSF - this is not my sentence, I read it in some materials to the talk, but I absolutely agree
And once again I was very pleasantly surprised by the new prospects that lie ahead of us in the space of this UI framework. The new single-file component definition which resembles Objective C object definition or revamped and standardized Ajax support are only few notable changes to mention.
It was a great session to end with the day full of new information. Overall today's GlassFish Day was a realy great kick-off for the Jazoon 2009 Conference that starts officially tomorrow. Looking forward to it - stay tuned for more details!
Interoperability Plugfest in Redmond
I have spent the last week in the rainy Seattle area together with Harold, Jiandong and Rama. We've attended a WS Interoperability Plugfest event organized by Microsoft and focused on testing interoperability of WS stack implementations from different vendors. This time we focused on testing our Metro implementations of standard versions of WS-* specifications as well as validating backwards compatibility with their older counterparts.
In the reliable messaging area, which I was taking care of, we have successfully passed all the tested scenarios despite some misconfiguration on internal Microsoft endpoints. If you are interested in a more detailed results, please check the table bellow:
Metro->WCF WCF->Metro Metro->WCF WCF->Metro Metro->WCF WCF->Metro external external internal A internal A internal B internal B RM1.0 SOAP1.2 One-way pass NR pass pass pass pass RM1.0 SOAP1.1 One-way pass NR pass pass pass pass RM1.0 SOAP1.2 One-way Secured pass NR FAIL FAIL pass pass RM1.0 SOAP1.1 One-way Secured pass NR FAIL FAIL pass pass RM1.0 SOAP1.2 Roundtrip pass NR pass pass pass pass RM1.0 SOAP1.1 Roundtrip pass NR pass pass pass pass RM1.0 SOAP1.2 Roundtrip Secured pass NR FAIL FAIL pass pass RM1.0 SOAP1.1 Roundtrip Secured pass NR FAIL FAIL pass pass RM1.1 SOAP1.2 One-way pass NR pass pass pass pass RM1.1 SOAP1.1 One-way pass NR pass pass pass pass RM1.1 SOAP1.2 One-way Secured pass NR pass pass FAIL FAIL RM1.1 SOAP1.1 One-way Secured pass NR pass pass FAIL FAIL RM1.1 SOAP1.2 Roundtrip pass NR pass pass pass pass RM1.1 SOAP1.1 Roundtrip pass NR pass pass pass pass RM1.1 SOAP1.2 Roundtrip Secured pass NR pass pass FAIL FAIL RM1.1 SOAP1.1 Roundtrip Secured pass NR pass pass FAIL FAIL NR=="Not Run"

