REST Web Service not working - spring

I am just trying to create a simple test web service. I want to access the User in XML format at the following url: http://localhost:8080/Online_Shopping/dispatcher/rest/hello, but when I go to the URL nothing is displayed.
Here is my code for the service:
package com.shopping.controller;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import com.shopping.model.User;
#Path("/rest")
public class RESTController {
#GET
#Path("/hello")
#Produces(MediaType.APPLICATION_XML)
public User getUser() {
return new User("paymon","123",true);
}
}
The following code is in my spring-config.xml
<context:component-scan base-package="com.shopping.controller" />
This is in my web.xml
<servlet>
<servlet-name>mvc-dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring-config.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>mvc-dispatcher</servlet-name>
<url-pattern>/dispatcher/*</url-pattern>
</servlet-mapping>

Your application is running on port 8080 , so to access this URL you need to add in your servlet dispatcher the "Online_Shopping"
<servlet-mapping>
<servlet-name>mvc-dispatcher</servlet-name>
<url-pattern>Online_Shopping/dispatcher/*</url-pattern>
</servlet-mapping>
or Just access your api without Online_Shoppping

You have to use Spring MVC's annotations instead and use #Controller or #RestController to annotate you controller to be registered as a spring controller.
Try this :
#RestController
#RequestMapping(value = "/rest")
public class RESTController {
#RequestMapping(value = "/hello",
method = RequestMethod.GET,
produces = "application/xml")
public User getUser() {
return new User("paymon","123",true);
}
}

Related

running spring mvc web app and jaxws soap web service in single tomcat instance having 1 web.xml file

I am making a zoho to quickbooks integration. In which I have created web application and soap service for quickbooks desktop to communicate with. My web app works fine with spring annotations but the autowired like annotations don't work. I want to know whether you can keep web.xml configuration like below
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" id="WebApp_ID" version="4.0">
<display-name>zohoquickbooks</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<session-config>
<session-timeout>2</session-timeout>
</session-config>
<servlet>
<servlet-name>zohoquickbooksdispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/zohoquickbooks-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>zohoquickbooksdispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<listener>
<listener-class>
com.sun.xml.ws.transport.http.servlet.WSServletContextListener
</listener-class>
</listener>
<servlet>
<servlet-name>qbservice</servlet-name>
<servlet-class>
com.sun.xml.ws.transport.http.servlet.WSServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>qbservice</servlet-name>
<url-pattern>/qbservice</url-pattern>
</servlet-mapping>
</web-app>
This configuration works. One problem is there for jaxws service in web.xml. The object of implementation class is initiated by jax-ws container and not by spring so autowiring other objects in that class does not work. You can get spring managed objects into non spring managed object by doing specified in this URL "https://dzone.com/articles/autowiring-spring-beans-into-classes-not-managed-by-spring". Otherwise this configuration works fine. You can run web app and soap service on same container on same port. Just the url path needs to be different.
It's easy with spring boot without any xml.
You can use dependency: cxf-spring-boot-starter-jaxws.
https://mvnrepository.com/artifact/org.apache.cxf/cxf-spring-boot-starter-jaxws
It will separate your spring services from jaxws services. By default it will expose jaxws service at url: http://localhost:8080/services
Details you can read here https://cxf.apache.org/docs/springboot.html.
import org.apache.cxf.Bus;
import org.apache.cxf.jaxws.EndpointImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.xml.ws.Endpoint;
#Configuration
public class ApacheCxfConfig {
#Autowired
private Bus bus;
#Bean
public Endpoint endpoint() {
EndpointImpl endpoint = new EndpointImpl(bus, new NumberConversionSoapTypeImpl());
endpoint.publish("/hello");
return endpoint;
}
}
#WebService(name = "NumberConversionSoapType", targetNamespace = "http://www.dataaccess.com/webservicesserver/")
#XmlSeeAlso({
ObjectFactory.class
})
public interface NumberConversionSoapType {
/**
* Returns the word corresponding to the positive number passed as parameter. Limited to quadrillions.
*
* #param ubiNum
* #return
* returns java.lang.String
*/
#WebMethod(operationName = "NumberToWords")
#WebResult(name = "NumberToWordsResult", targetNamespace = "http://www.dataaccess.com/webservicesserver/")
#RequestWrapper(localName = "NumberToWords", targetNamespace = "http://www.dataaccess.com/webservicesserver/", className = "az.soap.NumberToWords")
#ResponseWrapper(localName = "NumberToWordsResponse", targetNamespace = "http://www.dataaccess.com/webservicesserver/", className = "az.soap.NumberToWordsResponse")
public String numberToWords(
#WebParam(name = "ubiNum", targetNamespace = "http://www.dataaccess.com/webservicesserver/")
BigInteger ubiNum);
}
#Service
#WebService(name = "NumberConversionSoapType", targetNamespace = "http://www.dataaccess.com/webservicesserver/")
public class NumberConversionSoapTypeImpl implements NumberConversionSoapType {
#Override
public String numberToWords(BigInteger ubiNum) {
System.out.println("numberToWords");
return null;
}
}

