 |
Wednesday, November 23, 2005 |
This class has bitten me in the past and I've seen quite a few folks on different mailing lists and forums hit issues recently so figured it was worth a little blog post.
Spring's JmsTemplate is a handy abstraction for working with JMS - its particularly useful for publishing messages in a simple way. However its got a few gotchas which I'll list here in gory detail; if you're short on time skip ahead to the recommendations section.
Gotchas with JmsTemplateThe thing to remember is JmsTemplate is designed for use in EJBs using the EJB containers JMS pooling abstraction. So every method will typically create a connection, session, producer or consumer, do something, then close them all down again. The idea being that this will use the J2EE containers pooling mechanism to pool the JMS resources under the covers. Without using a pooled JMS provider from the EJB container this is the worst possible way of working with JMS; since typically each create/close of a connection, producer/consumer results in a request-response with the JMS broker.
A quick aside; we had a bug once in ActiveMQ where if you created 65535 MessageProducer instances within the space of a few seconds, we'd get an exception thrown in the broker. Its a kinda silly thing to do, to create that many producers in a small space of time (one for each message to be sent) - JMS is designed for resources like producers and consumers to be created up front and reused across many message exchanges. The bug was highlighted by a user using JmsTemplate without a JMS pool underneath. Well at least it helped find our bug which I'm glad to say is now fixed, but it didn't help their performance too much :) So you should only use JmsTemplate with a pooled JMS provider. In J2EE 1.4 or later that typically means a JCA based JMS ConnectionFactory. So if you are not inside an EJB I'd recommend using Jencks to create the ConnectionFactory, then things will be nicely pooled & can take part in XA transactions if you like - otherwise if you are in an EJB then make sure you use your J2EE containers ConnectionFactory, never a plain-old-connection factory.
Another gotcha I've seen folks do is to create a MessageConsumer inside one of the SessionCallback methods then wonder why messages are not being received. After the SessionCallback is called, the session will be closed; which will close your consumers too :). So if you want to create a MessageConsumer you should create a connection, session and consumer yourself. (BTW it might be nice to make the createConsumer & createSession methods public on JmsTemplate).
Another problem I've seen is folks using the JmsTemplate.receive() method; as I've said above if you're not in an EJB using the J2EE containers ConnnectionFactory, a connection, session & consumer will be create and closed for each receive() method. This is all fine and well - if painfully slow unless you are using pooling - but be aware that this mechanism, without pooling, may well miss messages. If you are consuming on a topic which has messages sent with NON_PERSISTENT delivery mode then chances are you will miss messages, since each receive() call is a brand new consumer which will not receive any messages sent before the consumer existed.
Another aside; in ActiveMQ 4.x we have a new feature called Subscription Recovery which even in non-durable delivery mode allows a new consumer to go back in time and receive messages delivered within a window (a fixed amount of RAM or time window). e.g. if your broker dies you have 2 minutes to reconnect to another broker and not miss any messages - even without durable delivery. Recommendations for using JmsTemplate- Never use a regular ConnectionFactory unless you are totally sure it does all the pooling you need
- If using in an EJB ensure you use the EJB containers ConnectionFactory; otherwise consider using Jencks to create it for you
- If not using in an EJB then use Jencks to create the ConnectionFactory
- If you are only publishing messages and you are not in an EJB and you are using ActiveMQ then you can use the PooledConnectionFactory
- If you are consuming messages its probably simpler & more efficient & less likely to loose messages to avoid using the receive() method and use Message Driven POJOs instead - unless you absolutely must pull messages on demand from inside an EJB.
9:48:21 AM
|
|
Maybe there's something really clever under the covers I'm not seeing but so far Spring WS seems to be a case of NIH syndrome. I've yet to see anything its claiming to be able to do one day that XFire & ActiveSOAP haven't been able to do for some time. Worse it doesn't seem to play nice with any other SOAP stack and completely ignores JSR 181 and JAX-WS which are where its at these days for SOAP stacks. It looks spookily like a reinvention of the JBI interfaces for message exchange, but not done anywhere near as well & ignoring things like headers & attachments.
I've gotta say I'm pretty disappointed; up to now the spring folks have been great at building a kick ass IoC/AOP container, focussing on their core competency and reusing stuff & working with other OSS communities for stuff they are not experts in. I wonder if they are focussing too much on competing with JBoss and building their own versions of stuff rather than reusing the good stuff the OSS community creates just to get a tick in the box. Here's hoping the Spring guys don't get all NIH and reuse XBean in future Spring releases.
9:10:01 AM
|
|
 |
