Why it failed when combining #component and bean? - spring

I am trying to use #component and regular beans. And below is my code:
MainApp.java
package com.company;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MainApp {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
TextEditor te = (TextEditor) context.getBean("textEditor");
te.spellCheck();
}
}
SpellChecker.java
package com.company;
public class SpellChecker {
public SpellChecker(){
System.out.println("Inside SpellChecker constructor." );
}
public void checkSpelling(){
System.out.println("Inside checkSpelling." );
}
}
TextEditor.java
package com.company;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
#Component
public class TextEditor {
#Autowired
private SpellChecker spellChecker;
#Autowired
#Qualifier("region")
private String region;
public TextEditor() {
System.out.println("I am in " + region );
}
public SpellChecker getSpellChecker( ){
return spellChecker;
}
public void spellCheck(){
spellChecker.checkSpelling();
}
}
Beans.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:annotation-config/>
<context:component-scan base-package="com.company" />
<bean id="spellChecker" class="SpellChecker" />
<bean id="region" class="java.lang.String">
<constructor-arg value="Vancouver" />
</bean>
</beans>
However, when I run this code, it gave error messages:
Cannot find class [SpellChecker] for bean with name 'spellChecker' defined in class path resource
When I remove the bean in the Beans.xml for SpellChecker and mark #component to it as well. Then it works (yet, the region String is still empty).
So my question is: why cannot we autowired a bean in a #Component class?

That isn't related to Spring Integration, please, choose tags properly for the questions.
You problem is that SpellChecker is in the com.company package, but <bean class=""> really requires the fully qualified class name to define the proper class to instantiate.
The base-package="com.company" is exactly for the #Component to scan, but that fully doesn't relate to regular <bean> definition.

By using fully qualified class name it should work...
<bean id="spellChecker" class="com.company.SpellChecker" />

Related

aop with spring 2.5 without Aspect J

I am working in a old project with spring 2.5.Application context starts with
.
I need to implment logging using aop I need to log each and every class's method.
tried this link :
http://forum.spring.io/forum/spring-projects/aop/4769-apply-jdkregexpmethodpointcut-to-multiple-beans-how.But didnt work.
and some more options.(but i felt this is taking me some where)
Also, I cant use xsd so i cant use aop namespace.i cant use aspect j as well
Please guide me on how can i achieve this what should be point cut as I have tried . and * as pattern and bean names with the point cut.
spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="debugInterceptor" class="test.DebugInterceptor" />
<bean id="testBean" class="test.TestBean" />
<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="beanNames" value="*" />
<property name="interceptorNames">
<list>
<value>debugInterceptor</value>
</list>
</property>
</bean>
</beans>
TestBean
package test;
public class TestBean {
public void foo() {
System.out.println("foo");
}
void bar() {
System.out.println("bar");
}
}
DebugInterceptor
package test;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
public class DebugInterceptor implements MethodInterceptor {
public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println("Before: invocation=[" + invocation + "]");
Object rval = invocation.proceed();
System.out.println("Invocation returned");
return rval;
}
}
AopTest
package test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class AopTest {
public static void main(String[] args) {
ApplicationContext ap = new ClassPathXmlApplicationContext("classpath:spring.xml");
TestBean bean = (TestBean)ap.getBean("testBean");
bean.foo();
bean.bar();
}
}

How to load Spring applicationContext into Jersey Application

I'm creating a Jersey JAX-RS web service with the following:
package com.mycompany.rest.config;
import java.util.Set;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
#ApplicationPath("")
public class ApplicationConfig extends Application {
#Override
public Set<Class<?>> getClasses() {
return getRestResourceClasses();
}
private Set<Class<?>> getRestResourceClasses() {
Set<Class<?>> resources = new java.util.HashSet<Class<?>>();
resources.add(com.mycompany.rest.controllers.UserController.class);
return resources;
}
}
However, when I try and integrate a spring applicationContext such as the following :
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.mycompany.rest.user"/>
<bean id="userService" class="com.mycompany.rest.user.UserServiceImpl" />
</beans>
I get null pointers from my controller class for the userService being loaded by the bean pasted above. I'm assuming this is because the application context is not being loaded into the Jersey application.
Is there a way of doing this?
If you want to inject Spring beans into your Jersey resource classes, you need to add jersey-spring3 dependency to your class path. see https://jersey.java.net/documentation/latest/spring.html
An hello-world example can be found at https://github.com/jersey/jersey/tree/2.19/examples/helloworld-spring-webapp
I had the same problem, and i fixed it by adding #autowired to my service, and extending SpringBeanAutowiringSupport like the following :
#Path("/mails")
public class MailController extends SpringBeanAutowiringSupport{
#Autowired
private MailService mailService;
#GET
#Path("/{code}")
#Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public String getMails(#PathParam("code") String code) throws Exception {
//function logic
}
Note that this is working without integrating jersey-springx.jar
And I'm using Spring 3 along with jersey-bundle-1.19.1.jar

