JSR 311, JAX-RS: Comment and suggestions

12 Comments

Since I’m so RESTless lately I started thinking about what JBoss could do to help with this effort. We’re involved with JSR-311, which is defining a server-side framework for REST web services, so I decided to contact Heiko Braun, our representative on this specification. I got a copy of the latest draft and dived in. Sometimes the rules of the JCP prevent you from talking about a specification publicly (please correct me if I’m wrong), so I wasn’t sure I could blog about this specification. But, since Brian Leonard has blogged about 311, then I guess I can too.

I don’t want to get into too much detail on 311. Instead please read Brian’s blog and follow the additional links he provides. 311 does seem like it is just standardizing the REST framework Sun has already written. I will though provide example code so that I can reference it later in this blog.

public class Shopping {
   @HttpMethod("GET")
   @UriTemplate("/shopping/orders")
   @ProduceMime("text/xml")
   public String getAllOrders(@QueryParam("expand") boolean expand) {...}

   @HttpMethod("POST")
   @UriTemplate("/shopping/orders")
   @ConsumeMime("text/xml")
   public String buy(Document order) {...}

   @HttpMethod("GET")
   @UriTemplate("/shopping/orders/{id}")
   @ProduceMime("text/xml")
   public String getOrder(@UriParam("id") int orderNum) {...}

   @HttpMethod("DELETE")
   @UriTemplate("/shopping/orders/{id}")
   public void deleteOrder(@UriParam("id") int orderNum) {...}
}

The spec allows you to map http header entries, query parameters, and individual elements within a URI to a method invocation and its parameters and return types. You can also specify what MIME types a method produces and consumes. The spec also provides you with the ability to define factories that can map representations to and from Java objects.

Change suggestions

After reading the specification and browing the Sun REST framework documentation, I have a few suggestions I’d like to make to JSR 311.

Remove magic methods

It seems like @HttpMethod can be placed without a http method identifier on a Java method and the HTTP method type inferred through the Java method name.

@HttpMethod String getOrders()

In this example, HTTP GET would be used because getOrders() begins with the string ‘get’. I never liked the idea of magic method names. They are too fragile and IMO, just bad programming practice. Instead let’s……..

Annotation refactoring of @HttpMethod

Annotation frameworks should be as tiny and concise as possible. Avoid verbosity at all costs. I’d like to see @HttpMethod replace with a more concrete set of http annotations with the additional ability of being able to define a uri template embedded within these applications. So, instead of @javax.ws.rest.HttpMethod (or whatever the package name will be), let’s instead have individual Get, Put, Post, Delete, and Options annotations under the package @javax.ws.rest.httpmethod:

public @interface Get {

   String value() default "";

}

The value() of Get, Post, Delete, etc. would be an optional uri template. So, instead of the verbose:

   @HttpMethod("GET")
   @UriTemplate("/shopping/orders/{id}")
   @ProduceMime("text/xml")
   public String getOrder(@UriParam("id") int orderNum) {...}

We would get:

   @Get("/shopping/orders/{id}")
   @ProduceMime("text/xml")
   public String getOrder(@UriParam("id") int orderNum) {...}

Reduces one line of typing and also, IMO, makes things easier to read.

Allow annotations on an interface instead

RESTful classes should be allowed to declare their REST annotations on the methods of an interface instead of on the class methods. IMO, this is a better way of isolating the published interface of a service. Doing so would also allow the EJB specification to adopt REST and be able to publish remote, local, and restful interfaces to the outside world. Another interesting side affect of this is….

How about a client side framework?

Another interesting side affect of being able to apply REST annotations to an interface is that this interface could be re-used by a client-side framework to generate a proxy that could invoke on REST web services. The client-side programmer could use the same annotations to describe many REST web services that may or may not be using the server-side implementation of 311 or even Java at all! Doesn’t seem like much more effort to define this client-side API.

@Location annotation?

One common pattern I’ve seen in the REST articles and books I have read is that when you have a service method that creates a new object or queries for an existing object, and Location header should be sent back to the client containing the URI the resource is locatable. The 311 spec seems to support this by allowing the user to return a spec-define Response class. What if instead, we provided the ability to map a return value to a Location header?

@Post("/shopping/orders")
@Location("/shopping/orders/{$r}")
public int buy(Document order) {...}