Wednesday, November 16, 2005 |
The Java eco system has zillions of web frameworks from JSF, Tapestry, Struts, WebWork, Spring WebFlow to things like JSP/JSTL/Velocity etc. There's probably a new web framework born every day in Java some place.
However if the world really does go Ajax or some kinda client technology very Ajax like - will that cause these traditional HTML/HTTP web frameworks to become legacy?
Web frameworks spend most of their time doing things like, dealing with HTTP and HTML, maintaining client side state on the server - handing intermediate form submissions & validation, templating/rendering issues and binding business objects to HTML form controls etc.
These days Ajax has template engines, XPath/XSLT engines, SOAP stacks, XForms implementations and so forth all done on the client side. You can do clever things like hide the JavaScript from your HTML page and use CSS to bind the JavaScript to the markup.
There's even a JavaScript version of Ruby on Rails that runs in the browser! :)
So is the web application of the future going to be static HTML & JavaScript, served up by Apache with Ajax interacting with a bunch of XML based web services (maybe using SOAP, maybe just REST etc)? If so, do we really need a web framework thats focussed on HTTP and HTML, or are we just gonna end up developing a bunch of XML based web services and letting Ajax do all the templating, editing and viewing?
Is this the end of web frameworks as we know it?
3:13:30 PM
|
|
 |
Wednesday, November 9, 2005 |
I missed it off my previous post, but some interesting things are taking place in Jetty and ActiveMQ to provide a great combination of an Ajax and enteprise messaging solution.
We've had Ajax support in ActiveMQ for about a year now which works well. Though the downside was we'd use up quite a few threads both in the JMS side of things and in the Servlet engine (with lots of threads in the servlet engine blocking, waiting for a message to arrive before timing out).
Firstly on the JMS side of things; we've optimised things to use configurable thread pools rather than creating a thread per client/connection/session so we can control the threads created.
Plus to improve the use of Ajax with ActiveMQ we've added an extension to the JMS client allowing you to work in synchronous mode; pulling messages from the consumer when you are ready to dispatch to a client - but getting an asynchronous notification when there is a message available to be consumed. Basically we've provided an extended MessageConsumer, a MessageAvailableConsumer which allows you to specify a MessageAvailableListener to be notified when there is a mesage avalable to to be consumed using the usual consumer.recieve*() methods in synchronous mode.
Then on the Jetty side, Greg's been doing some great work on making Jetty asynchronous with NIO and supporting kinda servlet-continuations. (Not strict continuations, just a way to suspend the execution of a servlet then resume it again later on - its up to do the servlet to do a real continuation into sub-method invocations and the like if needed).
The combination of Jetty on the Ajax/HTTP end and in the same JVM, ActiveMQ on the back end to provide connectivity (JMS, OpenWire, Stomp, WS-Notification, JBI etc) together with networks, clustering, failover and so forth provides an excellent Ajax based event based architecture.
12:27:48 PM
|
|
Crikey its been months since I last blogged. Am just so busy these days but I'll try harder to blog.
Spotted the demos of mylar yesterday which look very cool. As someone who works on lots of projects and lots of code all the time; anything to help navigate across different areas easily gets my vote. I particularly like mylars colour highlighting for different tasks etc.
We've just got ServiceMix 2.0 out of the door which was lots of work; ActiveMQ 4.0-M1 is out, M2 is just around the corner; both are starting to really rock. I'm really loving the Message Groups feature in ActiveMQ which works great in ActiveMQ and ServiceMix for load balancing of requests across a cluster while maintaining order across transactions (e.g. not wanting to get the order or messages wrong; such as processing an update of something before the first version etc) while working great as a sticky load balancer / caching layer for services. More on Message Groups another day...
I'm also really loving XBean for its custom XML which both projects have migrated to as has Jencks; its the thing I've wanted for some time; a simple easy way to add simple configuration to projects/libraries/utilities while keeping the power of Spring when you want it or just using XSD based XML when you don't.
Anyway more later, now I've finally remembered blogging again :)
Update: I forgot to talk about Ajax news so figured it warrented its own post :)
11:13:29 AM
|
|
I found I was getting some 'update_sharing' warnings after an OS X update with Java 5.
Thanks to this note from Sébastien I just typed this...
sudo ln -s /System/Library/Frameworks/JavaVM.framework/Versions/1.5.0/ /System/Library/Frameworks/JavaVM.framework/Versions/1.5 and it went way. Phew
11:00:55 AM
|
|
 |
