I'm adding some features to an old EJB 2 application using Spring. The Spring application context used by the EJBs is a parent context of the web application as described here.
I'm trying to use a session scoped bean from within the EJBs. The bean in question is initialized from the EJB application context.
However, I get this error when trying to access the bean:
Caused by: java.lang.IllegalStateException: No Scope registered for scope 'session'
From what I've read, this is because the parentContextKey is not an instance of WebApplicationContext. Does anyone have an ideas of how I could get this working?
You may try to register the scope manually:
<bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
<property name="scopes">
<map>
<entry key="session">
<bean class="org.springframework.web.context.request.SessionScope"/>
</entry>
</map>
</property>
</bean>
I guess it should work, because SessionScope itself depends only on the thread-bound request context exposed by the RequestContextListener and doesn't depend on the application context.
You can only use session-scoped Spring beans from within a Spring WebApplicationContext. There's no getting around this - no WebApplicationContext, no session-scoping.
Perhaps if you explained what you're trying to achieve, we could help further. Are you perhaps conflating stateful session EJBs with servlet sessions? They're not the same thing.
Related
The application uses Spring JMS Listener to connect to JMS Queues and it is deployed in WAS 8.5.x.
Using spring application context xml, org.springframework.jms.listener.DefaultMessageListenerContainer bean is initialized with ConnectionFactory, Destination as JndiObjectFactoryBean.
Inside MessageListener class onMessage() method, the code is trying to look JNDI reference using InitialContext, code snippet is below,
InitialContext ic = new InitialContext();
String name = (String) ic.lookup("jndiName");
Application throws below exception while processing a message.
Exception : javax.naming.ConfigurationException: A JNDI operation on
a "java:" name cannot be completed because the server runtime is not
able to associate the operation's thread with any J2EE application
component. This condition can occur when the JNDI client using the
"java:" name is not executed on the thread of a server application
request. Make sure that a J2EE application does not execute JNDI
operations on "java:" names within static code blocks or in threads
created by that J2EE application. Such code does not necessarily run
on the thread of a server application request and therefore is not
supported by JNDI operations on "java:" names. [Root exception is
javax.naming.NameNotFoundException: Name comp/env/cache not found in
context "java:".]
My understanding is, the Message Listener threads are created by the application during initialization under J2EE Web Container. The code is trying to access JNDI resource defined in WebSphere server, but not able to get the handle to Initial Context.
Note: resource-ref tag with this JNDI entry is included in web.xml.
<resource-ref id="configCache">
<description>Resource reference to Configuration Cache</description>
<res-ref-name>cache/config</res-ref-name>
<res-type>com.ibm.websphere.cache.DistributedMap</res-type>
<res-auth>Container</res-auth>
<res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>
Any help would be appreciated.
I was able to fix this problem.
Here is the solution,
In web.xml I defined the Resource reference of type com.ibm.websphere.cache.DistributedMap. I created the JNDI (of type Object Cache) in WebSphere Admin console and map it to this resource during deployment.
<resource-ref id="sampleCacheName">
<description>Resource reference to Cache</description>
<res-ref-name>cache/sampleCache</res-ref-name>
<res-type>com.ibm.websphere.cache.DistributedMap</res-type>
<res-auth>Container</res-auth>
<res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>
In my spring context xml, I defined the JMS Listener bean which takes Task Executor object from default WebSphere work manager,
<bean id="jmsContainerSampleEvent"
class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="myConnectionFactory" />
<property name="destination" ref="myQueue" />
<property name="messageListener" ref="myEventListener" />
<property name ="concurrentConsumers" value ="5"/>
<property name ="maxConcurrentConsumers" value ="20"/>
<property name="taskExecutor" ref="workManagerTaskExecutor" />
</bean>
<bean id="workManagerTaskExecutor"
class="org.springframework.scheduling.commonj.WorkManagerTaskExecutor"
p:workManagerName="wm/default" />
I am using ehcache in my project so when server start data of few table will be loaded into the cache ..in my application i am using Spring,Hibernate,JSF
I m using this configurationin applicationCOntext.xml file
<bean id="cacheManager" class="com.ccc.service.cache.CacheManager" init-method="init">
<property name="delay" value="${timer.delay}" />
</bean>
<bean id="companyCache" class="com.ccc.service.cache.clients.ValidCacheClient"/>
<context:component-scan base-package="com.ccc.spring" />
<context:annotation-config />
<context:spring-configured />
In Jsf Managed Bean i am creating Object of Service class like this
#ManagedProperty(value = "#{GlobalDataService}")
static GlobalDataService globalDataService;
But in ValidCacheClient.java how to create object of Service class? ValidCacheClient.java is not a manged class so how to create the Object of Service class?
You have two options:
Inject the necessary beans to be known from JSF as ServletContext attributes, so these beans will be treat by JSF as application scoped attributes. You can do this using Spring ServletContextAttributeExporter:
<bean class="org.springframework.web.context.support.ServletContextAttributeExporter">
<property name="attributes">
<map>
<entry key="globalDataService" value-ref="GlobalDataService" />
</map>
</property>
</bean>
Then you can inject it without problems in JSF:
#ManagedProperty(value = "#{globalDataService}")
GlobalDataService globalDataService; //no need to be static
Let Spring container manage the lyfecycle of JSF managed beans. With this approach, you may inject the springs beans using #Autowired. This is covered in Spring 3 + JSF 2 tutorials. Still, note that if you do this, you will lose access to JSF 2 view scope (crucial when working with ajax requests in the same view) because Spring still cannot support it. But this can be solved by creating a custom implementation for view scope, like Cagatay's
IMO I would use the latter approach rather than the former.
More info:
Set attributes of ServletContext in Spring 3.2 MVC configuration
Mkyong tutorial to integrate Spring 3 and JSF 2.0
Bean properties are shared across different sessions
Integration jsf, spring, hibernate. How to inject Spring beans into JSF managed beans?
In Spring, beans can be configured to be lazily initialized. Spring Batch jobs are also (Spring-managed) beans. That is, when I configure something like
<sb:job id="dummyJob" job-repository="jobRepository">
<sb:step id="dummyStep">
<sb:tasklet ref="dummyTasklet" />
</sb:step>
</sb:job>
I actually configure a new (Job-typed) bean inside the Spring container.
My issue is I really want my Job beans to be lazily initialized. As they are regular Spring-managed beans, I'd expect I can instruct the Spring context to make them lazy. This is because I have a large number of beans and there are many cases in which, during one execution of my Spring-based application, I only run one job.
But there's no lazy-init property I can set on my <sb:job... \> configuration. Is there any way I can force lazy initialization? If I configure my <beans\> root with default-lazy-init="true", will this also apply to the Job beans?
You have two options here:
Configure your job manually. This would allow you to use the regular lazy-init attributes Spring exposes.
Use the JobScope now available in Spring Batch 3. Spring Batch 3 will be available soon, but the JobScope was available in the last milestone.
Just to elaborate on Michael Minella's answer.
I had a similar requirement to lazy initialize the job repository.
I am working with Spring Batch 2.1.9.
The following is working for me.
<bean id="jobRepository"
class="org.springframework.batch.core.repository.support.JobRepositoryFactoryBean"
lazy-init="true">
<property name="dataSource" ref="jobDataSource"/>
<property name="transactionManager" ref="jobTransactionManager"/>
</bean>
Note one pitfall I had run into: do not set the databaseType i.e. avoid the following:
<property name="databaseType" value="SQLSERVER"/>
This is bad because it disable the auto-discovery of the database type and breaked my JUnits that works on H2.
I want to use JTA Transaction Manager for my application. I'm using Spring and Glassfish. I want to use JNDI lookup to get the JtaTransactionManager instance. My Spring bean configuration for JtaTransactionManager is set up as follows:
<tx:annotation-driven transaction-manager="jtaTransactionManager"/>
<bean id="jtaTransactionManager"
class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="transactionManagerName" value="java:comp/TransactionManager"/>
<property name="userTransactionName" value="java:comp/UserTransaction"/>
</bean>
But when I run the program, it reported errors:
Caused by: org.springframework.transaction.TransactionSystemException: JTA UserTransaction is not available at JNDI location [java:comp/UserTransaction]; nested exception is javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file: java.naming.factory.initial
which is associated with Non-initialized JNDI context. So I added a resource file jndi.properties which adds the missing initial context reported above:
java.naming.factory.initial=???
But the question is: What should I put in the above JNDI initial context field to be able get Glassfish transaction manager via JNDI lookup? I searched a number of sources but didn't find this piece of information. The official document only says:
To access a UserTransaction instance, you can either look it up using
the java:comp/UserTransaction JNDI name or inject it using the
#Resource annotation.
So how should I set up the JNDI initial factory for JTA Transaction Manager in jndi.properties file so that both TransactionManager and UserTransaction can be injected into my jtaTransactionManager bean by JNDI lookup? Thanks.
When I use DispatcherServlet, I get a java.lang.IllegalStateException: No WebApplicationContext found: no ContextLoaderListener registered?
error when I use a DelegatingFilterProxy filter. Therefore I've removed the DispatcherServlet and now I use a ContextLoaderListener instead, and my Spring application loads fine. However, I have a problem with one VERY important bean:
<context:component-scan base-package="com.mydomain"/>
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
<property name="interceptors">
<list>
<ref bean="openSessionInViewInterceptor" />
</list>
</property>
</bean>
This bean no longer works, none of my #Controller's are URL mapped anymore. If I switch back to using DispatcherServlet, no problem (except that my filter is useless again). How can I get this bean to load correctly from within a ContextLoaderListener?
Cheers
Nik
You need both the ContextLoaderListener and the DispatcherServlet - the error message didn't tell you to remove the servlet.
To clarify what Spring is doing here, the DispatcherServlet creates its own ApplicationContext (typically using xxx-servlet.xml), but any Spring Filters that you configure in web.xml don't have access to the servlet's ApplicationContext.
The ContextLoaderListener creates a second ApplicationContext (associated with the whole webapp), and links itself with the servlet's ApplicationContext, allowing filters and servlets to communicate via Spring.
The web.xml of the Spring MVC basic app doesn't have a ContextLoaderListener though? See https://src.springframework.org/svn/spring-samples/mvc-basic/trunk/src/main/webapp/WEB-INF/web.xml.
Reason I ask is because I'm getting the following error in my application:
ERROR [[Spring MVC Dispatcher Servlet]] Servlet.service() for servlet Spring MVC Dispatcher Servlet threw exception
java.lang.IllegalStateException: No WebApplicationContext found: no ContextLoaderListener registered?
and I don't have a ContextLoaderListener (which is likely to cause the issue).
Any thoughts as to why the MVC basic app will work?