I'm running Spring 4 and am trying to build a VERY basic REST web service as a proof of concept. Here is my web.xml:
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app id="poc" version="2.4"
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">
<display-name>Archetype Created Web Application</display-name>
<servlet>
<servlet-name>ws</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>ws</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/ws-servlet.xml</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
</web-app>
Here's the definition of my servlet in my application context:
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<bean name="/rememberName" class="com.corrisoft.air.ws.RememberNameController" init-method="init">
<property name="personService" ref="personService"/>
</bean>
Here are the messages I'm getting from Spring:
INFO: Mapped URL path [/rememberName] onto handler '/rememberName'
....
WARNING: No mapping found for HTTP request with URI [/springpoc/ws/rememberName] in DispatcherServlet with name 'ws'
Where springpoc is the name of the war file I'm deploying under tomcat. RememberNameController directly extends HttpServlet.
Can someone tell me what I'm doing wrong with my mapping?
I think this:
<servlet-mapping>
<servlet-name>ws</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
needs to be this:
<servlet-mapping>
<servlet-name>ws</servlet-name>
<url-pattern>/ws/*</url-pattern>
</servlet-mapping>
I think the problem is that you are mixing what is intended to be a Spring Controller with plain Servlets.
Spring Controllers are not Servlets, they are regular POJOs that are used by Spring MVC for handling the requests (called by the Dispatcher Servlet)
If you want to see a modern way of creating a REST Service using Spring 4, check out this guide
Spring controllers should not extend HttpServlet, they should be built with Spring annotations. e.g.
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
#Controller
public class HelloWorldController {
#RequestMapping("/hello")
public String hello() {
return "helloworld";
}
}
See the following tutorial for details http://javahash.com/spring-4-mvc-hello-world-tutorial-full-example/
Related
Im new to spring with crystal reports I have created my application where I used some java annotation configuration. Now I am trying to integrate with crystal reports where I have to convert xml based web.xml to java based config
here is the web.xml code
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1">
<!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/appServlet/servlet-context.xml</param-value>
</context-param>
<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Processes application requests -->
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/appServlet/servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- crystal report in spring -->
<context-param>
<param-name>crystal_image_uri</param-name>
<param-value>/crystalreportviewers</param-value>
</context-param>
<context-param>
<param-name>crystal_image_use_relative</param-name>
<param-value>webapp</param-value>
</context-param>
<servlet>
<servlet-name>CrystalReportViewerHandler</servlet-name>
<servlet-class>com.crystaldecisions.report.web.viewer.CrystalReportViewerServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>CrystalReportViewerHandler</servlet-name>
<url-pattern>/CrystalReportViewerHandler</url-pattern>
<url-pattern>/faces/CrystalReportViewerHandler</url-pattern>
</servlet-mapping>
</web-app>
I have tried to mix it with java config but it fails,
Thanks in advance
To convert your basic web.xml to java configuration, either create a class by
implement WebApplicationInitializer or
extend AbstractAnnotationConfigDispatcherServletInitializer
regarding your crystal report you can create the Bean of type CrystalReportViewerServlet using #Bean Annotation.
for more information please check
- web.xml to java config
and register secondary servlet in spring
Thanks for to all who looked for a solution. I did the following
#Configuration
#ComponentScan(basePackages = { "t.g.app" })
public class ReportsConfig implements WebApplicationInitializer{
#Override
public void onStartup(ServletContext servletContext) throws ServletException{
servletContext.setInitParameter("crystal_image_uri","/crystalreportviewers");
servletContext.setInitParameter("crystal_image_use_relative", "webapp");
ServletRegistration.Dynamic crystalReportViewerHandler = servletContext
.addServlet("CrystalReportViewerHandler", new CrystalReportViewerServlet());
crystalReportViewerHandler.setLoadOnStartup(1);
crystalReportViewerHandler.addMapping("/CrystalReportViewerHandler");
}
}
There were also some security issues caused by spring security so i added some exceptions in security configuration.
It seems that dispatcher-servlet unable to perform component scan using.
<context:component-scan base-package="abc" />
In my controller file (HelloController.java) under package abc. Code is written as follows:
#Controller
#RequestMapping("/hello")
public class HelloController {
#RequestMapping(method = RequestMethod.GET)
public String printHello(ModelMap model) {
model.addAttribute("message", "Hello Spring MVC Framework!");
return "hello"; //I have already made hello.jsp in web-inf/jsp/
}
}
My Application name is SpringMiddle. When try url as:
http://localhost:8080/SpringMiddle/hello.htm
I do have following url pattern in web.xml
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>*.htm</url-pattern>
</servlet-mapping>
It shows me error HTTP 404 not found.
EDIT: : it shows me warning
WARNING: No mapping found for HTTP request with URI [/SpringMiddle/hello.htm] in DispatcherServlet with name 'dispatcher'
You have to enable MVC in Spring. In xml config you can do it in such way:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc"
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
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<mvc:annotation-driven />
</beans>
and in JavaConfig:
#Configuration
#EnableWebMvc
public class WebConfig {
}
Please refer to Spring documentation
if you are referring to an mkyong tutorial, I didn't use the annotations: #Configuration
#EnableWebMvc, problem is you are using both annotations and xml declaration.
Annotation for setting the url:
#Controller
#RequestMapping("/hello")
you should remove this part:
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>*.htm</url-pattern>
</servlet-mapping>
and you'll be able to visit the url:
http://localhost:8080/SpringMiddle/hello
Also make sure you have this in your web.xml:
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/dispatcher-servlet.xml</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
the dispatcher-servlet.xml is where the component scanning is declared
This issue is solved. Someone created a file called mvc-dispatcher.xml and it had an incorrect configuration. That file is loaded automatically because it's called the same as a servlet.
I want to thank everyone who tried to help me fix this issue. I'm keeping this question here, since it actually explains how to create a REST interface. It works perfectly.
I'm trying to set up a RESTful interface with Spring-MVC. The server starts without issue, but any time I try to call the REST interface I get the message:
41 WARN [springframework.web.servlet.PageNotFound] No mapping found for HTTP request with URI [/myweb/rest/asd/aaa] in DispatcherServlet with name 'mvc-dispatcher'
It seems that the URL I am sending (http://localhost:8080/myweb/rest/asd/qwe for example) is not 'captured' by any controller. What am I doing wrong?
I do not know what else I could try. I'm using Java 1.7.0_15, Tomcat 7.0.34 and Spring 3.1.4.RELEASE
In my web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
<display-name>MyWeb</display-name>
<welcome-file-list>
<welcome-file>index.xhtml</welcome-file>
</welcome-file-list>
<!-- Listener for MVC spring -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
<!-- Servlet for MVC spring -->
<servlet>
<servlet-name>mvc-dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>mvc-dispatcher</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
<!-- Loading web properties -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext*.xml</param-value>
</context-param>
In my applicationContext.xml:
<context:component-scan base-package="com.myweb.*" />
<context:annotation-config/>
<tx:annotation-driven/>
<mvc:annotation-driven />
And finally, my controller class:
import org.apache.log4j.Logger;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
#Controller
public class RestController {
private static Logger LOG = Logger.getLogger(RestController.class);
#RequestMapping("/asd/{test}")
public void test(#PathVariable String test) {
LOG.info("You sent "+test);
}
}
Tried changing the method's #RequestMapping but still didn't work:
#RequestMapping(method=RequestMethod.GET)
public void test() {
LOG.info("You sent something");
}
Your mapping is wrong.
You are requesting /rest/asd/aaa but your mapping is for /asd/{test}.
You need to change #RequestMapping("/asd/{test}") to #RequestMapping("/rest/asd/{test}")
Or add #RequestMapping("/rest") to your controller class
Try annotate your controller class also with #RequestMapping("/rest") to handle all requests with url
/webapp/rest/
You should also configure your context via org.springframework.web.context.ContextLoaderListener listener. I think You are not loading applicationContext.xml
Add this part to your web.xml
<!--spring bootstrap listener -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/config/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
I am fairly new to Apache CXF and tomcat. I am trying to build a simple web service and deploy it on tomcat. below is my web.xml
However when I try to access the 'services' folder using my browser it says No services have been found. I tried creating java web service client but it is not able to locate the service either. What could be wrong in this?
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 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_2_5.xsd">
<display-name>Sample web service provider</display-name>
<listener>
<!-- For Metro, use this listener-class instead:
com.sun.xml.ws.transport.http.servlet.WSServletContextListener -->
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<!-- Remove below context-param element if using Metro -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:META-INF/cxf/cxf.xml
</param-value>
</context-param>
<servlet>
<servlet-name>WebServicePort</servlet-name>
<!-- For Metro, use this servlet-class instead:
com.sun.xml.ws.transport.http.servlet.WSServlet -->
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>WebServicePort</servlet-name>
<url-pattern>/services/*</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>60</session-timeout>
</session-config>
</web-app>
This means that you don't have any services exposed in your application. Your web.xml seems to be correct but I've just missed one thing, your Spring configuration. Add your Spring config location in your web.xml, for e.g.:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>WEB-INF/applicationContext.xml</param-value>
</context-param>
Also, you have to create a class which will implement your web service interface and expose it as the CXF endpoint in your Spring applicationContext.xml configuration file. For e.g.:
<bean id="candidateImpl" class="some.pckg.CandidateImpl"/>
<jaxws:endpoint id="candidateEndpoint"
implementor="#candidateImpl"
address="/Candidate"
/>
Your CandidateImpl class should have #WebService annotation. For e.g.:
#WebService(targetNamespace = "http://something.com/ws/candidate",
portName = "CandidateService",
serviceName = "Candidate",
endpointInterface = "some.pckg.types.CandidateService",
wsdlLocation = "WEB-INF/wsdl/CandidateService.wsdl")
public class CandidateImpl implements CandidateService {
//Implementation of all methods from CandidateService.
}
If you've done everything correctly you should see that there is one service available under:
http(s)://whateverhost.com:<somePort>/SomeContextPath/services
And you should be able to get the WSDL file like this:
http(s)://whateverhost.com:<somePort>/SomeContextPath/services/Candidate?wsdl
See also:
Writing a Web Service with Spring
You need to set the spring configuration file location to make this work. You can set it as follows.
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>WEB-INF/applicationContext.xml</param-value>
</context-param>
You need to configure a servlet in your web.xml. Below an example.
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<servlet>
<servlet-name>CXFServlet</servlet-name>
<display-name>CXF Servlet</display-name>
<servlet-class>
org.apache.cxf.transport.servlet.CXFServlet
</servlet-class>
<init-param>
<param-name>config-location</param-name>
<param-value>/WEB-INF/spring-ws-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>CXFServlet</servlet-name>
<url-pattern>/services/*</url-pattern>
</servlet-mapping>
</web-app>
Now you need to define a file named spring-ws-servlet.xml under WEB-INF folder. Below an example of the content of spring-ws-servlet.xml, which contains the actual configuration for your web service. This depends on your logic, of course:
<?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"
xmlns:jaxws="http://cxf.apache.org/jaxws"
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
http://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd">
<context:component-scan base-package="com.sample.service"/>
<!-- JAX-WS Service Endpoint -->
<bean id="personImpl" class="com.sample.service.impl.PersonServiceImpl"/>
<jaxws:endpoint id="personEndpoint"
implementor="#personImpl"
address="/person">
<jaxws:properties>
<entry key="schema-validation-enabled" value="true"/>
</jaxws:properties>
</jaxws:endpoint>
<!-- JAX-WS Service Endpoint End-->
</beans>
With this, you can access your web service under http://localhost:8080/services/person?wsdl
This is taken from this post. It is a tutorial about creating a Cxf service with IntelliJ Idea and Spring
https://aldavblog.wordpress.com/2015/01/22/creating-a-web-service-from-scratch-using-spring-maven-apache-cxf/
The JAX-RS 1.1 specification says on page 6:
If no Application subclass is present
the added servlet MUST be named:
javax.ws.rs.core.Application
What is the added servlet? Could it be an arbitrary servlet?
If an Application subclass is present
and there is already a servlet defined
that has a servlet initialization
parameter named:
javax.ws.rs.Application
Again, what is "a servlet" here?
If an Application subclass is present
that is not being handled by an
existing servlet then the servlet
added by the ContainerInitializer MUST
be named with the fully qualified name
of the Application subclass.
Does "the servlet added by the ContainerInitializer" mean that the servlets is added automatically? How would a configuration look like?
At the moment I use neither an Application class nor a web.xml and it works (with GlassFish 3.1). Does this deployment mechanism require a full class path scan, which could be slow with big libraries?
How to deploy on a Servlet container?
There is a confusing number of configuration options around in the web. See this example with context params in the web.xml (doesn't work for me!). What is the preferred way to deploy a JAX-RS application?
There are a number of options for deploying into a Java EE 6 container (more specifically a Servlet 3.0 implementation):
The simplest is:
<?xml version="1.0" encoding="UTF-8"?>
<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_3_0.xsd" version="3.0">
<servlet>
<servlet-name>javax.ws.rs.core.Application</servlet-name>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>javax.ws.rs.core.Application</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
</web-app>
Then all the #Path and #Provider classes found in your web application will be available in the "default" JAX-RS application with a servlet URL pattern of "/rest/*".
If you have one or more classes that extends javax.ws.rs.core.Application, you can specify like so:
<?xml version="1.0" encoding="UTF-8"?>
<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_3_0.xsd" version="3.0">
<servlet>
<servlet-name>com.example.jaxrs.MyApplication</servlet-name>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>com.example.jaxrs.MyApplication</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
</web-app>
You may want to do the above in case you wish to only return specific sets of #Path/#Provider classes on a URL (so you could have a second MyApplication2 with a different URL pattern above).
You can also skip the whole web.xml altogether and just annotate your MyApplication class wih #ApplicationPath which will serve as the URL pattern. I would recommend keeping the web.xml in any case because you will probably have to add other information about the web application there anyway.
If you're wondering where the servlet-class comes from, it is automatically added in by the environment. You can get an idea by looking at the Servlet 3.0 ServletContext.
With WAS 8.5, I change the web.xml to add:
<servlet>
<servlet-class>com.ibm.websphere.jaxrs.server.IBMRestServlet</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>com.tada.rest.RestApplication</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
<servlet-name>javax.ws.rs.core.Application</servlet-name>
</servlet>
<servlet-mapping>
<servlet-name>javax.ws.rs.core.Application</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
My RestApplication look like :
import java.util.HashSet;
import java.util.Set;
import javax.ws.rs.core.Application;
public class RestApplication extends Application {
#Override
public Set<Class<?>> getClasses() {
Set<Class<?>> sets = new HashSet<Class<?>>();
sets.add(RestService.class);
return sets;
}
}
My RestService looks like
#Path("/tada")
public class RestService {
#GET
public String getSomething() {
return "tada";
}
}
And I add in the pom.xml the dependency:
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
<version>2.0</version>
</dependency>
With Servlet3.0, follow this. This works for me.
<servlet>
<description>JAX-RS Tools Generated - Do not modify</description>
<servlet-name>JAX-RS Servlet</servlet-name>
<servlet-class>com.ibm.websphere.jaxrs.server.IBMRestServlet</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>your.restsrv.config.RESTConfig</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
<enabled>true</enabled>
<async-supported>false</async-supported>
</servlet>
<servlet>
<servlet-name>javax.ws.rs.core.Application</servlet-name>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>javax.ws.rs.core.Application</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>JAX-RS Servlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
As I said in the comment above, it all depends on the framework you want to use.
http://syrupsucker.blogspot.com/2008/10/deploying-jersey-in-tomcat-60.html for Jersey
http://syrupsucker.blogspot.com/2008/10/deploying-resteasy-in-tomcat-60.html for RESTeasy
As far as I know, JAX-RS does not contain a specification for deployment.