Request is not mapped to the controller

When I go with the url..http://localhost:8080/springdemo/hello..it is showing 404 not found error..I have put my java file inside src/main/java as usual in Maven project. My controller code is as follows :-
package org.abhishek;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
import java.lang.System;
#Controller
public class HelloWorldController {
#RequestMapping(value="/hello", method = RequestMethod.GET)
public ModelAndView helloWorld() {
System.out.println("hello**");
String message = "Hello World, Spring MVC # Javatpoint";
return new ModelAndView("hello", "message", message);
}
}
Web.xml file given below
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="java.sun.com/xml/ns/javaee"; xmlns:xsi="w3.org/2001/XMLSchema-instance"; xsi:schemaLocation="java.sun.com/xml/ns/javaee java.sun.com/xml/ns/javaee/web-app_2_5.xsd">;
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
</web-app>
I put this line System.out.println() for debugging purpose and I found that this method is not executed with the above mentioned url...i.e. http://localhost:8080/springdemo/hello.Please answer..thanx in advance.
This is speculative, but you could have a mapping problem in your web.xml file, which would result in the Spring controller not even being hit (despite having a correct #RequestMapping annotation). Your web.xml file should have the following servlet mapping:
<servlet>
<servlet-name>springServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springServlet</servlet-name>
<url-pattern>/springdemo/*</url-pattern>
</servlet-mapping>
Now paste your URL into a web browser and see if you can hit it:
http://localhost:8080/springdemo/hello

ServletContext Attribute is null when accessing it via restful web service in jersey implementation

I have a Java MVC application with a single controller. The database is initialized in servlet context listener class. I am passing the database object as a servlet context attribute to the controller servlet and webservice class. In controller servlet the "db" attribute is working fine but in web service class I am getting null and illegal state exception.
Error stacktrace -
javax.servlet.ServletException: A MultiException has 2 exceptions. They
are:
1. java.lang.NullPointerException
2. java.lang.IllegalStateException: Unable to perform operation: create on
com.home.mystorywriter.UserWS
org.glassfish.jersey.servlet.WebComponent.serviceImpl(WebComponent.java:489)
org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:427)
org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java: 388)
org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java: 341)
org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java: 228)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
root cause
java.lang.NullPointerException
at com.home.mystorywriter.UserWS.<init>(UserWS.java:36)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
webservice class
package com.home.mystorywriter;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import com.google.gson.Gson;
#Path("/users")
public class UserWS {
#Context
private HttpServletRequest req;
private HttpServletResponse res;
private ServletContext context ;
DAOdb db = (DAOdb)req.getServletContext().getAttribute("db");
#GET
#Produces(MediaType.APPLICATION_JSON)
#Path("allUsers")
public String getAllUsers() {
List<Profile> userlist = db.getProfileListOfAllUsers();
Gson gson = new Gson();
String jsonUsers = gson.toJson(userlist);
return jsonUsers;
}
}
Web.xml
<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
si:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1">
<listener>
<description>MyServletContextListener</description>
<listener-
class>com.home.mystorywriter.MyServletContextListener</listener-class>
</listener>
<servlet>
<servlet-name>StoryServlet</servlet-name>
<servlet-class>com.home.mystorywriter.StoryServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>Jersey REST Service</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>com.home.mystorywriter</param-value>
</init-param>
<init-param>
<param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
<param-value>true</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>StoryServlet</servlet-name>
<url-pattern>/StoryServlet</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Jersey REST Service</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>login.html</welcome-file>
</welcome-file-list>
</web-app>
#Context injection happens inside the web service class or class method. Below code is working fine.
#Path("/users")
public class UserWS {
private ServletContext context ;
DAOdb db;
public UserWS() {
System.out.println("Inside Constructor " + context);
}
#Context
public void setServletContext(ServletContext context) {
System.out.println("servlet context set here");
this.context = context;
db = (DAOdb)context.getAttribute("db");
}
#GET
#Produces(MediaType.APPLICATION_JSON)
#Path("/allUsers")
public String getAllUsers() {
System.out.println("Inside get method:"+ context);
System.out.println("db value"+ db);
Profile userlist = db.getProfileWithoutPic();
Gson gson = new Gson();
String jsonUsers = gson.toJson(userlist);
return jsonUsers;
}
}

Spring Mvc:No mapping found for HTTP request with URI

Maven3 + Spring 4 + Jetty
web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" 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_3_0.xsd">
<display-name></display-name>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<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>com.vito16.activiti.demo1.config.AppConfig</param-value>
</context-param>
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextClass</param-name>
<param-value>
org.springframework.web.context.support.AnnotationConfigWebApplicationContext
</param-value>
</init-param>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>com.vito16.activiti.demo1.config.WebConfig</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- Open Entity Manager in View filter -->
<filter>
<filter-name>openEntityManagerInViewFilter</filter-name>
<filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>openEntityManagerInViewFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
Spring mvc config using annotation:
package com.vito16.activiti.demo1.config;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import org.activiti.spring.annotations.EnableActiviti;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PropertiesLoaderUtils;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.Database;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;
/**
* #author Vito
* #version 2014/6/4
*/
#Configuration
#EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
#Bean
public InternalResourceViewResolver internalResourceViewResolver() {
InternalResourceViewResolver internalResourceViewResolver = new InternalResourceViewResolver();
internalResourceViewResolver.setPrefix("/WEB-INF/views/");
internalResourceViewResolver.setSuffix(".jsp");
return internalResourceViewResolver;
}
#Bean
public RequestMappingHandlerMapping requestMappingHandlerMapping() {
return new RequestMappingHandlerMapping();
}
#Bean
public RequestMappingHandlerAdapter requestMappingHandlerAdapter() {
return new RequestMappingHandlerAdapter();
}
}
My test controller:
package com.vito16.activiti.demo1.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
/**
* #author Vito
* #version 2014/6/4
*/
#Controller
public class IndexController {
#RequestMapping(value = "/index", method = RequestMethod.GET)
public String index() {
return "index";
}
}
when im visit http://127.0.0.1:8080/index result 404:
and console print message:
INFO o.s.w.s.m.m.a.RequestMappingHandlerMapping - Mapped "{[/index],methods=[GET],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public java.lang.String com.vito16.activiti.demo1.controller.IndexController.index()
INFO o.s.web.servlet.DispatcherServlet - FrameworkServlet 'dispatcher': initialization completed in 265 ms
WARN o.s.web.servlet.PageNotFound - No mapping found for HTTP request with URI [/WEB-INF/views/index.jsp] in DispatcherServlet with name 'dispatcher'
How to fix it? I do not have this problem before using the XML configuration over time
your configuration is missing
#ComponentScan(basePackages = "your package to beans")
so it cant scan your beans like controller or whatever you try to make as bean
so add this on top of your configuration class like below
#Configuration
#EnableWebMvc
#ComponentScan(basePackages = "com.vito16.activiti.demo1")
public class WebConfig extends WebMvcConfigurerAdapter {
#Bean
public InternalResourceViewResolver internalResourceViewResolver() {
InternalResourceViewResolver internalResourceViewResolver = new InternalResourceViewResolver();
internalResourceViewResolver.setPrefix("/WEB-INF/views/");
internalResourceViewResolver.setSuffix(".jsp");
return internalResourceViewResolver;
}
#Bean
public RequestMappingHandlerMapping requestMappingHandlerMapping() {
return new RequestMappingHandlerMapping();
}
#Bean
public RequestMappingHandlerAdapter requestMappingHandlerAdapter() {
return new RequestMappingHandlerAdapter();
}
}

