Load annotated spring bean from Jar - spring

If the spring bean used annotation in jar file, how can I load mythe bean instance in my class?
In jar file
package org.java.service.test;
#Service(value = "MyService")
public class MyService {
#Resource(name = "myproperties")
private Properties properties;
}
In my project
package org.java.project.test;
#Service(value = "OtherService")
public class OtherService {
#Resource(name = "MyService")
private MyService myService;
}
In spring-beans.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" ....>
<context:annotation-config/>
<context:component-scan base-package=org.java.service.test, org.java.project.test"/>
.....
</beans>
I also try as below, it does not work
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" ....>
<context:annotation-config/>
<context:component-scan base-package="org.java.service.test"/>
<context:component-scan base-package="org.java.project.test"/>
.....
</beans>

I think the problem is not in your component-scan configuration.
Rather than using #Resource annotation on your field private MyService myService; you shoudl use #Autowired annotation.
So now your code in class OtherService will be like below:
package org.java.project.test;
#Service(value = "OtherService")
public class OtherService {
#Autowired
private MyService myService;
}
According to me that should work for you. Just try it. Cheers.

<context:component-scan>
scans those packages which are in the current project.

Related

Spring Configuration with annotations #Autowired not working - step by step

I have performed this steps in order to use annotation based configuration:
a) 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.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd">
<context:annotation-config/>
<context:component-scan base-package="test.*"/>
</beans>
b) then I have this component:
package test;
#Component
public class InMemoryUserService implements UserService
c) then I try to use autowire:
#Autowired
private UserService userService;
and in runtime userService is null.
Basic stuff is set up properly (like dependencies etc.) because in first version of the test app I was using xml based configuration and it was working smoothly.
And this is a class that uses autowireing:
public class DemoApplication {
#Autowired
private UserService userService;
public DemoApplication() {
}
public static void main(String[] args) {
DemoApplication da = new DemoApplication();
da.userService.getUserByEmail("blabla#gmail.com");
}
}
Is there anything else I'm missing?
That is because -
DemoApplication is not a spring managed bean. Make it spring managed by adding #Component similar to UserService.
Use spring bean factory or application context, say ClasspathXMLApplicationContext, to get the DemoApplication instead of new operator.
How will spring know that it has to run this DemoApplication.
You have to run it with a SpringJunit4ClassRunner something like below:
Annotate your DemoApplication as shown below:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration
public class DemoApplication {
#Autowired
private UserService userService;
#Test
public void testBean() {
userService.getUserByEmail("");
}
}

Why it failed when combining #component and bean?

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" />

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

Converting spring xml to java configuration with implicit setter autowiring and ComponentScan

I have two classes: vehicle.Tire and vehicle.Car.
package vehicle;
#Named
public class Tire {
private String age;
}
package vehicle;
#Named
public class Car {
private Tire tire;
// Spring calls this setter because default-autowire="byName" of xml configuration
public void setTire(Tire newTire) {
this.tire = newTire;
}
public Tire getTire() {
return this.tire;
}
}
The following spring xml works fine.
<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-4.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd
default-autowire="byName">
<context:component-scan base-package="vehicle" />
</beans>
I tried to create a java configuration above:
#Configuration
#ComponentScan(basePackages={"vehicle"})
public VehicleConfig {
}
I'm not using #Inject nor #Autowired annotations in the classes, but spring autowires and it works with xml.
Using java configuration, the method setTire of Car is not called :(
What is missing? How can I change java configuration using component scan without modifying Car and Tire classes? Is there default-autowire="byName" xml tag attribute equivalent in java?
I used the class above to test java configuration
#Test
public class VehicleConfigTest {
public void testTire() {
AnnotationConfigApplicationContext applicationContext =
new AnnotationConfigApplicationContext();
applicationContext.register(VehicleConfig.class);
applicationContext.refresh();
Car car = applicationContext.getBean(Car.class);
Assert.assertNotNull(car.getTire());
}
}
Thanks in advance.
There is no equivalent in sprig java configuration to default-autowire="byName" global xml tag attribute.
More, the right way to have injection is using #Inject annotation by cdi or #Autowired annotation by spring. So, the class Car should be modified:
package vehicle;
#Named
public class Car {
#Inject
private Tire tire;
public Tire getTire() {
return this.tire;
}
}
Now, both xml or java configuration works.

Spring DI Unsatisfied dependency expressed

applicationContext.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="user" class="com.pomkine.pottyauth.domain.User"/>
<bean id="userdao" class="com.pomkine.pottyauth.persistance.GaeUserDao"/>
<bean id="userservice" class="com.pomkine.pottyauth.service.UserServiceImpl">
<constructor-arg ref="userdao"/>
</bean>
</beans>
Controller:
#Controller
public class RosterController {
private UserService userService;
#Inject
public RosterController(UserService userService){
this.userService=userService;
}
#RequestMapping(value = {"/userRoster"}, method = RequestMethod.GET)
public String showRosterPage(Map<String,Object> model){
model.put("users",userService.getAllUsers());
return "userRoster";
}
}
So I want UserService to be injected into my controller. But I'm getting the following exception:
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'rosterController' defined in file [S:\Coding\Idea_workspace\pottyAuth\target\pottyAuth-1.0\WEB-INF\classes\com\pomkine\pottyauth\mvc\RosterController.class]: Unsatisfied dependency expressed through constructor argument with index 0 of type [com.pomkine.pottyauth.service.UserService]: : No matching bean of type [com.pomkine.pottyauth.service.UserService] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency.
Here is my UserServiceImpl class:
public class UserServiceImpl implements UserService {
private UserDao dao;
public UserServiceImpl(UserDao dao){
this.dao=dao;
}
#Override
public User getUser(User user) {
return dao.getUser(user);
}
#Override
public void addUser(User user) {
dao.addUser(user);
}
#Override
public List getAllUsers() {
return dao.getAllUsers();
}
}
So I'm expecting Spring container to create UserServiceImlp bean and inject it into RosterController. But it seems that it cannot find UserServiceImpl bean.
What could be wrong?
UserServiceImpl is not implementing UserService
edit:
also I can't see
<context:component-scan base-package="">
Is this whole Spring configuration?
It means Spring couldnt find any bean of type UserService. Check your UserServiceImpl class.
Wondering why you are using both XML and annotation based approach to define beans? It will good if you stick to either of them.
EDIT:
Add #Component annotation to UserServiceImpl. So that Spring will come to know that it should create a object of UserServiceImpl
#Component
public class UserServiceImpl implements UserService
{
.....
}
and as #pawelccb have mentioned use
<context:component-scan base-package="your.base.package">
in Spring config file.
Check this link for details.

Resources