The $r would represent the string representation of the returned value of the buy() method. The client would receive an empty response with a Location header pointing to the new resource created by the buy() method. We could get even funkier in the @Location annotation and allow Unified EL expressions.

@Post("/shopping/orders")
@Location("/shopping/orders/{$r.getId()}")
public Order buy(Document order) {...}

This kind of flexibility could allow one object to be used both RESTfully and locally.

Security?

Another thing I see missing is security hooks. For instance, how about an annotation specifiying whether the resource should be accessed over HTTPS or not? How about an annotation that allows you to plug in an authentication mechanism? IMO, 311 shouldn’t be diving into defining security protocols, but should at least think about providing metadata that allows you to plug in your own implementation. Then again, maybe authentication is best left to being implemented in servlet filters. I don’t know…

XML Descriptor?

There are some bigots out there that despise annotations. An XML descriptor should be created that can define this type of metadata. It should follow the style of other EE components so that we can do things like integrating JAX-RS with EJB.

EJB bridge

The 311 specification does talk about how JAX-RS interacts in a servlet environment. I’d also like to see some work done so that EJBs can become restful as well. This will probably require some work around define lifecycle and creating an annotation like @Restful to ping the container that it needs to perform restful bindings. This would also require work with the EJB 3.1 JSR to expose JAX-RS XML descriptors within EJB 3.1. Red hat would be happy to drive this in the EJB 3.1 expert group.

More to come

I’m seriously thinking about implementing 311 with the changes I’ve suggested here and integrating it with our EJB3 implementation. Hopefully I have the time. Maybe somebody in the community would be interested? I’d be happy to help as long as the individual showed initiative and ability to work on their own. I’ll also talk to Heiko more on what he thinks should be massaged in the specification and blog about them here.

Compensating Transaction Framework

5 Comments

Mark Little’s team has put together a nice annotation framework on top of the JBoss TS, Business Activity service. What?!? JBoss has a Business Activity service? Yup, we do. Have had it for a long while, accept nobody but Mark (did he even?) made any noise about it within the JBoss community. What is the Business Activity service? Mark does a better job in an article he wrote a few years ago, (his book is even better), so I won’t get into a lot of detail. To summarize in my own words, the Business Activity service looks very much like XA and traditional transactions, except they are really meant for long running conversations or activity. Traditional transactions are not good in that scenario because they hold onto resources too long. Particpants in BA look a lot like resources in XA. The register themselves with an activity. An activity is very similar to a transaction in that you begin it, and either cancel (rollback) or close (commit) the activity when you are finished. Participants can interact at closing with a 2 phase protocol, much like 2PC in regular XA. The difference is that the rules are much more lax. Participants can choose to leave the activity whenever they like as well as some other neat things. See Mark’s book or article for more details. Oh, and I forgot, this is a WS-* specification.

So back to the annotation framework. Its pretty cool. It allows you to tie in a compensatory action to an executed method. So, if the business activity is cancelled, the coordinator will automatically callback to this compensation. Here’s an example:

@Stateless
@SOAPBinding(style = SOAPBinding.Style.RPC)
@HandlerChain(file = "jaxws-ba-handler-server.xml")
public class HotelBAImpl implements HotelBA
{
	@WebMethod
	@BAService(BAServiceType.MODIFY)
	@BAAgreement(BAAgreementType.PARTICIPANT_COMPLETION)
	@BACompensatedBy(value="cancel",type = BACompensationType.PARAMETERS_MATCH)
	public Integer book(String user, String pass, Integer room)
	{
		// ... business logic
		return reservationNumber;
	}

	@WebMethod
	public void cancel(String user, String pass, Integer room)
	{
		// ... business logic
	}
}

So, in the example, if you invoke the book() method of the Hotel service, it will interact with the coordinator to register a compensation action. This action will be to invoke the cancel() method with the exact parameters that were passed into the book() method if the activity is aborted. Alternatively, you can map the book() method’s return value and parameters to the compensation action using the @BAResult and @BAParam.

{
	@WebMethod
	@BAService(BAServiceType.MODIFY)
	@BAAgreement(BAAgreementType.PARTICIPANT_COMPLETION)
	@BACompensatedBy(value="cancel",type = BACompensationType.CUSTOM)
        @BAResult("reservationNumber")
        public Integer book(@BAParam("user") String user, @BAParam("password") String pass, Integer room)
        {
           // ... business logic
          return reservationNumber;
        }

        @WebMethod
        public void cancel(@BAParam("reservationNumber") Integer reserverationNumber,
                                 @BAParam("user")String user, @BAParam("password") String pass)
        {
           // ... business logic
        }
}

