Results 1 to 7 of 7

Thread: Hibernate update from within Runnable ?

  1. #1

    Question Hibernate update from within Runnable ?

    Hi,

    I am having a problem using Hibernate with Spring-managed sessions within a threaded object.

    I have a class that extends Runnable that I use to read byte arrays from a socket that's connected to an external system. It is instantiated using Thread.

    I get a nullPointerException error when I try to get the Spring sessionFactory that I've injected into the class. Also, if I call my DAO objects to do database updates from within the Thread, I also get a nullPointerException for the Hibernate session.

    My DAO classes work fine when I do not call them from a Thread. I use a separate session to avoid deadlock issues.

    Starting thread:

    Code:
    Thread thread = new Thread(new MyThreadedClass(param1, param2));
    			thread.start();
    MyThreadedClass is fairly big, so I will just post salient snippets:

    Code:
    @Repository
    public class MyThreadedClass implements Runnable {
    	
    	private SessionFactory sessionFactory;
    
    	@Autowired
    	public void setSessionFactory(SessionFactory factory)
    	{
    		sessionFactory = factory;
    	}
    
    @Transactional
    	public void updateDatabase()
    	{
    		
    		Session mySession = sessionFactory.openSession();
    		Transaction tx = null;
    		
    		try {
    			tx = mySession.beginTransaction();
    		} catch (HibernateException e1) {
    			logger.error("!!!!!!!!! booHooHoo  failed to start transaction : {}", e1);
    		}
    	
    		try
    		{
    			mySession.update(myTable);
    			tx.commit();
    		}
    		catch (HibernateException e)
    		{
    			logger.error("!!!!!!!!! booHooHoo  update of myTable failed : {}", e);
    		}
    Please help !
    Last edited by Slidewayz; Aug 16th, 2011 at 03:47 AM.

  2. #2
    Join Date
    Jun 2006
    Location
    The Netherlands
    Posts
    13,632

    Default

    So you expect the instance you create yourself to be injected by spring... Now spring can do much but it won't do that (not without work)... Create a bean definition and make it prototype scoped, then instead of creating a new instance retrieve a new instance from the application context.
    Marten Deinum
    Java Consultant / Pragmatist / Open Source Enthousiast / Author


    Pro Spring MVC: With Web Flow
    Conspect

    Have you read the reference guide.
    Use the [ code ] tags, young padawan

  3. #3

    Default

    Thank you, Marten...it makes perfect sense that Spring can't autowire an object I create myself.

    I just read the Spring doc on Bean scopes, so that explains how to define the bean in the applicationContext. I assume I could @Autowire it into my calling class. Since I am doing asynchronous comm. to multiple external devices, would I use SimpleAsyncTaskExecutor to create the threads, with Spring dynamically injecting the sessionFactory for each instance ? It is not clear to me how these would get garbage-collected...is that handled by SimpleAsyncTaskExecutor's relationship to the Spring container or do I still need a custom bean post-processor?

    Thanks again !!!

  4. #4
    Join Date
    Jun 2006
    Location
    The Netherlands
    Posts
    13,632

    Default

    I suggest a read of the reference guide... IMHO you should simply use a TaskExecutor to execute your tasks. The task I would configure in the application with the scope prototype. Then simply wire the TaskExecutor and the BeanFactory/ApplicationContext and use that to retrieve the bean, that should also take care of of gc'ing in the end...

    Code:
    @Autowired
    private TaskExecutor executor;
    
    @Autowired
    private ApplicationContext context;
    
    public void scheduleUpdateTask() {
      Runnable myTask = context.getBean("myTask");
      executor.execute(myTask);
    }
    Now you can also take advantage of @Transactional and you shouldn't need to mess around with the session/transactions yourself....

    Again I suggest a read of the scheduling/executor chapter of the reference guide.
    Marten Deinum
    Java Consultant / Pragmatist / Open Source Enthousiast / Author


    Pro Spring MVC: With Web Flow
    Conspect

    Have you read the reference guide.
    Use the [ code ] tags, young padawan

  5. #5

    Default

    Thanks again, Marten.

    I've read up on and tried some examples for TaskScheduler/TaskExecutor.

    The only issue I'm now facing is how to set dynamic constructor properties in the prototype object I've obtained from the context.

    Lamentably, casting the object to my class (or back to Runnable) so I can set its properties does not work, as I get a 'Proxy cannot be cast to' error.

    This doesn't work:

    Code:
    MyTaskObj myTaskObj = (MyTaskObj) context.getBean("myTaskObj");
    			myTaskObj.setParam1(objectA);
    			myTaskObj.setParam2("myString");
    			Runnable myTask = (Runnable) myTaskObj;
    		        taskExecutor.execute(myTask);
    I haven't found any examples that show how to dynamically set properties for beans retrieved from the context. I have to pass in the ipAddress and the
    requestType for each device.

    The Spring documentation show how to define constructor arguments, but not how to pass them in to an object retrieved from the context:

    Code:
    <bean id="exampleBean" class="examples.ExampleBean">
         <constructor-arg name="years" value="7500000"/>
         <constructor-arg name="ultimateanswer" value="42"/>
    </bean>
    It has to be fairly common for someone to read in data from a socket and persist it to a database using Spring/Hibernate ? Any advice is
    very warmly received !!!

  6. #6
    Join Date
    Jun 2006
    Location
    The Netherlands
    Posts
    13,632

    Default

    There is a getBean method which takes more arguments and one of those methods also takes arguments which will be used as constructor arguments.
    Marten Deinum
    Java Consultant / Pragmatist / Open Source Enthousiast / Author


    Pro Spring MVC: With Web Flow
    Conspect

    Have you read the reference guide.
    Use the [ code ] tags, young padawan

  7. #7

    Default

    Quote Originally Posted by Marten Deinum View Post
    There is a getBean method which takes more arguments and one of those methods also takes arguments which will be used as constructor arguments.
    Thanks again, Marten. It is definitely getting closer.

    I am throwing a null exception now on the update because I am not passing in
    'object' to myTask. So, there are 2 parameters, one Object and one String that
    need to be passed in.

    Please let me know if you see any problem with how I did it. Also, do you have
    any books you could recommend that cover stuff like this? I have Spring Enterprise
    Recipes, but it does not go into this kind of detail.

    Thanks again !!!

    Code:
    Runnable myTask = (Runnable) context.getBean("MyTask", object, stringParam);
    
    <bean id="myTask"
    	  class="externalInterface.MyTask"
    	  scope="prototype">
    		  <constructor-arg name="object" value="object"/>
    		  <constructor-arg name="stringParam" value="stringParam"/>
    		  <property name="sessionFactory" ref="sessionFactory"/>
    </bean>

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •