[Design of Messaging on JBoss (Messaging/JBoss)] - Re: Incorporating Remoting http transport into Messaging
by ron_sigal
I. The central change has been to push callbacks back down into the Remoting layer. In particular, where on HEAD ServerConsumerEndpoint.Deliverer gets the ServerInvokerCallbackHandler's Client and delivers messages to the client side using Client.invoke(), on the HTTP branch it calls ServerInvokerCallbackHandler.handleCallback(). As a result, Messaging can take advantage of Remoting's variety of callback options. In particular, the relevant choices are:
(a) push callbacks: a Connector (complete with ServerSocket) is created on the client side, and calling ServerInvokerCallbackHandler.handleCallback() causes an invocation to be made from server side to client side.
(b) poll callbacks: calling ServerInvokerCallbackHandler.handleCallback() causes the callback to be stored (possibly on disk) until the client side polls for pending callbacks. No ServerSocket is created on the client side.
It is my understanding that option (a) is suitable for the socket transport, and option (b) is suitable for the HTTP transport. Switching between the two is done by the following code in JMSRemotingConnection.start():
| boolean doPushCallbacks = "socket".equals(serverLocator.getProtocol());
| if (doPushCallbacks)
| {
| if (log.isTraceEnabled()) log.trace("doing push callbacks");
| HashMap metadata = new HashMap();
| metadata.put(InvokerLocator.DATATYPE, "jms");
| metadata.put(InvokerLocator.SERIALIZATIONTYPE, "jms");
| client.addListener(callbackManager, metadata, null, true);
| }
| else
| {
| if (log.isTraceEnabled()) log.trace("simulating push callbacks");
| HashMap metadata = new HashMap();
| metadata.put(CallbackPoller.CALLBACK_POLL_PERIOD, "100");
| client.addListener(callbackManager, metadata);
| }
|
The implementation of Client.addListener() does the rest.
Changes related to callbacks may be found in the following classes:
org.jboss.jms.client.remoting.CallbackManager
org.jboss.jms.client.remoting.CallbackServerFactory (no longer necessary)
org.jboss.jms.client.remoting.JMSRemotingConnection
org.jboss.jms.server.container.InjectionAspect
org.jboss.jms.server.endpoint.ServerConnecionEndpoint
org.jboss.jms.server.endpoint.ServerConsumerEndpoint
In order to replace invocations with callbacks, a callback acknowledgement facility was added to Remoting. When ServerConsumerEndpoint.Deliverer sends a callback, it also stores the callback in a pendingCallbacks HashSet, from which it is removed upon acknowledgement. ServerConsumerEndpoint.stop() waits for pendingCallbacks to go empty before returning. A callback is acknowledged in one of two ways:
- In the case of push callbacks, ServerInvokerCallbackHandler.handleCallback() does the acknowledgement after the callback has been pushed to the client side. At this point, the callback has been processed by MessageCallbackHandler.
- In the case of polled callbacks, the acknowledgement is initiated from the client side after the callback has been processed by MessageCallbackHandler.
TODO:
1. A callback ID should be stored in pendingCallbacks instead of the callback itself.
2. Unlike Client.invoke(), ServerInvokerCallbackHandler.handleCallback() does not return a response, so ServerConsumerEndpoint.Deliverer gets no feedback from the client side about throttling message flow.
II. The new Messaging specific serialization structure interacts with callbacks to generate some added complexity in JMSWireFormat. Because of the two forms of callbacks, there are two delivery modes for callbacks, and each has to be unwound to expose the ClientDelivery. For example, callback polling delivers an ArrayList of pending callbacks, and each ClientDelivery in the list has to be processed separately. There's also another related issue. In pull or poll mode, callbacks are stored on the server, which might involve writing them to secondary storage. Currently, the application's designated serialization type determines how the callbacks are transferred to and from disk, but MessagingObjectInputStream and MessagingObjectOutputStream are derived from the standard java classes, which can't handle Messaging non-Serializable messages. For now I've worked around the problem in my local version of Remoting, but the problem still needs to be resolved. Is there any reason the Messaging can't use JBoss Serialization?
III. I changed org.jboss.test.messaging.tools.jmx.ServiceContainer and org.jboss.test.messaging.tools.jmx.ServiceContainerConfiguration so that they can pick up the remoting transport from a <remoting-transport> element in tests/etc/container.xml.
IV. Right now the HTTP branch runs with my own private version of Remoting. I've checked in a copy of jboss-remoting.jar in the lib directory.
V. It's 4am and right now it looks like everything's broken. Great. Well, it WAS working.
View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=3978999#3978999
Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=3978999
19 years, 5 months
[Design of JBoss jBPM] - Re: MessageService and JMS
by mteira
So, as an implementation example of all this (take in mind that ant is new stuff for me): To allow switching between JMS and DB based messaging, we could use a jbpm.cfg.xml file containing:
<jbpm-configuration>
| <jbpm-context>
| <!--DB based Messaging (begin) ==
| <service name="message" factory="org.jbpm.msg.db.DbMessageService"/>
| == DB based Messaging (end) -->
| <!--JMS based Messaging (begin) ==
| <service name="message">
| <factory><bean class="org.jbpm.msg.jms.JmsMessageServiceFactoryImpl">
| <field name="connectionFactoryJndiName"><string value="java:/XAConnectionFactory"/></field>
| <field name="destinationJndiName"><string value="queue/JbpmJobQueue"/></field>
| </bean></factory>
| </service>
| == JMS based Messaging (end) -->
| ...
| </jbpm-context>
| </jbpm-configuration>
|
Now, how should we control what configuration to use? Could it be made using a property or something so? The examples I've found are uncommenting sections in an unconditional fashion. I think that this case is a little different, as we want to choose between two configuration modes.
Perhaps having local configuration files (in some place like local.config=${user.home}/jbpm/config ) should be simpler, and we could just try to use those files if they exist?
Regards.
View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=3978998#3978998
Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=3978998
19 years, 5 months
[Design of JBoss jBPM] - Re: MessageService and JMS
by tom.baeyens@jboss.com
i think i understand your problem. let me rephrase to see if i understood correct:
in the whole jbpm sources, we only want 1 source version of all the configuration files so that we don't have to search and update 20 different configuration files if a cfg property needs to be updated or added.
so now you want a different configuration.
here's my current approach. let me know if you see a better way.
i take the basic configuration file that is used for the unit tests as a starting point. Each time when i need a different configuration, i create a copy and apply modifications of certain parts in that file.
Several modifications techniques can be used.
Plain replace:
<replace dir="${tmp.dir}">
| <includesfile name="**/*.hbm.xml"/>
| <replacetoken><![CDATA[type="string_max"]]></replacetoken>
| <replacevalue><![CDATA[]]></replacevalue>
| </replace>
|
Or update the comments. In that case you put a commented section in the original file like this
<!-- CMT transaction properties (begin) ===
| <property name="hibernate.transaction.factory_class">org.hibernate.transaction.CMTTransactionFactory</property>
| <property name="hibernate.transaction.manager_lookup_class">org.hibernate.transaction.JBossTransactionManagerLookup</property>
| ==== CMT transaction properties (end) -->
|
so then you can use search and replace for the begin and end markers and replace the ==== pieces with the matching end of the comment. That way the commented section will be uncommented.
Most of the configurations that have to do with db properties can be specified from a .properties file rather then from inline in the properties in the hibernate.cfg.xml. In that case you can use any of the above 2 techniques to update the jbpm.cfg.xml and then add a reference to a properties file that is in cvs. then you can easily have a separate .properties configuration file instead of having your properties in the build script.
hope this helps.
let me know if something is not clear or needs improvement.
View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=3978992#3978992
Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=3978992
19 years, 5 months
[Design of JBossCache] - Re: API Issues integrating 2.0.0.DR1 in HEAD
by bstansberry@jboss.com
Sorry, last bit of last post got truncated...
"manik.surtani(a)jboss.com" wrote : anonymous wrote :
| | 6) The Node interface desribes various returned Collections as being immutable. From a glance at NodeImpl it looks like they aren't. Also, it would be good to be more clear about thread safety as immutable and thread safe aren't the same.
| |
|
| Which ones aren't? I may have missed some. The point is not for thread safety, but so changes go through the Node or Cache API and hence the interceptor stack.
|
Never mind re: not being immutable. I was looking at NodeImpl, which I see now doesn't actually implement Node. :-)
The concern I have re: thread safety is if a collection backed by the internal data structure of a node is exposed, you can get a ConcurrentModificationException just iterating over it. Not sure if that really happens. I saw NodeImpl.getDataKeys() exposes a collection backed by the data map. Haven't followed the code to see what happens to it. But, if that gets passed to a caller, any lock on the node could easily be released before the collection is even received by the caller (assume no tx). Thus easy to have another thread modify the data map via a put/remove while the first thread is iterating. Actually, as I write this, if what I'm describing is there, it's not a javadoc issue, it's something that needs to be changed.
View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=3978959#3978959
Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=3978959
19 years, 5 months
[Design of JBossCache] - Re: API Issues integrating 2.0.0.DR1 in HEAD
by bstansberry@jboss.com
"manik.surtani(a)jboss.com" wrote :
| * What callback do I need to provide for the DI from the MC?
| * The TM can be retrieved using the CacheSPI, again perhaps this could be downgraded to be accessible from Cache. Accessing this from the Configuration doesn't make much sense since the Configuration should be a valid, testable and checkable object even when the cache is not running while the TM is a resource that should only be available when the cache is running.
I'd have to think about it if doing it through the configuration is no good (I agree w/ what you're saying about that.) What I've been thinking about w/ the MC is to have it build the config and then create the cache via the factory. I suppose once its done that it could inject the TM via a setTransactionManager method. But that sounds like a hack.
This isn't a critical issue; the session repl thing is a bit of an odd case and I've got a (hacky) workaround for it.
anonymous wrote : anonymous wrote :
| | 5) Why is Node.getChildren() a Collection and not a Set? I expect it's because Map.getValues() is a Collection, but properly this method should return Set.
| |
|
| You guessed why. :-) Does it make more sense as a Set? I suppose so, since only one instance of each child would exist. I'd need to think of an efficient way to do this though, as iterating and creating a new set every time getChildren() is called is sub-optimal.
|
Probably not worth it. I just mentioned it because I happened to notice it.
anonymous wrote :
| 6) The Node interface desribes various returned Collections as being immutable. From a glance at NodeImpl it looks like they aren't. Also, it would be good to be more clear about thread safety as immutable and thread safe aren't the same.
|
Which ones aren't? I may have missed some. The point is not for thread safety, but so changes go through the Node or Cache API and hence the interceptor stack.
View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=3978957#3978957
Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=3978957
19 years, 5 months