The following method does not allow my servlet container to start:
#PUT
public String upload(final Customer customer, final Control control) {
// ...
}
I get, not surprisingly:
SEVERE: Missing dependency for method ... at index 0
SEVERE: Missing dependency for method ... index 1
SEVERE: Method, ..., is not recognized as valid resource method.
I have implemented MessageBodyReaders for each type. Removing any of the parameters enables the servlet container to start gracefully, so I suspect there must be a restriction on the number of parameters that will be resolved via Entity-Providers.
The problem is that I NEED these two parameters, since I am providing both SOAP and REST support, and of course, I am not in the liberty of changing method signatures, and I also do not want to create one specific Jersey method and one specific JAX-WS method as entry points.
I'm using Jersey 1.7.
JAX-RS allows only one entity parameter. The reson is very simple: each request may have at most one body (multiparts are not supported by spec)
So you must create two methods.
Btw, I don't think it's a good practice to mix JAXRS and JAXWS in the same class.
Related
I am running a Jetty web server and I have a generic servlet filter to handle exceptions. As part of this, I want to log aggregated metrics about which servlets are causing the exceptions. Is there a way I can figure out which servlets defined in the web.xml match the servlet path of the current request?
I have a generic servlet filter to handle exceptions
I take you to mean that your filter extends javax.servlet.GenericFilter directly.
Is there a way I can figure out which servlets defined in the web.xml match the servlet path of the current request?
In any given servlet context there should not be more than one servlet mapped to a given servlet path, so in any given case you're looking for just one servlet, not multiple.
As far as I know or can tell, GenericFilter and the generic ServletRequests and ServletResponses with which it works do not provide a good way to access the information you are after. If you cast the request to HttpServletRequest, however, then you can obtain its HttpServletMapping (since Servlet 4.0 / Java EE 8)
, which contains the servlet name as declared in the webapp's deployment descriptor, among other information. Or the HttpServletRequest can directly provide the servlet path, too.
But if you are contemplating casting the requests, then you would probably be better off having your filter extend javax.servlet.http.HttpFilter, which would give you type-safe access. This is itself a subclass of GenericFilter, so it probably wouldn't be difficult to perform such a refactoring.
I have the following javax rs annotated interface:
#Path("/")
public interface MyRestEndpoint {
#GET
#Produces(MediaType.APPLICATION_JSON)
#Path("myapp/resources/resourceId/{resourceId}/memberId/{memberId}")
MyResource findMyResource(#PathParam("resourceId") int resourceId,
#PathParam("memberId") long memberId);
Which I am calling via a jersey proxy client created as such:
MyRestEndpoint myRestEndpointForTests = WebResourceFactory.newResource(MyRestEndpoint.class, lobbyClient().target(myHost));
...
myRestEndpointForTests.findMyResource(resourceId, memberId);
But when I do so, I get the following exception:
java.lang.IllegalStateException: Unresolved variables; only 0 value(s) given for 2 unique variable(s)
at org.glassfish.jersey.client.JerseyWebTarget.getUri(JerseyWebTarget.java:134)
at org.glassfish.jersey.client.JerseyWebTarget.request(JerseyWebTarget.java:214)
at org.glassfish.jersey.client.JerseyWebTarget.request(JerseyWebTarget.java:59)
at org.glassfish.jersey.client.proxy.WebResourceFactory.invoke(WebResourceFactory.java:312)
at com.sun.proxy.$Proxy89.findCurrentTableOfPlayer(Unknown Source)
Having debugged somewhat through the Jersey codebase, it seems that the WebResourceFactory is trying to create a WebTarget by looping over the annotations on the MyRestEndpoint class. It picks up both annotations, and both provided values but seems to overwrite any previously resolved path params as it loops over them (so its left with only the memberId path param being resolved). Can anyone explain why? Is this a bug or expected behaviour? How can I support multiple path params?
I know this is specific to having more than one path parameter configured via annotation. As I have other methods in the annotated interface that have only one path parameter and work perfectly when called in the same way.
I'm using Jersey v2.16 components and Javax rs v2.0.1 components
Looks like WebResourceFactory is not actively developed also it's source code was quite hard to understand for me.
So we created another implementation of proxing rest interfaces.
Feel free to try https://github.com/adaptris/jaxrs-client-proxy implementation. It's under development currently so for sure have some bugs.
Is there any default method for java restful web services.
If I dont annotate my root resource class method with any html method annotation then will it match the upcoming get request to that method
#Path("xyz")
class abc
{
String methodName(String name)
{
//processing
}
}
In this case if I have an get request , then will this method be treated as resource .
I read that when our resource methods are annotated with #Path and not with #AnyHttpMehtod then its a sub resource locator. I want to know when we dont have any http method annotation then will there be some default behavior.
From the documentation:
By default, the JAX-RS runtime will automatically support the methods HEAD and OPTIONS if not explicitly implemented. For HEAD, the runtime will invoke the implemented GET method, if present, and ignore the response entity, if set. For OPTIONS, the Allow response header will be set to the set of HTTP methods supported by the resource. In addition, the JAX-RS runtime will return a Web Application Definition Language (WADL) document describing the resource; see https://wadl.dev.java.net/ for more information.
source
Essentially, I have a MessageBodyWriter that writes objects as JSON, and I'd like to be able to control some aspects of the output based on which resource method handled the request. However, the default lifecycle of #Provider classes is singleton (one per JVM), so I can't inject an instance of some configuration object. This leaves me with 2 obvious workarounds:
Use custom annotations: Each call to writeTo(...) includes the list of annotations on the method that was invoked, so I could check for the existence of some annotation. However, JAX-RS methods are already pretty laden with metaprogramming.
Use a ThreadLocal property map: Assuming one request per thread, but this approach breaks encapsulation a bit. The resource methods needs to be aware that there is some other class out there, looking for this map.
Is there a way to change the lifecycle of the Provider itself? I am using Jersey.
Not sure why you need a MessageBodyWriter Provider with per-request basis. If you just want to distinguish which methods are with JSON ouput and which are not, then jersey-json does already support.
And although the #Provider is singleton. You still can use per-request object within it like below.
#Provider
public class StViewProcessor implements ViewProcessor<ST> {
......
#Context
HttpServletRequest request;
public void writeTo(ST st, Viewable viewable, OutputStream out)
throws IOException {
System.out.println(request.getRequestURI());
...
}
}
And if you want to inject your instance per request, you can have a look at PerRequestTypeInjectableProvider. Here is a link about it.
The JAX-RS 1.1 spec requires that implementations support singleton providers and allows support for other lifecycles but doesn't suggest anything else along those lines. As far as I'm aware, pure Jersey doesn't support anything beyond singletons. With the jersey-spring contrib module, you get support for using Spring as Jersey's IoC container (where it gets its resource and provider instances from). I know Spring supports multiple lifecycles, including request, but I'm not sure if support for that is built into jersey-spring.
I'm running a JAX-WS web service which is based on Apache CXF 2.3.1 on a JBoss6 server.
My service offers a function getWeight. This function should return the values in different units (kilos, pounds) depending on an additional information within the SOAP header. For that purpose I have added my own interceptor:
public class MySoapHeaderInterceptor extends AbstractSoapInterceptor
{
public MySoapHeaderInterceptor()
{
super(Phase.USER_PROTOCOL);
}
...
}
The intercepting works fine and I can parse the additional element from the SOAP header and can set up a variable based on this element:
boolean poundsRequested = true;
Now my problem occurs. I don't know how to forward the variable poundsRequested to my actual WebService implementation MyServiceImpl. This class is calling another class ValueReader where I finally need the information from the SOAP header.
I've already tried to set up a global static variable ValueReader.poundsRequested. But such a solution is not thread safe. It might happen that the calls of two clients interfere, and can overwrite each others set up variable.
To sum up: I basically need a possibility to forward a variable from an Apache CXF Interceptor to the actual webservice implementation. Moreover the value of this variable needs to be unique for each request.
In the interceptor, you can save the values that you need on the incoming message:
message.put("my.value", value);
Inside your implementation, you can do one of two things:
1) Have the standard JAXWS WebServiceContext injected via an #Resource thing and call
context.getMessageContext().get("my.value");
2) Since you are tied to CXF anyway, do:
PhaseInterceptorChain.getCurrentMessage().get("my.value");
Ideally, the format in which the weights are requested should be a part of your payload - it does not make sense for it to be a header.
You may not need an interceptor for getting hold of this header, if you are using JAX-WS(recommended with CXF), you can get to this using #WebParam annotation with header attribute set to true.