Set Context path differently for both Webservice and Rest
I have an application which contains both implementation of Webservices and Rest services and I am looking for an solution to set context path for both Webservices and Rest services differently using yml/properties file
How to configure servlet dispatcher to work properly?
I would like to have:
localhost:8080/ws/* - webservice
localhost:8080/web/* - MVC components
servlet:
context-path: "/ws"
It sets globally for both webservices and rest services , How to make it independent to each other with out programming?
Using Spring Boot (with Spring Starter Web) you could achive what are you asking for with the annotation #RequestMapping.
You could put #RequestMapping(value="/ws") on the class declaration of every rest controller and #RequestMapping(value="/web") for web controllers.
For both rest and web controller than you could use other annotations to specify method path, i.e #GetMapping(value="/methodPath").
#Controller
#RequestMapping(value="/web")
public class WebController{
#GetMapping(value="/method")
public String method(){
...
}
}
#RestController
#RequestMapping(value="/ws")
public class RestController{
#GetMapping(value="method")
public String method(){
...
}
}
Related
I am working with Spring Boot 2 and I would like my requests to be handled asynchronously.
In Java EE, one can use Asynchronous Processing for Asynchronous Servlets as in this link. The following is a related example:
#WebServlet(urlPatterns={"/asyncservlet"}, asyncSupported=true)
public class AsyncServlet extends HttpServlet { ... }
and the above allows to use AsyncContext.
But in Spring Boot, I have the following #RequestMapping. How do I make it handle requests in Asynchronous mode and also supporting AsyncContext? How do I leverage the use of an Asynchronous Web Servlet?
#RestController
public class myRestController {
#RequestMapping("{resource}/**")
public void resourceRequest (#PathVariable("resource") String resource) {
// example:
// ... some long running calls such as database communication
// ... convert request through AsyncContext ctx = req.startAsync();
// etc
}
}
Note that returning void is intentional.
I found the following SO answer How to register a servlet with enabled "async-supported" in Spring-Boot? saying that "Spring Boot will automatically register any Servlet beans in your application context with the servlet container. By default async supported is set to true so there's nothing for you to do beyond creating a bean for your Servlet." but I am not using any #WebServlet annotations anywhere in my program, just the #RestController annotation. So how do I ensure that I am benefitting from asyncSupported option?
Problem:
I have a WebFilter which forwards valid urls to either a proxy servlet or a servlet which handles a webpage for the admin to monitor recent requests and more.
The admin servlet is suppost to forward ajax requests to a REST service (after login.jsp from the webpage rendered by controlpannel.jsp ) but apparently the rest service has a different context as the WebFilter and WebServlets ?
Question:
So is it at all possible to forward from my WebServlet to the rest helper servlet (and its resource classes) ?
More specific Information:
This is how I use forwarding:
ServletContext sc = request.getServletContext();
RequestDispatcher dispatcher = sc.getRequestDispatcher(forwardURI);
dispatcher.forward(request, response);
I tried to forward to this uri:
forwardURI = /REST/proxy_client/newer_than
My rest helper servlet:
#Stateless
#ApplicationPath("/REST")
public class RestService extends Application {
#Override
public Set<Class<?>> getClasses() {
final Set<Class<?>> restResourceClasses = new HashSet<Class<?>>();
restResourceClasses.add(ProxyClientResource.class);
return restResourceClasses;
}
}
And this resource class:
#Path("/proxy_client")
#Stateless
public class ProxyClientResource {
#EJB
private ProxyClientBean proxyClientBean;
#GET
#Produces("application/json")
#Path("/newer_than")
public String getNumberOfEntriesNewerThanTimestamp(#QueryParam("timestamp") Expression<Timestamp> indexTimestamp,
#QueryParam("numberOfclients") Integer numberOfclients) {
List<ProxyClient> pageData = proxyClientBean.getElementsNewerThan(numberOfclients, indexTimestamp);
return convertToJSONstring(pageData);
}
Solution attempt:
I found this question about how to call a rest web service from a servlet, but they use a client and no forwarding.
EDIT:
I had a configuration problem (might still have one), so now when I try to forward to my rest helper servlet (the one extending javax.ws.rs.core.Application) I get this error:
RestServlet is currently unavailable
(in the web.xml I call the Servlet RestServlet)
when accessing the REST api directly I get:
HTTP Status 500 - Authenticator.invoke() failed
but I can't find out what this means.
Edit2:
I will try repacing the subclass of Applicaton with a config in web.xml subclassing and #ApplicationPath dont seem to work for me. Also when I try to get the rest ServletsContext I get an error that no class has been specified, which is something you do when using the web.xml config.
Edit3:
I'm deploying my application on HCP and with the underlying problem beeing that I cant even access my REST service I found this SAP discussion.
When I get my REST service working without forwarding I will report back here.
Edit4:
This actually answers the question from Edit3
I had to add jersey 1.19.1 (not 2.x because im using Java EE6 which only supports up to DWP 3.0 not 3.1 as required) to by projects libraries otherwise It would say that I didn't specify a servlet class (but when I tried to add javax.ws.rs.core.Application it would tell me this is no Servlet class even though I have seen this configuration).
My real problem was that the javax.ws.rs.core.Application from the Java ee6 container on SAP Hana Cloud Platform did not work for a unkown reason.
The solution was to download and add the jersey-bundle-1.19.1.jar to WEB-INF/lib and the projects libraries.
There is no problem at all to forward a request from a vanilla servlet to the rest service! If it does not work in your case its most likely your setup or some unexpected reason like it was in my case.
I have a JavaEE MVC web app running on Wildfly 10. Now there is an idea to separate back-end and front-end. I want to create a RESTful Web Service with Spring Boot so it will mediate between front-end (Angular) and back-end (JavaEE app). For example the front-end will make AJAX calls to my RESTful Web Service and will handle the response returned in JSON format.
Within my JavaEE app I could make REST calls this way and the appropriate method would be invoked depending on the path. For example:
#Path("products")
public class ProductsResource {
#GET
#Produces(MediaType.APPLICATION_JSON)
public List<Products> getAllProducts() {
// return list of products
}
}
But for now I do not understand how can I make the Spring Boot RESTful service get data from my current JavaEE web app? They will be running on different servers.
UPD: providing more info on my JavaEE app, it has a DAO layer and EJBs as a service layer. For example:
public class ProdBean implements ProdBeanInterface {
#Override
public List<Product> getAllProducts(DataSource ds) {
ProdDao productDao = new PostgreSqlProdDao(ds);
return prodDao.getAllProducts();
}
The ProdBeanInterface is injected into a servlet controller and is further used for DB access fetching data from DAO layer.
In my previous experience:
When using pure servlet, we define servlets so that it will serve requests that match specific urls.
When using struts2, we define a filter so that it will serve requests that match specific urls.
When using springMVC in a traditional xml configuration style, we define a dispatcher servlet so that it will serve requests that match specific urls.
But with spring-boot:
Seems no servlet or filter is defined explicitly. But it still could serve specific urls.
The questions is:
Is it still using servlet? If yes, how it get to serve urls without defining servlet or filter explicitly?
Additional related questions (base on tips from comments):
It seems the implementation of SpringBootServletInitializer will be invoked on deploy, but who is going to invoke it?
As you can see here in details, on startup, while initializing an embedded server (Tomcat by default), Spring Boot creates and registers DispatcherServlet as a servlet.
Spring then, as usual, scans your own classes (including the one you invoke SpringApplication.run() from) and sets corresponding mapping for your controllers, if you have any. For example mapping for /hello here:
#RestController
#EnableAutoConfiguration
public class TestSpring {
#RequestMapping("/hello")
String hello() {
return "Hello World!";
}
public static void main(String[] args) throws Exception {
SpringApplication.run(TestSpring.class, args);
}
}
So I am developing a REST API in an application that uses both Spring and Wicket at the same time.
If I annotate #RequestMapping(value="/exchange") at my Spring #Controller annotated class (the one that is acting as a webserver), how do I have to configure Wicket to "recognize" http://myserver.com/myapp/exchange or http://myserver.com/myapp/exchange/onemethod as a valid URL so I don't get a 404 ERROR when I try to call the webservice from a client?
Use the JAX-RS #Path annotation:
#Path("exchange")
#Component
public class ExchangeService {
#POST
#Path("onemethod")
public void oneMethod(...) {
...
}
}