No unique bean of type is defined: expected single bean but found 0:

I have one spring based standalone project (PTSJMSProxy). I refer http://sahits.ch/blog/?p=2326
In the PTSJMSProxy I have followings.
1) SimpleWriterService.java
package com.test;
import org.springframework.stereotype.Service;
#Service
public class SimpleWriterService {
public void sayHello() {
System.out.println("Hello Spring DI service!");
}
}
2) ComponentConsumer.java
package com.test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
#Component
public class ComponentConsumer {
#Autowired
private SimpleWriterService service;
public void consume() {
service.sayHello();
}
}
3) ProxyJMSClient.java
package com.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class ProxyJMSClient {
// I commented some portions,but working fine
// Example #Autowired and also in the constructure
// #Autowired
private ComponentConsumer consumer;
public ProxyJMSClient() {
ApplicationContext context = new ClassPathXmlApplicationContext(
"applicationContext.xml");
// AutowireCapableBeanFactory acbFactory =
// context.getAutowireCapableBeanFactory();
// acbFactory.autowireBean(this);
consumer = context.getBean(ComponentConsumer.class);
}
public void callMyJMSClient() {
this.consumer.consume();
}
}
4) Test.java
package com.test;
public class Test {
public static void main(String[] args) {
(new ProxyJMSClient()).callMyJMSClient();
}
}
5) applicationContext.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<tx:annotation-driven />
<context:annotation-config />
<context:component-scan base-package="com.test" />
</beans>
Now when I invoke Test.java from eclipse Run As -Java Application I get the expected out put.
Output - Hello Spring DI service!
=============================================================================
Now I created the Jar with Eclipse export as Jar. Jar Name -PTSJMSProxy.jar
===============================================================================
My objective is to use this jar from a non spring java project
===============================================================================
I created another java project in eclipse "TestProxy"
In that project I add all the required Spring Jar and PTSJMSProxy.jar
Created TestJMSProxy.java class
package com.proxy.test;
import com.wiley.fts.ProxyJMSClient;
public class TestJMSProxy {
public static void main(String[] args) {
(new ProxyJMSClient()).callMyJMSClient();
}
}
When I run - I get following exceptions
log4j:WARN No appenders could be found for logger (org.springframework.context.support.ClassPathXmlApplicationContext).
log4j:WARN Please initialize the log4j system properly.
Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [com.test.ComponentConsumer] is defined: expected single bean but found 0:
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:269)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1083)
at com.wiley.fts.ProxyJMSClient.<init>(ProxyJMSClient.java:19)
at com.proxy.test.TestJMSProxyJar.main(TestJMSProxyJar.java:8)
How can I resolve this
NOTE: -
PTSJMSProxy is a spring based project - which has its own applicationContext.xml (Refer point no -5)
TestProxy is a NON Spring Java project - where I use PTSJMSProxy Jar
PTSJMSProxy Jar folder structure
PTSJMSProxy jar contains com,META-INF and applicationContext.xml under same level
The problem is resolved.
This is due to the loading problem of spring configuration xml file.
Code
String fileUrl = PTSJMSProxyClient.class.getClassLoader()
.getResource(SPRING_JMS_CFG_FILE).toString();
LOG.info("Spring jmsContext.xml file path :" +fileUrl);
xmlApplicationContext = new ClassPathXmlApplicationContext(fileUrl);
AutowireCapableBeanFactory acbFactory = xmlApplicationContext
.getAutowireCapableBeanFactory();
acbFactory.autowireBean(this);
client = xmlApplicationContext.getBean(MessageSenderImpl.class);
Sometime it also happens when you define basePackages wrongly inside #ComponentScan annotation like:
#ComponentScan("com.whodesire.model", "com.whodesire.util")
here the above one will considered as single package, if there are multiple packages to scan within your project, then you must mention packages like String[]
#ComponentScan( { "com.whodesire.model" , "com.whodesire.util" } )

