-
1. Re: Failed to deserialize object error
clebert.suconic Sep 11, 2009 2:21 PM (in response to rnicholson10)No.. it's not any different.
You're using ObjectMessages... perhaps there is some classpath issue regarding classLoaders on the JCA.
Maybe you could (as a test) add your POJO to the main classpath on JBAS. -
2. Re: Failed to deserialize object error
timfox Sep 11, 2009 2:25 PM (in response to rnicholson10)Yuck. What is it with everyone using ObjectMessages today? ;)
catch (Exception e) { JMSException je = new JMSException("Failed to deserialize object"); je.setLinkedException(e); throw je; }
If you catch the exception and log out the linked exception it will tell you why it couldn't deserialize it.
Maybe you don't have your user "Ack" class on your classpath of your receiver? -
3. Re: Failed to deserialize object error
timfox Sep 11, 2009 2:25 PM (in response to rnicholson10)If you can avoid ObjectMessage, it's much better.
-
4. Re: Failed to deserialize object error
clebert.suconic Sep 11, 2009 3:08 PM (in response to rnicholson10)Anyway, there seems to be a small issue in our code.
I just compared our activation code to the JBAS activation code.
JBAS will call endpoint.beforeDelivery and afterDelivery when a call is being made:endpoint.beforeDelivery(JmsActivation.ONMESSAGE); try { if (dlqHandler == null || dlqHandler.handleRedeliveredMessage(message) == false) { MessageListener listener = (MessageListener) endpoint; listener.onMessage(message); } } finally { endpoint.afterDelivery(); if (dlqHandler != null) dlqHandler.messageDelivered(message); } }
While our JCA's code will just do a plain call to onMessage:public void onMessage(final ClientMessage message) { if (trace) { log.trace("onMessage(" + message + ")"); } TransactionDemarcationStrategy txnStrategy = strategyFactory.getStrategy(); try { txnStrategy.start(); } catch (Throwable throwable) { log.warn("Unable to create transaction: " + throwable.getMessage()); txnStrategy = new NoTXTransactionDemarcationStrategy(); } HornetQMessage msg = HornetQMessage.createMessage(message, session); try { msg.doBeforeReceive(); message.acknowledge(); } catch (Exception e) { log.error("Failed to prepare message for receipt", e); return; } try { ((MessageListener) endpoint).onMessage(msg); } catch (Throwable t) { log.error("Unexpected error delivering message " + message, t); txnStrategy.error(); } finally { txnStrategy.end(); } }
I also looked further, and EJB3 will use that hook to set the classpath:protected void before(Object proxy, MessagingContainer container, Method method, Object[] args) throws Throwable { // Called out of sequence if (oldClassLoader != null) throw new IllegalStateException("Missing afterDelivery from the previous beforeDelivery for message endpoint " + getProxyString(proxy)); if (trace) log.trace("MessageEndpoint " + getProxyString(proxy) + " released"); // Set the classloader oldClassLoader = GetTCLAction.getContextClassLoader(inUseThread); SetTCLAction.setContextClassLoader(inUseThread, container.getClassloader());
This will be a problem with any other classloading operations... not just Object Serialization. So I'm opening a JIRA:
https://jira.jboss.org/jira/browse/HORNETQ-134
@rnicholson10: As a workaround, you could add your JAR to the main classpath. or set the context classLoader manually (as I specified on the JIRA above) -
5. Re: Failed to deserialize object error
timfox Sep 11, 2009 3:43 PM (in response to rnicholson10)I don't follow.
Can you explain in more detail why this is an issue? -
6. Re: Failed to deserialize object error
clebert.suconic Sep 11, 2009 4:12 PM (in response to rnicholson10)It's simple: We are supposed to call endpoint.beforeDelivery and afterDelivery. That's part of the contract (I bet this will be on the JCA spec), and we are not doing it.
EJB3 needs to setup the classLoader at the client's application, and the above hook is the where this was supposed to happen.
We used to make that call:
http://viewvc.jboss.org/cgi-bin/viewvc.cgi/hornetq/trunk/src/main/org/hornetq/ra/inflow/HornetQMessageHandler.java?r1=7466&r2=7604
After we removed the beforeDelivery call, onMessage will have a different classLoader set on the ContextClassLoader. Any classLoader operation done at the client level could happen on a wrong classLoader. -
7. Re: Failed to deserialize object error
clebert.suconic Sep 11, 2009 4:49 PM (in response to rnicholson10)BTW: the fix would be pretty simple... I just want to hear from Andy first (if he had any reason behind it or if he removed it by a mistake).
-
8. Re: Failed to deserialize object error
timfox Sep 12, 2009 2:34 AM (in response to rnicholson10)I remember discussing this in detail with Andy when we were working out where we had to manage transactions in the JCA adaptor.
Andy consulted the spec and said that calling before and end endpoint were optional - apparently we are allowed to omit the calls.
Now, what you're saying is that is not true. We need to consult the JCA spec to make sure. -
9. Re: Failed to deserialize object error
clebert.suconic Sep 12, 2009 3:26 AM (in response to rnicholson10)Now, what you're saying is that is not true. We need to consult the JCA spec to make sure.
Well... I don't know about the spec yet. All I know is what I briefly read on the EJB3 code, that the ClassLoader is set/unset through those calls.
I tried to look at the spec but couldn't find anything. Maybe I was looking at the wrong doc.
I will take a look again over the weekend. -
10. Re: Failed to deserialize object error
timfox Sep 12, 2009 7:40 AM (in response to rnicholson10)"clebert.suconic@jboss.com" wrote:
I tried to look at the spec but couldn't find anything. Maybe I was looking at the wrong doc.
I'm surprised you couldn't find anything.
It's the JCA 1.5 spec, easily downloadable from java.sun.com.
Chapter 12 goes into great detail about message inflow, and the various contracts.
At first glance it looks like our impl is wrong.
I've said this before, but *the spec needs to be studied* before writing an implementation!! -
11. Re: Failed to deserialize object error
clebert.suconic Sep 12, 2009 10:34 AM (in response to rnicholson10)I didn't implement it... so I never read the spec.
On Friday, I did a very quick search, and I was looking for the wrong names... that' s why I couldn't find anything.
As I said I would look over the weekend, the chapter 12 states that the application server must set and reset the classloader on the before and afterDelivery, and that before and afterDelivery are considered part of a single message delivery. So it is part of the spec indeed. -
12. Re: Failed to deserialize object error
clebert.suconic Sep 12, 2009 10:39 AM (in response to rnicholson10)Actually, I did read it before.. but JCA is something that I could never digest before.
But now after I read Jesper's and Andy's implementation it's easier to digest it. -
13. Re: Failed to deserialize object error
rnicholson10 Sep 12, 2009 2:24 PM (in response to rnicholson10)Clebert, thanks for the workaround.
It has already let me test performance on HQ with our current system and I have to say I'm, hugely impressed. Configuration is a easy compared to JBM 1.4, the documentation is well written and easy to follow and the examples invaluable.
Well done to everyone involved! -
14. Re: Failed to deserialize object error
timfox Sep 13, 2009 4:20 AM (in response to rnicholson10)"clebert.suconic@jboss.com" wrote:
Actually, I did read it before.. but JCA is something that I could never digest before.
Yes, it's not fun reading the JCA spec ;)