Spring Component scanned bean not accessable - spring

I have a UserDetailsService class annotated with #Service. I also have DAO classes annonated which are autowiring and working fine within my controllers.
The problem is when I want to wire up the UserDetailsService bean within my security-context.xml. Spring is unable to find the bean. Is it because my component-scan is in my controllers.xml file and out of the scope of my security configuration?
xml config file layout as so :
web.xml :
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring/root-context.xml
/WEB-INF/spring/appServlet/security-context.xml
</param-value>
</context-param>
servlet-context.xml :
...
<beans:import resource="controllers.xml" />
...

Yes, you'll need to add the component scan to both contexts, it's not enough to do it in just one.

Related

Spring #Autowired(required = true) is null [duplicate]

This question already has answers here:
Spring JSF integration: how to inject a Spring component/service in JSF managed bean?
(4 answers)
Closed 6 years ago.
I have a webmodule with JSF 2 end Spring 4.3. In a backing bean I use #Autowired for DI of a service of a JAR. In EAR module there are WAR, JAR with #Service Spring and JAR with Spring configuration file.
Below a web.xml snippet:
<context-param>
<param-name>locatorFactorySelector</param-name>
<param-value>classpath:beanRefContext.xml</param-value>
</context-param>
<context-param>
<param-name>parentContextKey</param-name>
<param-value>sharedContext</param-value>
</context-param>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
applicationContext.xml:
<context:annotation-config />
<context:spring-configured />
<!-- package of #Service class in jar module in EAR-- >
<context:component-scan base-package="com.ipdb.service" />
beanRefContext.xml:
<bean id="sharedContext" class="org.springframework.context.support.ClassPathXmlApplicationContext"> <constructor-arg>
<list>
<value>spring-ctx.xml</value>
</list>
</constructor-arg> </bean>
When I Use #Autowired(required=null) in a Backing Bean the value is null (there is not any exception). My JSF bean
#Component
#ManagedBean
#ViewScoped
public class PortfolioController {
#Autowired(required = true)
private PortfolioService portfolioService;
...
Can you help me, please.
PortfolioController is considered a JSF context bean adding #Component to #ManagedBean is totally wrong you can't mark same class as bean in two different contexts (JSF and Spring ).
Two solutions either make PortfolioController a spring bean thus remove the #ManagedBean and #ViewScoped or inject PortfolioController via JSF injection annotation #ManagedProperty
#ManagedProperty("#{portfolioService}")
private PortfolioService portfolioService;
if the applicationContext.xml is in your jar dependency, then you need to add asterisk after classpath:
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:applicationContext.xml</param-value>
</context-param>
With the asterisk spring search files applicationContext.xml anywhere in the classpath not only the current project.

How to initialize SpringWebAplication without dispatcher servlet?

I'm using Spring, but not SpringMVC in a web applcaition and gotta initialize Spring Application via web.xml
I have the standard web-project structure:
WEB-INF/applicationContext.xml
WEB-INF/web.xml
web.xml is currently contains:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
But my question was caused that any listener should be bound to a servlet. In my case I don't use dispatcherServlet. How to load spring WebApplicationContext, all spring beans, etc in that case? What do I write in web.xml?
A ContextLoaderListener initializes a WebApplicationContext and stores it in the ServletContext attributes under the name referenced by WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE.
You can retrieve it that way.
servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
anywhere you have access to the ServletContext, after the ContextLoaderListener has finished executing.
As suggested by M.Deinum in the comments, this is such a popular use case that Spring has its own utility to do it:WebApplicationContextUtils.getRequiredWebApplicationContext(ServletContext).
You don't need to change anything in your web.xml.

What can cause Spring IoC instantiate more than one instance of a singleton bean per WebApp?

I have a Spring based WebApp. In my application context, I have this bean defined:
<bean id="someSingleton" class="com.fake.SomeSingleton" scope="singleton"/>
I have the one Spring dispatch servlet definition and one class that has the #Controller annotation to which I auto-wired this bean, expecting Spring to only ever instantiating this class once. However, according to the following debug code, Spring is instantiating this class more than once:
private static final Semaphore SANITY_CHECK = new Semaphore(1);
public FakeSingleton(){
if(!SANITY_CHECK.tryAcquire()){
log.error("why?");
System.exit(-1);
else{
log.error("OK");
}
}
What can be the cause?
Note: I use spring 3.1.2.RELEASE
EDIT:
Thanks to the hints I was given, I found the culprit.
Apart from the DispatcherServlet, I also had a ContextLoaderListener in my web.xml. After removing it, SomeSingleton only got instantiated once.
<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>FakeService</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
There are few possible reasons:
Your class is wrapped by some CGLIB proxy which causes the constructor to run twice (as opposed to #PostConstruct callback which always runs once per bean) - once for your class and once for inheriting proxy
more likely, your bean is being picked up by two contexts: main one and Spring MVC one. This is a poor practice and you should avoid it. Check out if your SomeSingleton class is not picked up by MVC dispatcher servlet context via some CLASSPATH scanning.
BTW in such a code it's safe to use simple AtomicInteger instead of Semaphore.
A singleton is once per context, not once-per-heat-death-of-the-universe.
Turn on logging and see why/if the entire app context is being created more than once.

Beans injected into Apache Wink with Spring aren't registered

Following on from How do I inject a Spring bean into Apache Wink?
I'm now using wink-spring-support and I thought I had things set up correctly.
web.xml includes:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:META-INF/wink/wink-core-context.xml
classpath:applicationContext.xml
</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>restServlet</servlet-name>
<servlet-class>org.apache.wink.server.internal.servlet.RestServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>restServlet</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
META-INF/wink/wink-core-context.xml contains:
<bean class="org.apache.wink.spring.Registrar">
<property name="instances">
<set>
<ref bean="myservice" />
</set>
</property>
</bean>
<bean id="myservice" class="mystuff.ServiceImpl"/>
There's a #Autowired annotation in mystuff.ServiceImpl that injects other Spring stuff, and mystuff.ServiceImpl implements a JAX-RS annotated interface and itself includes a JAX-RS #Path("/services") annotation.
I can see Spring loading up this stuff just fine, including the myservice bean. However when I request my resources, I get a 404 not found. As Wink starts, I can see a couple of log entries that might indicate the problem:
applicationConfigLocation property was not defined
Using application classes null named in init-param applicationConfigLocation
Have I missed something somewhere? Any advice?
The problem was my misunderstanding the docs.
There is a Spring configuration META-INF/server/wink-core-context.xml provided with wink-spring-support. This registers the BeanPostProcessors that actually do the setup and must be referenced from contextConfigLocation.
I thought that I put my configuration in there, which explains why the application didn't get registered with Wink on startup.

How to connect HttpServlet with Spring Application Context in web.xml?

I'm trying to connect my FooServlet which extends HttpServlet with the ApplicationContext which is in the same Project.
The Application Context is already used by a Wicket Servlet
It works with
servletContext = this.getServletContext();
wac = WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext);
(IMyBean)wac().getBean("myServiceBean")
Now I try to aviod to use explicitly Spring Classes in my Code (WebApplicationContextUtils) as it's not the IoC way.
The Wicket Servlet is connected with the Application context in the web.xml
<servlet>
<servlet-name>ExampleApplication</servlet-name>
<servlet-class>org.apache.wicket.protocol.http.WicketServlet</servlet-class>
<init-param>
<param-name>applicationFactoryClassName</param-name>
<param-value>org.apache.wicket.spring.SpringWebApplicationFactory</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
I found the class Spring HttpServletBean but I don't know if it serves for my Case
I found a way to inject Beans in my HttpServlet (Note: I don't need a Presentation View, otherwise there are more advanced Spring Classes)
Add a ContextLoaderListener to web.xml so that Spring's root WebApplicationContext is loaded
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
Configure Servlet using Springs HttpRequestHandlerServlet Class
<servlet>
<servlet-name>FooServlet</servlet-name>
<display-name>Foo Servlet</display-name>
<servlet-class>
org.springframework.web.context.support.HttpRequestHandlerServlet
</servlet-class>
</servlet>
Let your Servlet implement the org.springframework.web.HttpRequestHandler Interface
Define your Servlet as a Bean in ApplicationContext (beanID must be same as "servlet-name").
Now it's possible to inject all necassary Beans in the Spring DependencyInjection way without dependency lookup.
I think you should use Spring utilities like
RequestContextUtils.getWebApplicationContext(request, application);
to hookup the Spring Context within your Servlet.
Agreed this is no DI/IoC, but the servlet is no bean as well !

Resources