unable to use Spring Advice(#Before) using annotations

I am new to springs and trying to run a simple java application with java advices....
xml file...
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<aop:aspectj-autoproxy>
<aop:include name="com.cts.two.Advices"/>
</aop:aspectj-autoproxy>
<context:annotation-config/>
<context:component-scan base-package="com.cts.two"></context:component-scan>
</beans>
Advice Class
package com.cts.two;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
#Aspect
public class Advices implements Adv{
#Pointcut("execution(* com.cts.two.*.*(..))")
public void advice(){
}
#Before("advice()")
public void before(JoinPoint name) throws Throwable{
System.out.println("inside advices");
/*System.out.println(name.getClass() + " this is get class");
System.out.println(name.getSignature().getName() + " this is the get signatue and get name");*/
}
}
class on which advice needs to be applied...I want the before method of Advice class to be executed before below mentioned test() method
package com.cts.two;
import org.springframework.stereotype.Component;
#Component
public class ClassA {
private ClassB b= new ClassB();
public void setB(ClassB b) {
this.b = b;
}
public void test(){
System.out.println("inside classA test");
//b.test();
}
}
caller of methods/test class/main class
package com.cts.two;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class CallerAB {
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
ApplicationContext context = new ClassPathXmlApplicationContext(
"AllAnnotations.xml");
ClassA calledA = (ClassA) context.getBean("classA");
calledA.test();
}
}
the problem is that when I run the code directly the test method of class A is executed but the advice is not...
Kindly advice..
Am i missing something ???
AspectJ 1.6.12 jar is also added...
Aspects should be decalred as beans.
#Aspect doesn't do it automatically, <aop:include> doesn't do it as well (it sets additional restriction on beans that can be used as aspects).
So, you need
#Aspect
#Component
public class Advices implements Adv { ... }
and don't need <aop:include>.
As mentioned in the answer from #axtavt you need to add the #Component annotation. But you also need to remove the <aop:include>. Your spring wiring xml should just be:
<aop:aspectj-autoproxy/>
<context:annotation-config/>
<context:component-scan base-package="com.cts.two"/>
As stated in the spring AOP documentation, the name attribute in the <aop:include> element is supposed to be a bean name, not a class name. Specifying a bean explicitly overrides Spring's auto-detection and specifying it incorrectly means that there is no aspect used at all.

Spring #Autowired not working

