Announcement Announcement Module
No announcement yet.
Service activators and channel adapters in their own threads? Page Title Module
Move Remove Collapse
Conversation Detail Module
  • Filter
  • Time
  • Show
Clear All
new posts

  • Service activators and channel adapters in their own threads?

    My problem currently is that i need to start transactions for each of the method calls to a service activator, and a channel adapter. I have to use an existing hibernate configuration + DAO's, and therefor can't really use spring managed session factories and transaction management.

    In spring batch I "solved" this in Tasklets by advicing the execute method of the Tasklet interface, and instead calling my own method via an interface.

    public RepeatStatus execute(StepContribution sc, ChunkContext ctx, MySessionFactory mf) throws Exception;
    But this is not really possible in spring integration, without breaking all the really fancy functionality and flexibility that the annotations give you.

    So I'm looking for suggestions on how to handle this, one thing i was thinking of is to use ThreadLocal sessions and management, like in a typical web app, but can I somehow guarantee that each call to a @ServiceActivator (even if a single instance has >1), and channel adapters will be run in their own threads so that theres no chance of executions using each others hibernate sessions?

    Is defining a <task:executor/> in the context enough? What will the task executor end up running in separate threads?

  • #2
    What is type of channel-adapter are you using here? If I understand correctly, you need a transaction to begin *before* the call to the service-activator's referenced POJO but to end only *after* a successful call to the channel adapter?


    • #3
      Basically I'm just loading hibernate POJOS, evicting them from the session and sending them as payload in Messages.

      Currently the system looks like this:

      Inbound-adapter -> List<Pojo> -> splitter -> Message<Pojo> -> serviceactivator (calls remote service with data and updates pojo via hibernate session if needed)

      Basically what I'd need is a way to have a hibernate session open and available
      a) during one messages travel from inbound-apdater to service activator
      b) during inbound-adapter AND serviceactivator method calls

      which would basically mean
      a) single message travels from start to end in the same thread so I can use ThreadLocal sessions
      b) each call to a pojo method (service activator, channel adapter) would be in their own threads so i can use ThreadLocal sessions

      In Spring batch i used AoP (see first post) to open up the session and "inject" the legacy session/dao/etc handling system with the tasklet execute() call, but I cant think of anything similiar for spring integration due to the use of annotations instead of interfaces


      • #4
        I'm not fully understanding how you are "injecting" the SessionFactory in the Spring Batch case. It seems like that would be something that occurs in your DAO code (or proxies for those instances). Can you explain?


        • #5
          Ok, I changed my approach a bit.

          Now spring manages the SessionFactory, and I basically need to do the following:

          public void doSomething(Message<?> msg) {
            OurDAOSystem daofactory = new OurDAOSystem(this.sf.openSession());
            // do stuff
            daofactory.commit(); //or rollback etc...
          So basically i can do what I need to do.

          What I'm having trouble getting my head around is: how is this supposed to be done "properly" via the DAO pattern? In a webapp it's trivial to use ThreadLocal stored sessions and request scope dao beans (and then use .getCurrentSession()), but I just can't figure this part out being pretty much a spring newbie

          Any tips appreciated

          edit: in spring integration specifically, spring batch has step scope and interfaces i can advice, just looking for some "best practices" info so I don't end up shooting myself in the foot
          Last edited by deebo; May 20th, 2010, 05:08 AM.


          • #6
            The "right" way, I suppose, means using Spring's declarative transaction model with the HibernateTransactionManager. That will open and close the Sessions at the transaction boundaries, and it will also set the "currentSession" for the SessionFactory. The only prerequisite to take advantage of that approach is to inject the same instance of SessionFactory into the HibernateTransactionManager as well as any DAOs. The DAOs can then call sessionFactory.getCurrentSession() whenever they perform data access operations.

            The thing that I notice about your code excerpt is that you are instantiating the DAO factory object every time you use it. If you could create that once and inject a SessionFactory (instead of injecting the stateful "Session" instance), then it seems like you would be on the track to the typical usage of Spring with Hibernate.

            Hope that helps.