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("");
}
}
Related
In a Spring 3.1.3.RELEASE project I want to create and autowire a list that contains some enum to some service.
Unfortunately the autowiring fails (NoSuchBeanDefinitionException), while I can retrieve the bean in the context and manually wire the dependency.
Here is a small testcase showcasing the issue (using Spring 3.1.3 and JUnit):
The XML context (int package /junk):
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
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/util http://www.springframework.org/schema/util/spring-util.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="junk"/>
<util:list id="myList" value-type="junk.GreatThings">
<value>SUPER</value>
<value>COOL</value>
</util:list>
</beans>
The enum:
package junk;
public enum GreatThings {AMAZING, GREAT, SUPER, COOL}
The test class (in package junk - I've removed the import for clarity):
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = {"classpath*:junkcontext.xml"})
public class TestAutowiringSupport {
#Autowired #Qualifier("myList") List<GreatThings> greatThings;
#Test public void testSuperCool() {
Assert.assertThat(greatThings, hasItem(SUPER));
Assert.assertThat(greatThings, hasItem(COOL));
}
}
This result in a NoSuchBeanDefinitionException.
I have try to put a #Qualifier with my bean id to help Spring to perform the wiring without any success.
My IDE is however able to detect the wiring by itself:
And if I use the Spring lifecycle callbacks to get back the bean and wire it manually then, it is fine.
Version that compiles and runs fine:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = {"classpath*:junkcontext.xml"})
public class TestAutowiringSupport implements ApplicationContextAware
{
ApplicationContext ctx;
List<GreatThings> greatThings;
#Override
public void setApplicationContext(ApplicationContext ctx) throws BeansException {this.ctx = ctx;}
#PostConstruct
public void manualWiring() {greatThings = (List<GreatThings>) ctx.getBean("myList");}
#Test public void testSuperCool() {
Assert.assertThat(greatThings, hasItem(SUPER));
Assert.assertThat(greatThings, hasItem(COOL));
}
}
What's wrong with the autowiring in this case ?
Looks like some problem with generics.
With Spring 4.1 I am able to execute this code: where greatThings is of type List<Object>
#Qualifier("myList")
#Autowired List<Object> greatThings;
#Test
public void testSuperCool() {
Assert.assertThat(greatThings, Matchers.hasSize(2));
Assert.assertThat(greatThings, Matchers.hasItem(GreatThings.SUPER));
Assert.assertThat(greatThings, Matchers.hasItem(GreatThings.COOL));
}
As stated in the reference documentation, placing the #Autowired annotation over a typed collection means "find all beans of the given type (GreatThings in your case), put them in a collection and inject that collection". You are getting the exception because there are no beans of type GreatThings declared.
The problem is that there is no easy way to declare enum values as beans. Then again I don't see the use case to be honest.
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
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.
I am having some issues with Autowiring
First off i create an Embedded server
Main.java
Server server = new Server(8080);
CXFNonSpringServlet cxf = new CXFNonSpringJaxrsServlet();
ServletHolder servlet = new ServletHolder(cxf);
servlet.setInitParameter("javax.ws.rs.Application", "com.asd.dispatcher.rest.testApplication");
servlet.setName("services");
servlet.setForcedPath("services");
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
context.setContextPath("/hello");
server.setHandler(context);
context.addServlet(servlet, "/*");
server.start();
testApplication.java
public class testApplication extends Application {
#Override
public Set<Class<?>> getClasses() {
Set<Class<?>> classes = new HashSet<Class<?>>();
classes.add(testServlet.class);
return classes;
}
}
testServlet.java
#Path("/people")
#Component
#Scope("prototype")
public class testServlet {
#Autowired
private StatsService statsService;
#Produces({ "application/json" })
#GET
public String getPeople(#QueryParam("page") #DefaultValue("1") final int page) {
System.out.println("======= getPeople");
//statsService.printStats();
return "Hello World";
}
}
Now my issue is that my statsService is not being autowired in testServlet.java, yet i can autowire it into another class annotated with #Service,
is this because of me using a CXFNonSpringServlet??
or is it because of the way i am trying to Autowire?
Ok i got it working
Ok so i fixed it (i would post this as the answer but cant answer my own question :/ )
putting the answer here to help anyone else with the same problem
After having a look at the following
Autowiring in servlet
I came to the conclusion that a Post Construct method that gets the applicationContext and then the bean would work
Eg: my code would be this
#Path("/people")
#Component
#Scope("prototype")
public class testServlet {
private StatsService statsService;
#PostConstruct
public void initStats() {
System.out.println("============================= Init");
ApplicationContext context = new GenericXmlApplicationContext("applicationContext.xml");
statsService = context.getBean("statsService", StatsService.class);
}
#Produces({ "application/json" })
#GET
public String getPeople(#QueryParam("page") #DefaultValue("1") final int page) {
System.out.println("======= getPeople");
statsService.printStats();
return "Hello World";
}
}
Although this is not autowiring it does work, if there is anyone who knows how to do this with autowiring i would love to know as it would be far cleaner then the solution i found.
*on a side note i picked up a new issue with this 'solution' to my problem in that the statsService that i have also has other beans autowired in, and it seems although the auto wiring initializes these beans any changes to their state in another class are not reflected in the statsService infact the state of these beans remain unchanged (although that might be the suspected behavior i am still new to spring so i am not sure)
I don't know what CXFNonSpringServelt is, but my question is: Have you added the lines above in the context-config.xml file of your application?
<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.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd">
...
...
<context:component-scan base-package="package of the classes with annotations" />
And in your server class you should add the annotation #Service
#Service("myService")
public class MyService ...
And you can use the #Authowire like this:
public class Client{
#Autowire
MyService myservice;
...
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.