There’s also a CompensationManager object that allows you to programatically put data into the activity that can be referenced by the @BAParam annotation:

{
        // injected field
        @CompensationManagement CompensationManager cm;

	@WebMethod
	@BAService(BAServiceType.MODIFY)
	@BAAgreement(BAAgreementType.PARTICIPANT_COMPLETION)
	@BACompensatedBy(value="cancel",type = BACompensationType.CUSTOM)
        public Integer book(String user, String pass, Integer room)
	{
		// ... business logic
               cm.put("reservationNumber", reservationNumber);

               return reservationNumber;
        }

        @WebMethod
        public void cancel(@BAParam("reservationNumber") Integer reserverationNumber)
        {
           // ... business logic
        }
}

There’s a few more ways to define a compensation. You can have the method compensated by another different EJB method, Web Service, or even a plain POJO. I won’t get into further detail. You’ll have to read the documentation and take a look at the demo app that comes with the distribution.

Client interface

The client interface is very simple and similar to UserTransaction:

public abstract class UserBusinessActivity
{
    public static final int ATOMIC_OUTCOME = 0;
    public static final int MIXED_OUTCOME = 1;

    /**
     * Start a new business activity with atomic outcome.
     * If one is already associated with this thread
     * then the WrongStateException will be thrown. Upon success, this
     * operation associates the newly created transaction with the current
     * thread.
     */
    public abstract void begin()
        throws WrongStateException, SystemException;

    /**
     * Start a new BA with atomic outcome and the specified timeout as
     * its lifetime.
     * If one is already associated with this thread then the
     * WrongStateException will be thrown.
     */
    public abstract void begin(final int timeout)
        throws WrongStateException, SystemException;

    /**
     * The BA is normally terminated by the close method. This signals to
     * all registered participants that the BA has ended and no compensation
     * is required.
     */
    public abstract void close()
        throws TransactionRolledBackException, UnknownTransactionException, SystemException;

    /**
     * If the BA must undo its work then the cancel method is used. Any
     * participants that can compensate are forced to do so.
     */
    public abstract void cancel()
        throws UnknownTransactionException, SystemException;

    /**
     * If participants have registered for the BusinessAgreementWithComplete
     * protocol then they will be expecting the application to inform them
     * when all work intended for them has been sent (and responded to). The
     * complete method is used for this purpose.
     */
    public abstract void complete()
        throws UnknownTransactionException, SystemException;

    public abstract String transactionIdentifier();
}

Here’s an example of using the activity service:

UserBusinessActivity businessActivity = UserBusinessActivityFactory.userBusinessActivity();
businessActivity.begin();
try {
   // do some work
   businessActivity.close();
} catch (Exception ex) {
   businessActivity.cancel();
}

There is of course some initialization to do. I’ll leave that to the documentation, but overall its a very simple API. What I like about this way of doing compensations is that the client is decoupled from the knowledge of whether something should be compensated for, and how it is compensated. The knowledge of this is encapsulated in the services the client interacts with. Services automatically register themselves for the appropriate callbacks. User code does not have to perform commits or rollbacks. Very similar in ease of use to what we’re used to with JCA combined with JTA transactions.

I really think this stuff would be even more useful in plain web applications, not just coordinated remote web services. In my previous blog, Andy Oliver commented how Hibernate application transactions with FlushMode NEVER isn’t always a great solution for long running web apps that interact with your browser. This new framework could provide a very simple mechanism for registering compensatory callbacks so that browser interactions with a database don’t have to be held in memory.

In my next blog on this subject, I want to dive into some ideas I have for improving this framework. Until then, have fun.

Guaranteed jBPM Failure Handling

2 Comments

jBPM 3.x allows you to define exception handlers in .jpdl. You can define exceptions you want to catch and either recover from the exception, or allow the execution to fail. These exception handlers are incomplete in functionality though. In my last blog, I talked about how asynchronous continuations give you the ability to have guaranteed transitions. If you dive into the asynchronous code though, you see that exception handlers are executed within the same transaction as the command service triggering the node execution. What does this mean? What are the consequences of this?

Let’s say that your action logic runs into an error condition and it needs to rollback any database changes it has made. Since the thread of execution is marked for rollback, you cannot make any changes to the execution context of the business process, for instance, like transitioning to a failure state. Any failure changes you make to the execution context would just be rolled back by the transaction. Another scenario is the guaranteed transitions I talked about in my last blog. On a rollback situation, what if you want to let your business process decide on whether the node execution should be tried again or not instead of the simple logic of the MDB’s retry count. We talked a bit about these problems on the jBPM forum. Let me summarize some solutions that were discussed.

Execute in a separate transaction

One approach is to solve the problem by invoking non-jbpm code in its own transaction. Your jbpm action could just delegate to an EJB or Spring bean that uses a REQUIRES_NEW semantic. If the invocation succeeds, populate the appropriate bpm variables and move on. If it fails, transition to a failure state or abort and retry the action.

I don’t think this is a good approach because you wouldn’t be able to use frameworks like Seam which make integrating business processes and business logic much easier. Seam uses annotations to biject (push data to and from) jbpm context data into your beans. Freeing you from writing a lot of jbpm specific code.

More importantly, I don’t think this is a solid solution. For instance, what if your non-jbpm code is successful and commits, but the machine crashes before the jbpm context commits? Then your system ends up in an inconsistent state and you are screwed.

Have a Failure State

A better way to solve this is to actually define a transition to a failure state in your process definition

<process-definition>
   <start-state>
     <transition to='business-state-1'/>
   </start-state>
   <state name='business-state-1' asynch='true'>
     ...
     <transition name="failure" to='failure-state-1'/>
   </state>
   <state name='failure-state-1' asynch='true'>
     ...
   </state>

...
</process-definition>

Your failure processing would be encapsulated within actions of the failure state instead of within exception handlers in the original business state. The failure state should be asynchronous because we want to get guaranteed processing of this state. There are two ways to ensure that either a) the business-state-1 state gets processed, or b) the failure state gets processed. I already discussed in a previous blog how to guarantee (a), but for (b) we needs some more thought.

Guarnateed failure handling: Dead Letter Queue Processing

One way to do guaranteed failure handling would be to take advantage of dead letter queues. Most MDB containers allow you to specify how many times you want a message redelivered. After the message redelivery count is reached and there still is failure, the container will reroute the message to a dead letter queue. This queue is a normal queue that you can listen on. Although not a standard JMS feature, I looked into it a little, and at least JBoss, ActiveMQ, and MQSeries have the notion of a DLQ.

So, to do jBPM failure handling, you could just register a new MDB to listen on the dead letter queue. Asynchronous continuations post instances of org.jbpm.job.ExecuteNodeJob. The MDB would check to see if the message contained an org.jbpm.job.ExecuteNodeJob, if it did, check the node for a “failure” transition. If one exists, then signal the process instance to traverse that “failure” transition.

@MessageDriven(activationConfig= {
      ActivationConfigProperty(propertyName="destinationType", propertyValue="javax.jms.Queue"),
      ActivationConfigProperty(propertyName="messageSelector", propertyValue="jobId IS NOT NULL"),
      ActivationConfigProperty(propertyName="destination", propertyValue="queue/DLQ")})
public class DLQFailureHandler implements MessageListener
{
    JbpmConfiguration jbpmConfiguration = null;
    @Resource(name="JbpmCfgResource") String jbpmCfgResource = null;

    @PostConstruct
    public void initJbpm() {
      jbpmConfiguration = JbpmConfiguration.getInstance(jbpmCfgResource);
    }

    public void onMessage(Message message) {
        long jobId = 0;
        try {
            jobId = message.getLongProperty("jobId");
        } catch (JMSException ignored) {
            // message selector confirms existence
        }

        JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
        try {
            JobSession jobSession = jbpmContext.getJobSession();
            Job job = jobSession.loadJob(jobId);
            if (!(job instanceof ExecuteNodeJob)) {
                // do some other failure handling
                jbpmContext.close();
                return;
            }
            ExecuteNodeJob executeNodeJob = (ExecuteNodeJob)job;
            if (executeNodeJob.getNode().hasLeavingTransition("failure")) {
                executeNodeJob.getProcessInstance().signal("failure");
                jobSession.deleteJob(job);
            }
            else {
                // push to a different DLQ?
            }
        } finally {
            jbpmContext.close();
        }
    }
}

