No bean named '...' is defined and Spring #Resource annotation - java

I use #Resource to annotate bean classes, #Autowired to autowire dependencies,
and in Spring configuration file these things:
context:component-scan base-package="package1,package2"
tx:annotation-driven
So, it works fine (tested). Spring scans package1, package2, classes with #Resource annotation
and then I can get them using getBean() IF TESTED FROM CONSOLE APPLICATION [say, with main() function].
But when I try to use next approach (to use Spring in container managed environment = with Tomcat):
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:beans.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
compile a jar with all the bean classes and put this jar into WEB-INF/lib
then what I see? I cannot getBean() any of those #Resource annotated beans!
Spring simply cannot find them.
Still I can getBean() beans that are explicitly present in beans.xml.
Where's the problem?

Is missing <context:annotation-config/>?
<context:annotation-config/>
<context:component-scan base-package="package1"/>
<context:component-scan base-package="package2"/>
<tx:annotation-driven transaction-manager="transactionManager" />
or
<context:annotation-config/>
<context:component-scan base-package="package1, package2"/>
<tx:annotation-driven transaction-manager="transactionManager" />

I'm not sure how it's working in standalone mode, but the "" element in your Spring context allows the use "#Resource" annotations. Look at the Spring doc for more information.

Related

JSF + Spring integration [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.

Spring Scheduling: #Scheduled annotation on a method inside a class annotated with #Controller runs twice

Consider the below code snippet:
#Controller
public class RestController {
#Scheduled(cron = "0 0 */* * * ?") // run every hour
public void runMeHourly() {
LOGGER.debug("RestController#runMeHourly triggered to run at: " + System.currentTimeMillis());
// Do your hourly work here
}
}
When I deploy this controller in a J2EE web server I see that the method RestController#runMeHourly() in triggered twice every hour.
I found a reference to something like this here on spring docs scheduling.
It says:
Make sure that you are not initializing multiple instances of the same #Scheduled annotation class at runtime, unless you do want to schedule callbacks to each such instance. Related to this, make sure that you do not use #Configurable on bean classes which are annotated with #Scheduled and registered as regular Spring beans with the container: You would get double initialization otherwise, once through the container and once through the #Configurable aspect, with the consequence of each #Scheduled method being invoked twice.
Is this related? Does this mean I need to Schedule the method runMeHourly() from outside the RestController?
[Edit 1: Looks like the #Configurable is something else and not contributing to the problem, and I have not used it anywhere. So there must be some other reason that is causing this behaviour]
[Edit 2:
My web.xml:
<web-app>
<servlet>
<servlet-name>mvc-dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>mvc-dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/mvc-dispatcher-servlet.xml</param-value>
</context-param>
<listener>
<listener-class>com.company.module.ModuleContextListener</listener-class>
</listener>
</web.xml>
mvc-dispatcher-servlet.xml
<beans>
<mvc:annotation-driven />
<task:annotation-driven />
<context:component-scan base-package="com.company" />
<import resource="module/module-servlet.xml"/>
</beans>
module/module-servlet.xml
<beans>
<context:component-scan base-package="com.company.module"/>
</beans>
]
The com.company.module.ModuleContextListener is forcing the DispatcherServlet to look for a root application context, and since the root application context is same as mvc-dispatcher-servlet.xml its being loaded twice. Once as root context and again under DispatcherServlet with the name mvc-dispatcher.
Renaming the root context xml mvc-dispatcher-servlet.xml to applicationContext.xml and adding an empty mvc-dispatcher-servlet.xml solves the problem.
Thanks to #6ton for pointing this out.

How don't duplicate the dataSource in Spring xml files?

I have two files which contain the dataSource definitions. There are /WEB-INF/applicationContext.xml and src/main/resources/hibernateContext.xml
it's my dataSource definition:
<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close"
p:driverClassName="com.mysql.jdbc.Driver"
p:url="jdbc:mysql://localhost/fullproject"
p:username="root"
p:password="admin" />
This definition is necessary in every file for using with different services; Can i don't duplicate this code and only definite it only in one place????
Yes, it's possible to factor out commons snippets into dedicated Spring XML file and then include them like this:
<!-- Import shared bean definitions -->
<import resource="classpath:shared.env.xml"/>
Those two "dataSource" beans can be shared. So you only need one definition.
In your web.xml, load the "master" configuration file:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath*:/applicationContext.xml
classpath*:/hibernateContext.xml
</param-value>
</context-param>

Intilaizing a bean with constructor args - WebApplicationContext vs ClassPathApplicationContext

A bean defiend on the applicationContext.xml is getting instantiated using both ClassPathXmlApllicationContext and WebApplicationContext. While using the former the bean is returned as expected but while using the latter, WebApplicationContext, I'm getting a null value.
FYI: Not using the Spring to its full extent. Just used to define a bean and to intialize it. Its a web service application based on jboss.
I defined the WebApplicationContext in my web.xml as below
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<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>
<servlet>
<display-name>Service</display-name>
<servlet-name>MService</servlet-name>
<servlet-class>
com.xyz.atop.ws.memb.MServiceImpl
</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>MService</servlet-name>
<url-pattern>/Service</url-pattern>
</servlet-mapping>
</web-app>
The entry from the applicationContext.xml
<beans ...>
<context:annotation-config />
<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>
<bean id="helper" name="helper" class="com.xyz.svc.wrapper.Helper">
<constructor-arg type="java.lang.String" value="ABC"/>
</bean>
</beans>
Used the ClassPathApplicationContext (returning a bean instance as expected) in my code as below
private static Helper helper;
public MServiceImpl() {
}
static {
ApplicationContext appContext = new ClassPathXmlApplicationContext("applicationContext.xml");
helper = (Helper) appContext.getBean("helper");
}
......
......
While using the WebApplicationContext, I tried #Autowired annotation and even tried setter injection. Both the ways I'm getting a null value returned.
The "Helper" class I'm trying to initialize is coming from a jar file which in turn makes calls to a cxf-spring application.
Please look at the above scenario and advise to get rid of the null pointer while using the WebApplicationCOntext.
Ok, spring beans are injected into other spring beans. MService needs to be a bean too. Autowire will then inject the helper into the MService bean. You can't use a static initializer to do this, because that is run at classload time, which is before the application context has loaded. Also, helper shouldn't be static -- that's bad practice -- it makes testing very difficult.
Scenario: Used WebApplicationContext to intialize the beans defined in the applicationCOntext.xml file and received a null while trying to use the instantaited bean object in the code after autowiring.
Issue in this scenario: I'm trying to autowire a spring bean in a class on which Spring has control over.
Solution:
Extending the Servlet class (Class which is not in Spring control) which is the endpoint of my JBOSS WS with Spring's SpringBeanAutowiringSupport class helped me resolve the issue.
Below is the code snippet
public class MServiceImpl extends SpringBeanAutowiringSupport implements MService{
#Autowired
private Helper helper;
public MServiceImpl() {
}
......
......
}
Figured out that using static block to initialize the spring bean is bad approach. Thanks to #Engineer Dollery

#Autowired doesn't work in Spring and Vaadin integration

I'm trying to integrate Spring with Vaadin, but I can't use the #Autowired annotation in my Vaadin classes.
Firstly, I created the followed maven structure
This is my web.xml
<web-app>
<display-name>Vaadin Web Application</display-name>
<context-param>
<description>Vaadin production mode</description>
<param-name>productionMode</param-name>
<param-value>false</param-value>
</context-param>
<context-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
</context-param>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/application-context.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>
<servlet>
<servlet-name>Vaadin Application Servlet</servlet-name>
<servlet-class>com.mycompany.config.AutowiringApplicationServlet</servlet-class>
<init-param>
<description>Vaadin UI to display</description>
<param-name>UI</param-name>
<param-value>com.mycompany.ui.MyUI</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>Vaadin Application Servlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
This is my application-context.xml
<bean id="datasource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.postgresql.Driver" />
<property name="url" value="jdbc:postgresql://localhost/vaadin" />
<property name="username" value="postgres" />
<property name="password" value="tobbis" />
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="datasource"/>
<property name="persistenceUnitName" value="myUnit"/>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<jpa:repositories base-package="com.mycompany.repository"></jpa:repositories>
<context:annotation-config/>
<context:component-scan base-package="com.mycompany" />
Now I created my UserService that is within com.mycompany.services package
#Service
public class UserService {
public void saveUser(User user){
System.out.println("Test to Save");
}
}
And finally, I have my Panel where I want to inject the service
public class UserPanel extends VerticalLayout {
#Autowired
UserService service;
public UserPanel() {
// TODO Auto-generated constructor stub
Injector.inject(this);
service.saveUser();
}
}
but the result is always the same
Error creating bean with name 'com.mycompany.ui.UserPanel': Injection of autowired dependencies failed;
nested exception is org.springframework.beans.factory.BeanCreationException:
Could not autowire field: com.mycompany.services.UserService com.mycompany.ui.UserPanel.service;
nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException:
No matching bean of type [com.aiem.services.UserService] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency.
Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
Try to declare your UserService at applicationContext.xml
<bean name="userService" class="com.mycompany.services.UserService"></bean>
As far as I know,
Injector.inject(this);
is not something from Spring, you may be mixing it with another framework.
Instead, I would make UserPanel a prototype-scoped Spring component (meaning it can be instantiated and autowired by Spring, but you remain responsible for it's lifecycle).
#Component
#Scope(SCOPE_PROTOTYPE)
public class UserPanel extends VerticalLayout {
Note that a new instance will be created anytime UserPanel is retrieved from the context (e.g. autowired in another object). It could be best to control the creation of instances yourself by explicitly invoking
context.getBean(UserPanel.class)
at the right time.
AnnotationConfigWebApplicationContext is not meant to be used with XML config. It is supposed to be used with the #Configuration annotated classes.
Since you're using an xml file for Spring config, then you should instead remove these lines from web.xml:
<context-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
</context-param>
And then by default Spring will use the XmlWebApplicationContext and pick up your xml file.
I have tried the same scenario than you. At the end, the solution is at the Vaadin documentation.
Seems that the problem is that we are using Vaadin context and not Spring context, and therefore we need to do the trick showed in the documentation (SpringHelper) to obtain any bean. Outside of the Spring context, the autowiring is not goint to work.
There is an addon for enabling autowiring via annotations: http://vaadin.xpoft.ru/.
Here is the link to the Vaadin site: http://vaadin.com/addon/springvaadinintegration. Hope it helps.

Categories