I have some problems wth autowire annotation. My app looks like this:
Here is controller:
#Controller
public class MyController {
#Autowired
#Qualifier("someService")
private SomeService someService;
....
}
It's a service layer:
public interface SomeService {
...
}
#Service
public class SomeServiceImpl implements SomeService{
#Autowired
#Qualifier("myDAO")
private MyDAO myDAO;
....
}
And DAO layer:
public interface MyDAO{
....
}
#Repository
public class JDBCDAOImpl implements MyDAO {
#Autowired
#Qualifier("dataSource")
private DataSource dataSource;
....
}
This is a app-service.xml file:
....
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
p:location="/WEB-INF/jdbc.properties" />
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource"
p:driverClassName="${jdbc.driverClassName}"
p:url="${jdbc.url}"
p:username="${jdbc.username}"
p:password="${jdbc.password}"/>
<bean id="SomeService" class="com.service.SomeServiceImpl" />
<bean id="myDAO" class="com.db.JDBCDAOImpl" />
So... When I'm launching a web-app, MyController Autowires correctly (the someService field correctly injected by SomeServiceImpl class object), but myDAO feild of someService has null value (not injected properly).
Could you help me to find a problem?
P.S. Its interesting, but when I'm changing a "bean id" from myDAO to some another (e.g. myDAO2), system gives me an error, that injecting could not be done, because bean myDAO doesn't exist. So, Spring make an injection, but where it is? And why it's not work correctly?
I found the solution. As Javi said (thanks a lot for you, Javi), I have to annotate DAO and Service layer classes with #Repository and #Service annotation. Now I've tried to write like this:
#Service("someService")
public class SomeServiceImpl implements SomeService{
#Autowired
#Qualifier("myDAO")
private MyDAO myDAO;
....
}
and
#Repository("myDAO")
public class JDBCDAOImpl implements MyDAO {
#Autowired
#Qualifier("dataSource")
private DataSource dataSource;
....
}
and all works fine!!!
But I still not found an answer for this quesion: if application will be more complex, and will have more complex structure, where #Repositore and #Service annotation are not preferred for some classes, how to inject correctly beans, which located in lower levels (in a fields of classes, or in a field of fields of classes) (with #Autowire annotation, of course)?
I guess you need <context:annotation-config />.
You can use
<context:component-scan base-package="PATH OF THE BASE PACKAGE"/>
entry in your configuration .xml file. This entry will scan/read all the stated type and annotations from the java classes.
Important points:
Sometimes, #Component may leads to a problem where it might say no default constructor found.
The class which is defined as a #Component annotation, it must have a default constructor.
Suppose, we have applied #Autowired annotation at field which is a user defined class reference.
Now, if we also apply #Component to that class then it will always be initialized with null.
So, a field with #Autowired should not have #Component at its class definition.
By default #Autowired is byType.
Address bean is autowired at Student class.
Let’s see what happens if we apply #Component at Address.java.
CollegeApp.java:
package com.myTest
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import com.bean.Address;
import com.bean.Student;
//Component scanning will for only those classes
//which is defined as #Component. But, all the class should not use
//#Component always even if the class is enabled with auto
//component scanning, specially the class which is Autowired
//Or which is a property of another class
#Configuration
#ComponentScan(basePackages={"com.bean"})
public class CollegeApp {
#Bean
public Address getAddress(){
return new Address("Elgin street");
}
public static void main(String[] args) {
AnnotationConfigApplicationContext context=new AnnotationConfigApplicationContext(CollegeApp.class);
Student student=context.getBean(Student.class);
System.out.println(student.toString());
context.close();
}
}
We want Elgin street to be autowired with Student address.
Address.java:
package com.bean;
import org.springframework.stereotype.Component;
#Component
public class Address {
private String street;
public Address()
{
}
public Address(String theStreet)
{
street=theStreet;
}
public String toString()
{
return (" Address:"+street);
}
}
Student.java:
package com.bean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
#Component
public class Student {
private String name;
private int age;
private Address address;
public Student()
{
}
public Student(String theName,int theAge)
{
name=theName;age=theAge;
}
#Autowired
public void setAddress(Address address) {
this.address = address;
}
public String toString()
{
return ("Name:"+name+" Age:"+age+ " "+address);
}
}
Output: - Name:null Age:0 Address:null //Address not Autowired here.
To resolve the issue, only change the Address.java as below:
Address.java:
package com.bean;
public class Address {
private String street;
public Address(String theStreet)
{
street=theStreet;
}
public String toString()
{
return (" Address:"+street);
}
}
Output:-
Name:null Age:0 Address:Elgin street
You should include this section of XML code in spring-config.xml :
<context:component-scan base-package="Fully.Qualified.Package.Name" />
but you should know the difference between <context:annotation-config> vs <context:component-scan> as most people are suggesting these two :
1) First big difference between both tags is that <context:annotation-config> is used to activate applied annotations in already registered beans in application context. Note that it simply does not matter whether bean was registered by which mechanism e.g. using <context:component-scan> or it was defined in application-context.xml file itself.
2) Second difference is driven from first difference itself. It does register the beans in context + it also scans the annotations inside beans and activate them. So <context:component-scan>; does what <context:annotation-config> does, but additionally it scan the packages and register the beans in application context.
There can be two reasons for this.
When you have not annotated the injected object or say service with proper #Service/#Component/#Repository annotations.
Once you have made sure of point 1 ,next check for whether the class package of your annotated service class is included in the class-path for your spring boot application in the main class.You can configure this using the following annotation.
#SpringBootApplication(scanBasePackages = {
"com.ie.efgh.somepackage","com.ie.abcd.someotherpackage" })
Doing this you tell spring to look into the packages for the classes during class loading.
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!-- Specifying base package of the Components like Controller, Service,
DAO -->
<context:component-scan base-package="com.jwt" />
<!-- Getting Database properties -->
<context:property-placeholder location="classpath:application.properties" />
<!-- DataSource -->
<bean class="org.springframework.jdbc.datasource.DriverManagerDataSource"
id="dataSource">
<property name="driverClassName" value="${database.driver}"></property>
<property name="url" value="${database.url}"></property>
<property name="username" value="${database.user}"></property>
<property name="password" value="${database.password}"></property>
</bean>
<!-- Hibernate SessionFactory -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
<prop key="hibernate.format_sql">${hibernate.format_sql}</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
</props>
</property>
</bean>
</beans>

Resources