To make sure we process dead jbpm jobs, we use a message selector configured at line 02. Lines 06-12 lookup and configure the jbpm context. Line 24-25 extracts the Job. If the Job is not an ExecuteNodeJob, you’ll want to add specific handling there or forward the message to another DLQ. Next in line 32 we check to see if the node has a “failure” transition. We transition and delete the job. If there is no “failure” transition, you might want to repost the message to a different DLQ that you create. If there is a failure in this processing, because of message delivery, we are still guaranteed to reprocess the failure logic.

The advantage of this approach is that it is totally seemless to your application: both in code and in your process diagram. You are guaranteed to either be in a successful or failure jbpm state. (At least with using the JBoss JMS inflow adapter but you should probably be ok in other implementations). The disadvantage of this approach is that you have no knowledge of the error condition and can’t report it to the “failure” state. Your failure logic will not know the cause of the failure. This isn’t always an issue because sometimes, specifically in a machine crash, you may not know why there is a failure.


Guaranteed failure handling: Transaction Synchronization

Another idea that came up in the forum discussion was to register a javax.transaction.Synchronization with the Transaction Manager. In afterCompletion(), do the transition to a failure state if there was a rollback. The advantage of such an approach over DLQ is that you can programmatically add the behavior in action code or write an action that performs the TM synchronization. Because of this, you can propagate any exception or failure reason to the failure state. I’m not going to get into details of this approach as I am not sure it will work, specifically:

  • You must set your redelivery count to 0. The synchronization has no way of knowing whether or not the message had been redelivered or whether or not you should transition the token to the failure state with jBPM code out-of-the-box. Since you don’t want the original JMS message redelivered after you have transitioned to the failure state, you need a retry count of zero.
  • JMS Providers may not be able to guarantee that a message isn’t redelivered. Since we require a redelivery count of zero, this is not an option.
  • Your machine could crash before transitioning to the failure state. Since we cannot redeliver the message, the node will never transition to the failure state. You may say, “well, can’t the same thing happen with the DLQ option?”. With the JBoss Inflow adapter, no. The JBoss adapter performs the DLQ check within the same transaction as the delivered method. Since both the sending to the DLQ and acknowledgement of the message are within the same transaction, you are guaranteed of one or the other succeeding.
  • Probably the most important thing is that Synchronization.afterCompletion() is not guaranteed to be executed on TX recover, after a machine crash.

So, the winner is DLQ! Of course I may have missed something. This approach would be better if we could work out the issues.

Side Effect: Redelivery handling

In my previous blog on Guaranteed Execution in jBPM, I discussed at the end how jBPM actions have know current way of knowing whether or not they have been retried by a new transaction. An indirect consequence of the DLQ approach to failure handling is that we now have some ability to recognize and keep track of redeliveries.

<process-definition>
   <start-state>
     <transition to='guarantee'/>
   </start-state>
   <state name='business-state-1' asynch='true'>
     ...
     <transition name="failure" to='failure-state-1'/>
   </state>
   <decision name='failure-state-1' asynch='true'>
     <transition name="recover" to='recovery-state-1'>
        <condition expression="retryCount >=3"/>
     </transition>
     <transition name="retry" to='business-state-1'>
        <condition expression="retryCount < 3"/>
     </transition>

   </state>

...
</process-definition>

Since failures result in a transition to a failure state we can keep increment and store redelivery counts within the token. We can programmatically decide wheter or not we are allowed to retry the message.

Conclusion

So that’s how you can have guaranteed failure handling. I do have a disclaimer though. I’m too lazy to actually try out these ideas. When I do I’ll get back to you in a follow up blog. Please try it out yourself and provide feedback on the jbpm forum topic. We’re still working out the issues here and your thoughts would be most appreciated.

MarcF interview

1 Comment

How’s Marc Fleury doing?  Matt Asay gave a pretty good interview with Marc.

Guaranteed Execution in jBPM

2 Comments

Was thinking a bit about jBPM today. One thought crossed my mind: How can you guarantee that a specific state transition happens in jBPM? We’ll talk about guaranteed state transition in this blog, but first of all, before we even think of jBPM, how could you guarantee that *any* event happens in a general application? There are few things you have to think about here:

  • You want to be guaranteed that the event is scheduled to be processed
  • You only want the event to be scheduled if your business logic succeeds
  • You want to be guaranteed that somebody processes the event

Being as stupid and slow as I am, took me a few minutes to realize that JMS provides guaranteed delivery of messages. This is obvious to many people, but let’s walk through what you would have to do in JBoss to have the guaranteed processing of an event.

First things first is to write the sender code. Let’s do this in an EJB 3.0 stateless session bean. I know this is basic stuff, but you may not be familiar with a) EJB 3.0 or b) the JBoss specifics:

@Stateless
public class BusinessLogicBean implements BusinessLogic {
   @Resource(mappedName="java:/JmsXA") ConnectionFactory factory;
   @Resource(mappedName="queue/mylogic") Destination destination;

   public void doSomething() {
      ... do some logic ...
      Connection con = factroy.createConnection();
      ... do all the JMS sugar ...
      messageProducer.setDeliverMode(DeliveryMode.PERSISTENT);
      messageProducer.send(message);
   }
}

The doSomething() method is a transactional unit of work. We want every piece of business logic to have succeeded when we deliver the message. In other words, we want the message delivered as part of a transaction. To use a transactionally aware sender, we injected the “java:/JmsXA” connection factory into our SLSB. We also set the delivery mode of the producer to be PERSISTENT. So, we both guaranteed that the message would only be sent if the business logic succeeded and that the message has been scheduled for processing. On to the server:

@MessageDriven(activationConfig= {
      ActivationConfigProperty(propertyName="destinationType", propertyValue="javax.jms.Queue"),
      ActivationConfigProperty(propertyName="destination", propertyValue="queue/mylogic"),
      ActivationConfigProperty(propertyName="DLQMaxResent", propertyValue="5")
})
public class MyMessageConsuomer implements MessageListener {
   public void onMessage(Message msg) {
      ... do the work ...
   }
}

Typical message driven bean in EJB 3.0. Since this bean is using the container to manage transactions and being invoked inside of a transaction, the receipt of the message will not be sent back to the JMS provider if the business logic is rolled back. So, if there is a system failure, or some other reason for abort, the message will be redelivered, thus guaranteeing its processing. The “DLQMaxResent” property is JBoss specific and tells the JMS adapter how many times the message should be resent before it is sent to a “dead letter queue” and put to death. There’s other configuration items around dead-letter queues. Go read our documentation for additional DLQ settings.

Guaranteed State Transitions in jBPM

Guaranteed state transitions with jbpm is all about using asynchronous continuations and the Enterprise Archive. In jBPM if you mark a node as asynch then jBPM will use its configured messaging system to transition to that state in another thread and transaction. If you have deployed jBPM through the Enterprise Archive, JMS is used to do the transition. Here’s example .jpdl

<process-definition>
   <start-state>
     <transition to='guarantee'/>
   </start-state>
   <state name='guarantee' asynch='true'>
     ...
   </state>
...
</process-definition>

So, starting a process instance of this definition will generate a JMS message that transitions to the ‘guarantee’ state. By default, jBPM is configured to use transactional connection factory, “java:/JmsXA”, describe earlier in this blog. So, when the start-state transitions, it will create a persistent JMS message and deliver it to the queue transactionally. Now, the ‘guarantee’ node will be triggered by an MDB that receives the message sent by the jBPM message layer. This MDB uses container managed transactions. This means that if there is a failure within the execution of the state, the message will be redelivered until the transaction completes successfully. This MDB is configured to use JBoss’s old EJB 2.1 container which does not use JCA message inflow. The default message redelivery count is 10. Chapter 5 in the JBoss AS documentation shows how you can define the max redelivery as well as dead letter queue configurations. You’ll need to open up the Enterprise Archive, jbpm-enterprise.ear, to get to the file, jbpm-enterprise.jar. This file contains the ejb-jar.xml and jboss.xml files you need to modify to change the jbpm configuration of the message driven bean.

The only thing missing with this JMS transitioning in jBPM is that the node receiving the transition does not have knowledge on whether the message was redelivered or not. Future versions might incorporate this knowledge. I have pinged the jBPM team and there is some discussion on the jbpm forum.

That’s about it! Yeah, I know a lot of this stuff is basic, hope I didn’t bore you too much. I just wanted to set down some foundation for other topics I want to discuss that may use these JMS and jBPM features.

It’s free and it doesn’t suck

Leave a comment

Burr Sutter reminisces about Marc Fleury’s first Atlanta JUG presentation in 2002. Its a great story and a must read for anybody interested in JBoss history.

Unbreakable Red Hat

2 Comments

I’m angry again,

