I have problem figuring out why My Jersey RESTful entry point can't find the Spring Bean that I configure when the app server starts. It kept getting NullPointerException after trying from
Spring DI - Autowired property is null in a REST service
NullPointerException on #Autowired attribute with Jersey and Spring for REST service
#Autowired is not working with jersey and spring
Integrating both spring mvc and Jersey, getting a null pointer when viewing a jersey endpoint
Jersey 2 + Spring: #Autowired is null
Web.xml
<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>
<servlet>
<servlet-name>jersey-serlvet</servlet-name>
<servlet-class>com.sun.jersey.spi.spring.container.servlet.SpringServlet</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>com.testing.resource</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>jersey-serlvet</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
Spring-context.xml
<context:annotation-config />
<context:component-scan base-package="com.testing.config, com.testing.repository, com.testing.workflow" />
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>classpath:jdbc.properties</value>
</property>
</bean>
Jersey servlet entry point
#Component
#Produces(MediaType.APPLICATION_JSON)
#Path("/{userId}/items")
public class UserResource
{
#Autowired
private UserWorkFlow userWorkFlow;
#GET
public Response getAllItems(#PathParam("userId") String userId)
{
// ** NullPointerException here complains about the UserWorkFlow
return Response.status(200).entity(userWorkFlow.getItemsFor(userId)).build();
}
}
Service layer
I also tried to make an interface for this but it didn't work.
#Service
public class UserWorkFlow
{
#Autowired
private AllItems allItems;
public List<Item> getItemsFor(String id)
{
return allItems.getItemsFor(id);
}
}
Repository and DAO
#Repository
public class AllItems
{
#Autowired
private ItemSql itemSql;
public List<Item> getItemsFor(String id)
{
return itemSql.getAllItemsFor(id);
}
}
MyBatis Mapper (this has a XML associated with it)
public interface UserSql
{
List<Item> getAllItemsFor(#Param("userId") String userId);
}
I also changed to com.sun.jersey from org.glassfish.jersey but didn't work. I am running out of ideas what could be wrong. Can anyone spot what did I do wrong ?
The link I provided for your previous question had links to four fully working examples. You could have easily just grabbed one of the examples and built on top of it.
I will just walk you through one of the examples. Maybe it was too hard to follow. I will use the Jersey 2.x with Spring XML config.
First, make sure you have the dependencies (only showing versions to ones not shown in the pom)
jersey-container-servlet: 2.22.1
spring-web: 3.2.3.RELEASE
commons-logging
jersey-spring3: 2.22.1. (Notice the snapshot project uses jersey-spring*4*. This is not yet released, and will be released in the next Jersey release)
Second, make sure your web.xml is in order
Third, add your applicationContext.xml to the project class-path.
Fouth, the MyApplication class listed in the previous web.xml.
If you follow the example to the T, you will have a working example. It may not be the exact way you want to configure your Spring components, but you will have a working example you can build off of and tweak around to see what works and what doesn't. When you get more comfortable, you can see the other examples (in the first link of this answer) for other configuration styles/options.
I have extended ServiceImpl and DAOImpl classes with SpringBeanAutowiringSupport, It solved my autowired null pointer exception.
Related
I'm trying to use Jersey 2 with Spring with help of this article:
How to use Jersey 2 with Spring IoC container
But autowired bean is null when the application tries to call it after the client request.
In applicationContext.xml i have only component-scan setting.
In pom.xml:
<spring.version>4.1.0.RELEASE</spring.version>
<jersey.version>2.12</jersey.version>
#Component
#RequestScoped
#Path("/user")
public class UserREST {
#Autowired
private UserFacade userFacade;
#POST
#Path("/auth")
#Consumes(MediaType.APPLICATION_JSON)
#Produces({MediaType.APPLICATION_JSON})
public AuthResponse authorize(User user){
return userFacade.authorize(user); // Null is caught here
}
}
-
#Component
public class UserFacade {
public AuthResponse authorize(com.pushock.model.User user){
AuthResponse response = new AuthResponse();
response.setAuthorized(true);
return response;
}
}
What am I doing wrong?
UPD:
Here is my pom.xml https://bitbucket.org/spukhov/memo-ws/src/00724e00e3aa786f62fd0e43fe0606de6ae569df/pom.xml?at=master
Spring managed beans cannot be injected to JAX-RS classes directly, you need to use Jersey extension for integrating it with Spring.
There is a maven dependency which you don't have in your pom.xml
<dependency>
<groupId>org.glassfish.jersey.ext</groupId>
<artifactId>jersey-spring3</artifactId>
<version>2.12</version>
</dependency>
Refer to Jersey Documentation: Chapter 22. Spring DI and at the bottom of the page, there is a link to sample spring integration Github project.
Another problem I've seen in your project is you didn't show how spring context should be loaded and configured. You need to configure it in your web.xml
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
and in case you are using java based approach for spring configuration, you also need to :
servletContext.setInitParameter("contextConfigLocation", "<NONE>");
in your WebApplicationInitializer implementation
I am studying for the Spring Core certification and I have some doubts related this question:
What is the #Controller annotation used for? How can you create a
controller without an annotation?
So I know that the #Controller annotation indicates that a particular class serves the role of a controller. The #Controller annotation acts as a stereotype for the annotated class, indicating its role. The dispatcher scans such annotated classes for mapped methods and detects #RequestMapping annotations.
So a controller class is something like this:
#Controller
public class AccountController {
#RequestMapping("/listAccounts")
public String list(Model model) {...}
}
}
Ok, this is pretty clear for me but what exactly means create a controller without an annotation? How can I do it? By XML configuration or how?
Tnx
public class AccountController extends MultiActionController {
public ModelAndView listAccounts() {
// your code
return new ModelAndView("listAccounts.bean", "msg", "As you want")
}
}
web.xml
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>*.bean</url-pattern>
</servlet-mapping>
dispatcher-servlet.xml
<bean name="/listAccounts.bean" class="p1.AccountController"></bean>
I've come across this: Spring MVC 3.1 without annotations?
It would seem that you can actually create a controller without annotations (I've been working with Spring for little over a year and haven't encountered such a scenario, I don't know why one would want to do this, apart from certification questions of course) and the way to do it is by using a special configuration in the dispatcher-servlet XML file.
Just to comment the reasons why someone would like to configure Spring programatically or throuth XML, it is because it takes some to scan all the files looking for the annotations during runtime, so if we disable the scan and configure it manually the application will be available to service requests much faster and that is very important on high demand sceneraios.
Is there any way to remove .action/.html/(.any) extension in Spring MVC like Struts2.
I'm looking for a clean URL in my address bar.
Like: http://localhost:8080/SpringProject/Dashboard
Rather than: http://localhost:8080/SpringProject/Dashboard.html
Solution That I have found :
Added two line in my spring-servlet.xml file
<mvc:default-servlet-handler/>
<mvc:annotation-driven />
and modify my web.xml
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
that's all
I also post this answer in my blog javalink2me.blogspot
The support for #Controller and #RequestMapping is provided by Spring by default. However, by enabling mvc:annotation-driven you get support for processing the requests that are mapped to annotated controller methods, such as declarative validation, formatting and conversion service.
In servlet-config.xml
<mvc:default-servlet-handler/>
<mvc:annotation-driven />
In WEB.xml
<servlet-mapping>
<servlet-name>home</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
You just need to configure your controller with the path you want.
#Controller
public class MyController {
#Inject
private MyService myService;
#RequestMapping("/mypath")
public String showPathWithouteExtension(Model model) {
return "myjspfile";
}
}
With a controller like this, you just need to call.
http://server:port/myapp/mypath
and boom, no extension. :)
TLDR at the bottom:
As per the JBossWS-cxf user guide, for a web service, the web.xml should contain the following
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
version="2.4">
<servlet>
<servlet-name>MyWebService</servlet-name>
<servlet-class>com.sgb.MyWebService</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>MyWebService</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
Jboss also expects a descriptor file named jboss-cxf.xml in WEB-INF directory (instead of cxf.xml) which should contain the jaxws:endpoint tag like so:
<beans xmlns='http://www.springframework.org/schema/beans'
xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
xmlns:beans='http://www.springframework.org/schema/beans'
xmlns:jaxws='http://cxf.apache.org/jaxws'
xsi:schemaLocation='http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://cxf.apache.org/jaxws >
<bean id="MyWebService" class="com.sgb.MyWebService" />
<jaxws:endpoint id="POJOEndpoint" implementor="#MyWebService" wsdlLocation="WEB-INF/wsdl/XYZ.wsdl" address="/warfilename">
<jaxws:invoker>
<bean class="org.jboss.wsf.stack.cxf.InvokerJSE" />
</jaxws:invoker>
</jaxws:endpoint>
</beans>
I then create my service implementation class thusly:
package com.sgb;
#javax.jws.WebService(... ... ... )
public class MyWebService implements IMyWebService
{
public CreateResponse create(CreateRequest request)
{
... ... ... <-- an instance of createService is created
return createService.serve(request)
}
}
So far so good. It works fine.
However, as per Spring's reference documentation, the convenient way to instantiate an application context for web applications is by adding a ContextLoaderListener in the web.xml like so.
<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>
So, I could add the above in my web.xml and then annotate MyWebService class with #Service and make sure the package is set up for component-scaning.
And it should become a spring managed bean too.
Problem is, it doesn't.
JbossWS-CXF seems to be instantiating MyWebService due to which the dependencies are not injecte resulting in a nullpointer.
I am able to get the applicationContext programmatically using ClassPathXmlApplicationContext("/WEB-INF/applicationContext.xml")
And then inject/create my dependencies using appContext.getBean()
But I was hoping to inject/autowire the dependencies directly using annotations instead.
TLDR:
What I currently have is this. (This bean is created by jboss and not spring):
#javax.jws.WebService(... ... ... )
public class MyWebService implements IMyWebService
{
private ApplicationContext appContext;
public MyWebService(){
appContext = new ClassPathXmlApplicationContext("/META-INF/spring/applicationContext-ws.xml");
}
public CreateResponse create(CreateRequest request)
{
*** Use getBean() here to get my dependency. ***
IXyzService createService = appContext.getBean("createService",IXyzService.class);
return createService.serve(request)
}
}
What I want is this:
#javax.jws.WebService(... ... ... )
#Service <-- <-- <-- ** This is Spring managed bean**
public class MyWebService implements IMyWebService
{
#Resource <-- <-- <-- **Dependency Injected by Spring**
IXyzService createService;
public CreateResponse create(CreateRequest request)
{
return createService.serve(request)
}
}
What is the best way to accomplish this ???
I found out a few days back that this is indeed possible, so editing my previous answer.
The magic glue is this:
#PostConstruct
public void postConstruct(){
SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
}
So to summarize, the following pieces are needed:
1) Load the spring context via web.xml
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:/META-INF/spring/appContext.xml</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
2) Annotate a method with #PostConstruct in the class that implements the interface generated by CXF like so:
#javax.jws.WebService(... ... ... )
public class MyWebService implements IMyWebService
{
#Resource <-- <-- <-- **Dependency Injected by Spring**
IXyzService createService;
#PostConstruct
public void postConstruct(){
SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
}
public CreateResponse create(CreateRequest request)
{
return createService.serve(request)
}
}
The above info is courtesy of this link:How to initialize Spring Framework inside CXF JAX-WS service
Hope this helps...
=== PREVIOUS ANSWER ===
Well. Turns out, it cannot be done - The version I have now working is the correct way - as far as I can tell.
Explanation:
Apache CXF can be used with OR WITHOUT Spring.
JbossCXF (in AS 7.x or EAP 6.x) uses CXF as the default web service stack WITHOUT Spring. So when Jboss invokes the class that implements the web service interface (MyWebService above in my example annotated with #WebService(), the spring container is NOT yet initiated.... as the configuration in web.xml or jboss-cxf.xml does not allow for it.
So, the Spring container needs to be manually started inside the SEI impl class due to which the service class itself cannot be a spring managed bean (obviously).
Hence, the need to instantiate service beans inside the method using the getBean() method.
Once the service Beans are instantiated, their dependencies are automatically managed by the spring container as they are all now spring managed bean.
Hope this helps someone.
SGB
I am integrating Spring MVC into an existing project I have been working on. By integrating, I mean I am rewriting the project using Spring, and using much of my old code. I have already setup the environment and have began working on it. I will refer to this project as ProjectX.
I have already setup and configured my ProjectX-servlet.xml that holds the view-resolver bean, and the controller beans, etc. I want to set up an applicationContext.xml file that I can place all my DAO beans in such as ...
<bean id="MemberDAO" class="com.xxx.xxx.MemberDAO"/>
<bean id="ProductDAO" class="com.xxx.xxx.ProductDAO"/>
I want these values to be in the applicationContext.xml so that in my controllers I can do the following.
public SomeController extends SimpleFormController{
private MemberDAO memberDao;
private ProductDAO productDao;
...getter/setter methods for memberDao;
...getter/setter methods for productDao;
and the values will be available(injecting them into the controllers)
I have configured the controllers in the ProjectX-servlet.xml like the following definition.
<bean name="/SomeController.thm" class="com.xxx.xxx.controllers.SomeController">
<property name="memberDao" ref="MemberDAO"/>
<property name="productDao" ref="ProductDAO"/>
</bean>
I believe I need to configure something such as the following in my web.xml so that it knows to load the application context.
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<servlet>
<servlet-name>context</servlet-name>
<servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
My question is, what do I have to do following creating an applicationContext.xml file, to be able to do what I showed above and inject beans such as the ProductDAO and MemberDAO into my controlellers which are configured in the ProjectX-servlet.xml
I have been using Spring MVC for a contract for a couple months and am comfortable with how to use it, but I am new to configuring it on my own, for my own use, so I would appreciate if any advice or answers were explained a little easier for me.
Thank you
By convention, the name you give to your instance of DispatcherServlet will be associated with {name}-servlet.xml. This context will be a child to applicationContext.xml as you described, meaning it will have access to beans in applicationContext.xml.
Try the following in your web.xml:
<servlet>
<servlet-name>ProjectX</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ProjectX</servlet-name>
<url-pattern>/projectx/*</url-pattern>
</servlet-mapping>
You don't have to do anything special. You can continue injecting beans defined in applicationcontext.xml into the beans defined in xx-servlet.xml as if all of them are declared in same file. Do remember to use the attribute ref instead of ref-local as below.
<bean id="mycontroller" class="x.y.z.CustomerController>
<property name="service" ref="myservice"/><!--myservice defined in applicationcontext-->
</bean>
Unless I'm misunderstanding, the solution you're looking for is to use an import statement in your applicationContext.xml. This effectively combines the two XML files into a single context, allowing you to reference beans in either.
Ex:
<import resource="classpath:foo/bar/ProjectX-servlet.xml" />
You may or may not want to use "classpath." See section 3.2.2.1 in the Spring docs for more details.