Wednesday, August 31, 2005 |
The Eclipse plugins are getting very good which is dragging me away from IDEA (who's plugins mostly suck).
The WebTools project is good - very useful for editing WSDLs/XSDs. BIRT looks awesome. The AspectJ plugin impressive. The Spring plugin
is handy.
Also IDEA 5.0 breaks the 'maven idea' plugin too which makes
moving back to Eclipse even more tempting. I do love IDEA for hacking
Java code; I'd love it if someone refactored IDEA to be the Java editor
in Eclipse :)
Maybe someone needs to do an IDEA key-bindings for Eclipse? (I've made
a trivial start - splat-D for Text editing -> Duplicate lines).
Update I forgot about the awesome Antlr plugin for eclipse.
1:54:23 PM
|
|
 |
Thursday, August 18, 2005 |
Its been really busy in the open source world lately.
TTMPFirstly Brian has been making great progress
on a real simple wire protocol, currently code named TTMP, for
conecting different languages to a high performance message bus like ActiveMQ or other JMS providers. Yay! Go Brian - thats a great example showing Ruby talking to ActiveMQ!
LingoThen we finally released Lingo 1.0-M1. Lingo is
an implementation of Spring Remoting which works on JMS for the
transport, supports asynchronous one ways and async request-response in
addition to the usual synchronized request-response and can work with a
JCA container. Lingo supports pluggable marshallers to/from JMS so we
can use ObjectMessage or use XStream to marshal things as XML or add
custom JMS property processing etc.
JencksNew kid on the block is Jencks which has just released 1.0-M1 also. Jencks is a JCA framework for Spring. It provides full Message Driven POJO
support for any Spring application (just add jencks-all.jar to your
classpath and you're done!). This lets Spring do all of the dependency
injection of your message listeners and letting Jencks do the JCA connection & thread &
POJO pooling, transaction & exception handling and parallel message
consumption etc.
Jencks started life in the ActiveMQ project and has then merged closely
to reuse components from Geronimo (the TransactionManager, WorkManager,
JCA connectors etc) together with some handy Spring interceptors and
factory beans from Thierry from the Spring team.
e.g. its now really easy to reuse Geronimo's TransactionManager or WorkManager from inside any Spring application.
ServiceMixLast and in no way least, ServiceMix has just gone 1.0!
ServiceMix is an open source, Apache 2.0 licensed, ESB built from the
ground up on JBI (JSR 208) principles, semantics and APIs.
ServiceMix contains a suite of JBI Components together with offering services such as Orchestration via BPEL, Smart Routing, Transformation, Scripting, Rules, Scheduling and Caching
This release includes.
* a new RSS component for integrating and processing RSS news feeds in JBI * a sophisticated XPath and XSLT based XPath Router and
transformer JBI component * migrated the JCA components to work with Jencks the Spring based JCA
container which integrates with Geronimo JTA, JCA connectors and
security components.
Coolbeans!
12:11:22 PM
|
|
 |
Wednesday, July 27, 2005 |
The JCache API rocks. Now if only the Expert Group would release a public draft of the RI I'd be very happy! :). Please guys - just ship an early access release or something real soon. Anyway...
When working with SOA and ESBs caching often becomes important. If
every time a service needs some data it always performs a remote
request over HTTP/JMS on a back end system you often get large amounts
of traffic and high latency and high loads on back end systems.
Putting a cache in front of service requests can often save lots of
traffic, increase throughput rate and take load of expensive back end
systems. One of the downsides of Web Services in general (as opposed to
REST) is they don't lend themselves very well to the web centric
caching structures such as when using HTTP GET with the front end web
cache.
In ServiceMix we have a caching JBI component
which works with any JCache provider. The nice thing about this is it
works with any JCache provider (or even just a Map :) and can be used
in any service pipeline or orchestration irrespective of the transport
of the service (web service, HTTP REST, JMS, POJO) and caches at the
service invocation level - usually in memory to avoid off-process
caching overhead. The only tricky part is creating a key expression
from the request; which typically a simple XPath expression will do the
trick.
BTW a tip to all those wishing to use JCache until the EG finally
releases a public beta; just use a Map for your cache, use dependency
injection and you'll be all set for JCache when its finally public :)
11:00:53 AM
|
|
 |
Tuesday, July 26, 2005 |
ServiceMix now has rules based routing using the Drools library. Cool beans!
The Java semantic module is a little more verbose than it could be; we're working with the Drools community to put together a neater JBI based rule configuration mechanism which is more concise and JBI friendly - but already using the current Drools modules its very useful for adding routing rules into the JBI bus to provide smart routing in your SOA network.
Update: thanks to lots of help from the Drools team, we now have a JBI DSL for Drools which massively simplifies the writing of rules for JBI. See the examples for more details. This feature is currently dependent on CVS HEAD of Drools - there'll be a new release real soon hopefully :)
12:31:45 PM
|
|
I was surprised I'd never seen someone doing this before - use Spring to create and configure a JNDI context.
In ServiceMix we need to work inside a J2EE container such as when we run inside Geronimo to add JBI capability to the Apache J2EE stack. We also need to work embedded inside any Java SE platform or inside, say, Tomcat.
So as well as reusing any JNDI context available - such as for JDBC
DataSources etc - we need to be able to provide one when running
ServiceMix in stand alone mode for use by other JBI components.
There are a couple of JNDI implementations around such as the one in Apache Directory (which has lots of dependencies) and simple-jndi - which looks quite good but I couldn't get to work properly with hierarchial namespaces (probably pilot error).
But since most things we work with these days tends to use Spring's XML
configuration mechanism we kinda wanted to reuse its ability to nicely
configure objects using dependency injection as well as having a ton of
neat features (like AOP & interceptors, pooling, factory beans,
dependencies, declarative transactions etc). Plus once you become
proficient in one XML mechanism to configure POJOs, you don't wanna
have to use another one just for JNDI.
So we enhanced ActiveMQ's default
JNDI provider with a fairly simple Spring wrapper implementation and
hey presto we can configure JNDI using regular Spring XML
configuration.
All thats required is to define this jndi.properties on the classpath
java.naming.factory.initial = org.servicemix.jbi.jndi.SpringInitialContextFactory
Then this jndi.xml can be placed on the classpath and hey presto - you've a configured JNDI context all configured using Spring.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="jndi" class="org.servicemix.jbi.jndi.DefaultContext">
<property name="entries">
<map>
<entry key="jdbc/pxe__pm">
<bean class="org.hsqldb.jdbc.jdbcDataSource">
<property name="database" value="jdbc:hsqldb:mem:pxe"/>
</bean>
</entry>
</map>
</property>
</bean>
</beans>
You can see more discussions and examples here
10:30:22 AM
|
|
© Copyright 2005 James Strachan.
|
|
 |
 |
 |
 |
November 2005 |
Sun |
Mon |
Tue |
Wed |
Thu |
Fri |
Sat |
|
|
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
|
|
|
Aug Dec |
|
 |
 |
 |
 |
|