Java – Use Spring to start threads at server startup in weblogic

Use Spring to start threads at server startup in weblogic… here is a solution to the problem.

Use Spring to start threads at server startup in weblogic

I want to start a thread when the server starts. My thread fetches data from the database and puts it into a JMS queue. All beans are defined in the Spring configuration file. JMS QUEUES AND DATABASE CONNECTION FACTORIES (CONNECTION-FACTORIES) ARE CONFIGURED ON WEBLOGIC.
I’m trying to put my thread startup code inside the contextInitialized method of the ContextLoaderListener or the init method of the servlet. But I get the following exception when starting the server:

nested exception is
javax.naming.NoPermissionException:
User anonymous does not have
permission on CONNECTION-FACTORY to
perform lookup operation.

If I put the code in the servlet’s doGet method and hit the url after the server starts, my code will work perfectly. But I don’t want to start the thread manually.

I

think I’m getting this error because all beans are not initializing properly.

Where should I put my code so that the thread starts automatically after the server starts?

Solution

If you are creating your own threads, that is most likely the problem. In any application server, you should let the container manage the thread pool and schedule only any jobs you might want to run.

Add this to your web.xml:

<resource-ref>
    <res-ref-name>timer/MyTimer/res-ref-name>
    <res-type>commonj.timers.TimerManager</res-type>
    <res-auth>Container</res-auth>
    <res-sharing-scope>Unshareable</res-sharing-scope>
</resource-ref>

In your applicationContext.xml (requires spring-context-support JAR):

<bean id="scheduler" class="org.springframework.scheduling.commonj.TimerManagerTaskScheduler" scope="singleton">
    <property name="timerManagerName" value="java:comp/env/timer/MyTimer"/>
</bean>    

Then do it in your contextInitialized(…).

scheduledFuture = scheduler.schedule(new MyJob());

Then execute it in your contextDestroyed(…);

scheduledFuture.cancel(true);

In my project I couldn’t find anything about configuring timers at the application server level, so I’m guessing it “works”.

If you want to generate a job asynchronously (via java.lang.concurrent.Executor interface), the process is similar, but you need to configure a thread pool in Weblogic:

In web.xml;

<resource-ref>
    <res-ref-name>wm/MyWorkManager</res-ref-name>
    <res-type>commonj.work.WorkManager</res-type>
    <res-auth>Container</res-auth>
</resource-ref>

In applicationContext.xml:

<bean id="executor" class="org.springframework.scheduling.commonj.WorkManagerTaskExecutor" scope="singleton">
    <property name="workManagerName" value="java:comp/env/wm/MyWorkManager"/>
</bean>

In your weblogic .xml (or the equivalent of EARs), something like:

<work-manager>
    <name>wm/MyWorkManager</name>
    <min-threads-constraint>
        <name>minThreads</name>
        <count>1</count>
    </min-threads-constraint>
    <max-threads-constraint>
        <name>maxThreads</name>
        <count>20</count>
    </max-threads-constraint>
</work-manager>    

In your code:

executor.execute(new MyRunnable());

Read Weblogic docs on timers and work managers More information about job scheduling for this specific application server.

Related Problems and Solutions