Came across Savio Rodrigues’s blog about whether Oracle would buy Red Hat and/or BEA. One particular comment is a very incorrect assumption, specifically Savio wrote:

By announcing Oracle Unbreakable Linux, Oracle has already proven that Red Hat doesn’t have a whole lot of technology that can’t be easily replicated. ….

Maybe Savio believes that Red Hat doesn’t produce any technology? JBoss aside, I used to think that Red Hat was just a packager and was surprised to find out this wasn’t the case. They are one of the biggest presences the Linux and FSF community. I was astounded by the kind of quality engineers Red Hat has in key positions in the OSS community.

Or maybe Savio believes what Larry believes, that since Red Hat is all open source based Oracle can steal whatever IP they want and that’s the end of that. I’m not sure either of them understands that professional open source runs on top of the same fundamentals of any other business. Brand, employees, management, happy customers, and ability to execute and innovate. Let’s face it, open source is a software industry segment. Only Red Hat has proven it can execute effectively in such a space. If you’re just going to “take Red Hat’s IP”, you still have to establish strong OSS community relations, you still have to have great engineers that know the software, productization teams that know how to take raw OSS projects and turn them into a product you can support for 5 years, you need sales people that know how to sell it, marketing that knows how to promote, management that knows how to deal with “freetards” and open source prima donas.

None of this means that Oracle can’t establish itself in Red Hat’s market, it just means that as long as Red Hat continues to execute and innovate they will still be the leaders. Over the years JBoss had to go through various crisis’s in order to grow up as a company, I remember myself panicking thinking we were done, it was over. Marc and Sacha, always the steady hands say, “just continue to execute and everything will be fine”. You know what? It was. When you see us stop being able to execute, then you can say we’re done.

Co-existence with Hibernate, JPA, and EJB3

22 Comments

How can you slowly migrate existing Hibernate apps to JPA? How can you use Hibernate features and unique mapping capabilities with a JPA deployment? How can you take advantage of EJB3 injection and persistence context management with Hibernate? In this blog I want to show how Hibernate, JPA, and EJB 3.0 can co-exist and compliment one another. This information is fully documented between the Hibernate and JBoss EJB3 projects, but I thought I’d highlight them in this blog to make the community aware that they exist.

Mixing and matching JPA annotations within Hibernate

Using the standard JPA annotations helps out greatly in cutting down the amount of XML metadata you have to type. This annotation metadata is an exact replacement for much of the metadata in hbm.xml. Using them does not require you to use the JPA EntityManager interface. You may still use SessionFactory and Session objects to interact with your database. After downing the Hibernate Anotations project, setting things up is fairly easy:

SessionFactory sessionFactory =
                  new AnnotationConfiguration().buildSessionFactory();

You use hibernate.cfg.xml to specify which exact classes you want mapped by this SessionFactory:

<hibernate-configuration>
 <session-factory>
    <mapping class="com.acme.Flight"/>
    <mapping class="org.jboss.Sky"/>
    <mapping resource="org.acme.orm.xml"/>
 </session-factory>
</hibernate-configuration>

You can mix hbm.xml mapping files with new annotated classes. XML resources can also either be JPA-based XML or Hibernate based. This mixing and matching allows you to quickly prototype new mappings using JPA, but allows these mappings to co-exist with older Hibernate 3 applications.

There are a few more options for configuration. Check out the Hibernate Annotations documentation for more information.

Use Hibernate to configure JPA

If you want to use the JPA Entity Manager API to code a portable application, you may still want to use Hibernate metadata to map your beans. Although the JPA orm mapping is pretty rich, it is still a subset of Hibernate’s functionality. The Hibernate Annotations project provides additional Hibernate-specific annotations to elaborate a persistence mapping where JPA leaves off. If you prefer XML, you can use hbm.xml files to define the mappings for your entity beans. When loading a persistence archive, Hibernate Entity Manager will automatically scan the .jar file for any *hbm.xml files and add them to its mapping information.

Hibernate specific configuration is defined in the properties element of the persistence.xml file. You can configure any hibernate property within this XML blob

<persistence>
 <persistence-unit name="manager1" transaction-type="JTA">
    <jta-data-source>java:/DefaultDS</jta-data-source>
    <properties>
       <property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/>
 </persistence-unit>
</persistence>

You may also define all your hibernate configuration in the usual Hibernate way: within a hibernate.xfg.xml file. You must tell the JPA implementation to use this configuration file through the hibernate.ejb.cfgfile property.

