I'm implementing ApplicationEventListener, I need to retrieve the context path, the one declared in my web.xml:
<servlet-mapping>
<servlet-name>MyApplication</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
I'm implementing onEvent method
#Override
public void onEvent(ApplicationEvent event) {
if (event.getType() == ApplicationEvent.Type.INITIALIZATION_FINISHED) {
final ResourceModel resourceModel = event.getResourceModel();
}
}
I can also use #Context ServletContext servletContext in ResourceConfig to pass the info if necessary but I don't know how to reach this.
From a servlet using HttpServletRequest, it's possible to call request.getContextPath(), but obviously I can't use HttpServletRequest.
Generally speaking, in my application I need a way to retrieve servlet-mapping
Thanks
Edit:
listener class: org.glassfish.jersey.server.monitoring.ApplicationEventListener
Related
My rest application contains a service and I need to make this service to act like a singleton to save a state of the service.
a service:
#Path("/script")
public class ScriptEngineProvider {
private AtomicInteger idCounter;
public ScriptEngineProvider() {
System.out.println("before AtomicInteger");
idCounter = new AtomicInteger();
}
#POST
public Response executeScript( String x ) {
idCounter.incrementAndGet();
System.out.println("counter " + idCounter);
...
a client besides all other code has:
WebTarget webTarget = client.target("http://localhost:8080/NashornEngine/rest").path("script");
web.xml
<url-pattern>/rest/*</url-pattern>
With the above configuration the application works but with every request the variable idCounter creates so idCounter is allways 1.
Now I use next class to make the ScriptEngineProvider to be a singleton:
#ApplicationPath("/services")
public class NashornApplication extends Application {
private Set<Object> singletons = new HashSet<Object>();
public NashornApplication() {
singletons.add(new ScriptEngineProvider());
}
#Override
public Set<Object> getSingletons() {
return singletons;
}
}
The problem is that I get The requested resource is not available with request:
//path services was added
WebTarget webTarget = client.target("http://localhost:8080/NashornEngine/rest").path("services").path("script");
What is the problem with this config?
try this:
#Singleton // this is the important line
#Path("/script")
public class ScriptEngineProvider {
private AtomicInteger idCounter;
public ScriptEngineProvider() {
System.out.println("before AtomicInteger");
idCounter = new AtomicInteger();
}
#POST
public Response executeScript( String x ) {
idCounter.incrementAndGet();
System.out.println("counter " + idCounter);
...
#ApplicationPath effectively serves the same purpose as the url-mapping. But only one can be used. You use #ApplicationPath with an Application subclass when you don't want to use web.xml configuration. To go web.xml-less, you need to make sure of two things
You are deploying to a 3.x servlet container.
You have the dependency that supports the servlet pluggability. See more here
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>${jersey2.version}</version>
</dependency>
It's also possible to use an Application subclass without the #ApplicationPath, which will then use the url-mapping to map the Jersey servlet. For example
<servlet>
<servlet-name>MyApplication</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>com.pkg.YourApplication</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>MyApplication</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
Which ever way you choose, either the url-mapping path will be used, or the #ApplicationPath value will be used, but not both. So in your case, if you do with no web.xml configuration, the path would not include the /rest in the url-mapping. And if you go with the above web.xml configuration, then you should get rid of the #ApplicationPath on your Application subclass, that url you would use would with /rest, with no /services.
The reason you keep getting one is because
The default behavior is to create a new resource class for every request
Your Application subclass is not being used, and your web.xml configuration is being used, where you are package scanning.
Review the information from this post, and make the changes accordingly.
I am wondering if it is possible to dispatch a request from a servlet to a Jersey (JAX-RS implementation) resource class. I am trying to do it but it doesn't seem to work and according to my logging, the jersey resource is never reached.
Code examples are below. Is what I'm trying to do impossible for some reason?
Please note, the Jersey resource works correctly when I access it directly in a web browser via the address bar.
Also please note that 'RequestDispatcher.forward()' works as expected. It is just 'include' that doesn't.
The servlet
//The Jersey dispatcher url-filter is set to '/api/*'
String servletID = "/api/items";
RequestDispatcher dispatcher = getServletContext().getRequestDispatcher(servletID);
dispatcher.include(request, response);
The Jersey resource
#GET #Path("/items")
#Produces ({MediaType.TEXT_XML})
public JAXBElement<Items> getItems(#PathParam("project") String project) throws IOException, JAXBException {
log.debug("reached getItems");
//Omitted code that returns 'Items' object wrapped in JAXBElement
}
Relevant parts of web.xml
<servlet>
<servlet-name>jerseyDispatcher</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>uk.co.web.api.resource</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>jerseyDispatcher</servlet-name>
<url-pattern>/api/*</url-pattern>
</servlet-mapping>
It is possible you forward the request.
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
RequestDispatcher requestDispatcher = null;
requestDispatcher = httpServletRequest.getRequestDispatcher("/items");
dispatcher.forward(request, response);
return;
However note if you receive a GET request and try to forward to a POST resource,
It will throw a 405 error.
Edit:
Let me understand what you are trying to achieve, if you need write content to response output stream you could use jersey Resource Filter.
public class YourResourceFilter implements ResourceFilter
{
public ContainerRequestFilter getRequestFilter()
{
return new ContainerRequestFilter()
{
#Override
public ContainerRequest filter(ContainerRequest containerRequest)
{
//Pre- editing the request
return containerRequest;
}
};
}
#Override
public ContainerResponseFilter getResponseFilter()
{
return new ContainerResponseFilter()
{
#Override
public ContainerResponse filter(ContainerRequest containerRequest, ContainerResponse containerResponse)
{
// after the request has been completed by your jersey resource
return containerResponse;
}
};
}
}
I got it to work, sort of (Jersey 2.13) by configuring Jersey as a filter, and not a servlet, in web.xml. Then, you can tell the container to apply the filter to included requests too:
<filter-mapping>
<filter-name>Jersey Web Application</filter-name>
<url-pattern>/api/*</url-pattern>
<dispatcher>FORWARD</dispatcher>
<dispatcher>INCLUDE</dispatcher>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
RequestDispatcher.include will then work for request handled by Jersey, too. There's a caveat, though. Jersey calls response.getOutputStream, so all output must be performed through said output stream - this rules out JSP pages, that use response.getWriter instead. So, unless you figure out how to work around the problem, forget about including a Jersey resource in a JSP page or, vice versa, including the result of evaluating a JSP as part of a REST response.
I am trying to find out what is the proper way to initialize a static settings object, which should be loaded once and re-used by the restlets? Should I create a servlet which auto-loads, or is there (I am almost sure) a better way to do this?
Let's say I have a configuration.xml and would like to have it loaded so my restlets could start using it's settings. What would be the proper and most efficient way to do this?
Many thanks in advance!
You can create a ServletFilter that you map to your REST URLs in web.xml:
<filter-mapping>
<filter-name>MyServletFilter</filter-name>
<url-pattern>/rest/*</url-pattern>
</filter-mapping>
Then you override the init method to do your init business:
public class MyServletFilter implements javax.servlet.Filter {
#Override
public void init(FilterConfig filterConfig) throws ServletException {
loadConguration();
}
I'm having an issue regarding #RequestMapping on classes. Say I have these two controllers:
#Controller
#RequestMapping(value="/controller1")
public class Controller1 {
#RequestMapping(value="/method11.do")
public #ResponseBody method11(){
//...
}
#RequestMapping(value="/method12.do")
public ModelAndView method12(){
//This method redirects me to another jsp where I'll call Controller2 methods
return new ModelAndView("test");
}
}
#Controller
#RequestMapping(value="/controller2")
public class Controller2 {
#RequestMapping(value="/method21.do")
public #ResponseBody method21(){
//...
}
}
When I first call via AJAX method11, it works fine, the url generated is http://mydomain/myapp/controller1/method11.do
Then, I call method12 and get redirected to test.jsp, and from there, I call to method21, and here is the problem, the url generated is not the expected http://mydomain/myapp/controller2/method21.do, but something else, depending on how I make the AJAX call:
url:'controller2/method21' --> http://mydomain/myapp/controller1/controller2/method21.do
url:'/controller2/method21' --> http://mydomain/controller2/method21.do
So, in what way should I make the calls so that they always start at http://mydomain/myapp/...?
I believe I could just use url:'/myapp/controller2/method21.do', but I guess there should be a more generic way in which I don't have to use 'myapp' on every call.
This is my web.xml:
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
You should make the client aware of the proper URL by retrieving the context root within your script using JSP EL.
In JSP
<script>var ctx = "${pageContext.request.contextPath}"</script>
You can then use ctx as a prefix to the URLs constructed via Javascript.
var url = ctx + "/rest_of_url"
On the server side, you can use:
${pageContext.request.contextPath} or JSTL has a tag, <c:url> which will append your context root.
http://127.0.0.1:8888/socialnetwork/contactsService
That's the current URL for one of my servlets. My question is, how do I change it?
In my web.xml file, altering
<servlet-mapping>
<servlet-name>contactsServiceServlet</servlet-name>
<url-pattern>/socialnetwork/contactsService</url-pattern>
</servlet-mapping>
to
<servlet-mapping>
<servlet-name>contactsServiceServlet</servlet-name>
<url-pattern>/a/contactsService</url-pattern>
</servlet-mapping>
Makes absolutely NO difference to the URL it requests when I make an RPC-call to the servlet.
Once you have done the above you need to change where you invoke (Which is described in the Annotation below) as in...
// The RemoteServiceRelativePath annotation automatically calls setServiceEntryPoint()
#RemoteServiceRelativePath("email")
public interface MyEmailService extends RemoteService {
void emptyMyInbox(String username, String password);
}
See http://google-web-toolkit.googlecode.com/svn/javadoc/1.6/com/google/gwt/user/client/rpc/RemoteServiceRelativePath.html