Spring 2.5.5 and jersey with autowired

I am trying to integrate jersey to an existing Spring application (Spring 2.5.5).
Jersey is working fine, but however when I AutoWire an existing spring bean, the object is null.
Below is my web.xml
<servlet>
<servlet-name>fs3web</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet>
<servlet-name>jersey-servlet</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.fl.fs3.api;org.codehaus.jackson.jaxrs</param-value>
</init-param>
<init-param>
<param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
<param-value>true</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>fs3web</servlet-name>
<url-pattern>/fs3/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>jersey-servlet</servlet-name>
<url-pattern>/api/*</url-pattern>
</servlet-mapping>
And, here my application context xml (obviously this is not complete, since this is a huge application, there is much more bean definitions):
TestPojo is my bean I would like to autowire to my jersey resource.
<context:annotation-config />
<aop:aspectj-autoproxy/>
<context:component-scan base-package="com.fl.fs3.api,com.fl.fs3.integration.*.web"/>
Both my jersey resource class and POJO class is in package com.fl.fs3.api
#Component
#Path("/v1/site")
public class SitesApiControllerV1 {
#Autowired TestPojo testPojo;
#GET
#Path("/{folderName}")
#Produces(MediaType.APPLICATION_JSON)
public Response getSite(#PathParam("folderName") String folderName) {
System.out.println("pojo obj:" + testPojo);
return Response.ok("info for " + folderName).build();
}
}
#Component
public class TestPojo {
}
When I start my tomcat, I do not see the expected line in logs:
INFO: Registering Spring bean, hello, of type ..... as a root resource class
When I invoke my service /v1/site/xyz, testPojo object is null.
However, before integrating this to my existing project, I did a sample jersey+spring application, and it worked perfectly. I was able to see 'Registering Spring bean' line in logs.
Any help is appreciated.
Try this, it may be more simplified:
Load spring through web.xml like shown below as normal spring confifuration:
<servlet>
<servlet-name>project-spring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:project-spring-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>project-spring</servlet-name>
<url-pattern>*.htm</url-pattern>
</servlet-mapping>
Now load your jersey Resources through Application as shown below:
#ApplicationPath("/rest")
public class ResourceLoader extends Application
{
/* (non-Javadoc)
* #see javax.ws.rs.core.Application#getClasses()
*/
#Override
public Set<Class<?>> getClasses()
{
Set<Class<?>> classes = new HashSet<Class<?>>();
loadResourceClasses(classes);
return classes;
}
private void loadResourceClasses(Set<Class<?>> classes)
{
classes.add(StudentResource.class);
}
}
Then in your resource:
#Path("student")
class StudentResource
{
private StudentService studentService;
StudentResource(#Context ServletContext servletContext)
{
ApplicationContext applicationContext = WebApplicationContextUtils.getWebApplicationContext(servletContext);
this.transactionService = applicationContext.getBean(StudentService .class);
}
}
There you go.
Spring has been configured with all dependency injections with Jersey!

Resources