<persistence>
 <persistence-unit name="manager1" transaction-type="JTA">
    <jta-data-source>java:/DefaultDS</jta-data-source>
    <properties>
       <property name="hibernate.ejb.cfgfile" value="/hibernate.cfg.xml"/>
    </properties>
 </persistence-unit>
</persistence>

EJB 3.0 managed persistence sessions

EJB 3.0 has some nice integration with JPA. You can have your EJB session beans manage persistent sessions for you, freeing you from having to create, destroy, and clean up your persistence sessions. It can manage your persistent sessions in two ways:

Transaction-scoped persistence contexts

Transaction-scoped persistence contexts can be injected into your stateful, stateless, or message driven beans. These transaction-scoped contexts only live for the duration of the JTA transaction they are invoked within. When you first interact with an injected transaction-scoped EntityManager within a transaction, an underlying persistence context (in other words, a Hibernate session) is transparently created and associated with the transaction. This associated context is propagated automatically to an nested EJBs that invoke on entity managers of the same persistent unit type. This means that any EJB that invokes on an entity manager will be using the same underlying Hibernate Session.

@Statelesspublic class MyBean implements MyInterface {

 @PersistenceContext(unitName="custDb") EntityManager manager;

...

Extended persistence contexts

In Hibernate terminology, an extended persistence context is one particular Hibernate session. This session may live beyond the duration of a JTA transaction. In EJB 3.0, you can inject an extended persistence context into a stateful session bean. Unlike transaction-scoped entity managers, these persistence contexts are not created and destroyed in a transaction, but instead have their lifecylce tied to that of the SFSB session. This allows you to have conversations with your database that span multiple JTA transactions.

@Statefulpublic class ShoppingCartBean implements ShoppingCart {
{
 @PersistenceContext(unitName="custDb", type=EXTENDED) EntityManager manager;
...
}

Using EJB 3.0 injection annotations with Hibernate

The JBoss EJB 3.0 implementation allows you to use Hibernate Session and SessionFactory as types for targets of the @PersistenceContext and @PersistenceUnit annotations. The injected Session or SessionFactory will behave exactly as if you were instead using the JPA counterparts EntityManager or EntityManagerFactory:

@Statelesspublic class MyBean implements MyInterface
{
 @PersistenceContext(unitName="custDb") org.hibernate.Session session;
 @PersistenceUnit(unitName="custDb") SessionFactory factory;
...
}

Just like with the EJB 3.0/JPA integration, the Hibernate Session will be associated with the JTA transaction and propagated to nested EJB invocations within the same transaction. It is also ok if these nested calls use the EntityManager API instead. The same underlying Hibernate session will still be used for both.

Hiberate Sessions can also represent extended persistence contexts:

@Statefulpublic class ShoppingCartBean implements ShoppingCart
{
 @PersistenceContext(type=EXTENDED) org.hibernate.Session session;
...
}

Again, the EJB container will manage this Hibernate Session the same way it would manage an EntityManager instance.

Obtaining Hibernate objects programmatically

You can always get access to a Hibernate Session object from an EntityManager instance through the standard EntityManager.getDelegate() method. This is a JPA specification feature.

  @PersistenceContext EntityManager manager;
  ...
{      org.hibernate.Session session = (Session)manager.getDelegate();  }

The specification, however, does not provide a way to get at the underlying implementation of a Query. Hibernate should provide most of its extended functionality through JPA query hints. For example, lets say you wanted to enable a query cache:

  javax.persistence.Query query = manager.createQuery(...);
  query.setHint("org.hibernate.cacheable", true);

Conclusion

Hibernate and the JBoss EJB 3.0 project provide multiple ways in which you can mix and match Hibernate and JPA annotations and XML metadata. JBoss EJB 3.0 can manage Hibernate typed objects the same way it can manage JPA objects. Finally the specification provides programmatic ways to get at the underlying Hibernate connection. With the features you should have the flexibility to get at the HIbernate features you need while staying as portable as possible under the JPA specification. Or conversely, you can use well-defined JPA mapping annotations within your Hibernate deployments to make coding simpler and easier.

Disclaimer 😉 This blog was meant to make you aware of certain integration features that exist between JPA, Hibernate, and JBoss EJB 3.0. You should not use it as a reference guide, but rather dive down deeper into each project’s docoumentation. Have fun.

Newer Entries