Handling Dot (.) Parameters in Java Jersey - java

I want to format my REST interface as follows:
myurl.com/resources/{resourceId}
I optionally want people to be able to provide the following variations to specify return formats:
myurl.com/resources.json/{resourceId}
I am using Jersey to provide my REST services. What is the best way to handle these parameters?
Should a create a separate class with a different #PATH notation, or can I have a single class and parse out that parameter? Are there any built in annotations that might handle this, similar to #PathParam or #QueryParam?

There already is a mechanism for this (as #digitaljoel already stated) - HTTP Accept header.
Jersey doesn't have any direct support for your usecase, but there is something similar - media type mapping feature, see
http://jersey.java.net/nonav/apidocs/1.12/jersey/com/sun/jersey/api/core/ResourceConfig.html#PROPERTY_MEDIA_TYPE_MAPPINGS
and
http://jersey.java.net/nonav/apidocs/1.12/jersey/com/sun/jersey/api/core/ResourceConfig.html#getMediaTypeMappings%28%29
Unfortunately for you it handles only URLs which have this "param" at the end, but it should not be very hard to take UriConnegFilter sources (http://java.net/projects/jersey/sources/svn/content/trunk/jersey/jersey-server/src/main/java/com/sun/jersey/api/container/filter/UriConnegFilter.java?rev=5698) and modify it to suit your needs.

Related

Is there a way to use Google's Custom Methods with Jersey Resources?

I was looking for a way to make my JAX-RS APIs more readable and came across with Google's Custom Methods approach:
https://cloud.google.com/apis/design/custom_methods
I was looking for this because some of my entities perform more actions than I could express with traditional HTTP verbs. Google pattern is to use a colon (:) at the end of the URI, separating the entity/collection from the desired action.
I tried to apply this pattern to a simple Jersey resource, just to test how it could be done. I've got a resource class StudentDetailsResource annotated with #Path("students/{studentId}") and a few methods also annotated with #Path.
If my method has another entity before the custom method, then all is ok. Let's say the enrol method is annotated with
#Path("subjects/{subjectId}:enroll").
The problem rises when the action is right after the Resource Class URI, because #Path uses a URI Template that prefixWithSlash all sub-resources. So if I have a dropout method, the annotation would look like #Path(":dropout"), but the URI template would become /students/{studentId}/:dropout, an this /: would break in the matching phase.
I have read about Jersey Providers and ResourceDelegates, but I couldn't find a way to replace the URI Template default action of prefixWithSlash.
The question is: how can I apply Google's custom method approach or how can I avoid the default prefixWithSlash behaviour with Jersey?
Note: I know this is a silly example and there are other ways to solve this specific case, but I have more complex cases which can benefit from the custom methods.

Swagger API integration for non standard Java technology

We have a system that uses http POST with JSON as an RPC method.
It is an in house solution for internal components communication.
The requests and responses are described each by a Java bean (POJO).
My question is, how can I use swagger annotations to create nice documentation in the swagger standard?
I am not afraid from messing around with existing code, but I was wondering if anyone has some experience with something similar.
The goal is to use Swagger UI to display nice docs and give a playground for users to invoke the Apis.
Based on the comments above, it's impossible to describe this sort of API using Swagger. The Swagger specification is intended to REST-based APIs, where the URLs serve as a unique endpoints to describe an operation, and not the payloads.
By definition, Swagger considers a unique operation to be the combination of a URL and the HTTP method (there are requests to expand the definition to include the mime type as well, for example, but it is not currently available).
There is simply no way to describe a single endpoint that operates multiple requests types, each having its own output.
There may be a solution for what you request in the future, but it is not in the near future, not will it answer your requirements to the fullest.
To be clear - this is not an issue of messing around with code or anything. The specification itself doesn't support it.
There are 2 simple tweaks required to make a swagger file work for any generic hand-built RPC application.
The first tweak is to make the swagger endpoints appear to be unique. This is done by defining each endpoint with a unique name after a hash in the context. This works because your app will not process the url past the '#' and this allows swagger to consider the path to be "unique". In reality though this technique will allow every unique path defined in the swagger file to actually invoke the same endpoint.
paths:
/endpoint#myUniqueCommandA
...
/endpoint#myUniqueCommandB
...
The other tweak is needed to ensure the generated swagger clients will actually call the correct operation inside your RPC app. This is done by implementing a "defaulted single value" enum in each command's request object. The defined enum represents the corresponding attribute / value combo the api needs to pass to get dispatched to the right target action inside your application:
...
definitions:
MyUniqueCommandARequest:
type: object
properties:
rest_call:
type: string
enum:
- myUniqueCommandA
default: myUniqueCommandA
...
MyUniqueCommandBRequest:
type: object
properties:
rest_call:
type: string
enum:
- myUniqueCommandB
default: myUniqueCommandB
...
In the above example, the property "rest_call" is what my underlying system uses to dispatch the request to the right underlying operation.
The request object for myUniqueCommandA has its rest_call attribute defined as enum["myUniqueCommandA"]. The request object for myUniqueCommandB has its rest_call attribute defined as enum["myUniqueCommandB"].
Since these are defined as a single value enums that are also defaulted to that same value, the generated swagger classes that calls these apis will be wired to pass their correct routing value automatically.

Java's Jersey, RESTful API, and JSONP

This must have been answered previously, but my Google powers are off today and I have been struggling with this for a bit. We are migrating from an old PHP base to a Jersey-based JVM stack, which will ultimately provide a JSON-based RESTful API that can be consumed from many applications. Things have been really good so far and we love the easy POJO-to-JSON conversion. However, we are dealing with difficulties in Cross-Domain JSON requests. We essentially have all of our responses returning JSON (using #Produces("application/json") and the com.sun.jersey.api.json.POJOMappingFeature set to true) but for JSONP support we need to change our methods to return an instance of JSONWithPadding. This of course also requires us to add a #QueryParam("callback") parameter to each method, which will essentially duplicate our efforts, causing two methods to be needed to respond with the same data depending on whether or not there is a callback parameter in the request. Obviously, this is not what we want.
So we essentially have tried a couple different options. Being relatively new to Jersey, I am sure this problem has been solved. I read from a few places that I could write a request filter or I could extend the JSON Provider. My ideal solution is to have no impact on our data or logic layers and instead have some code that says "if there is a call back parameter, surround the JSON with the callback, otherwise just return the JSON". A solution was found here:
http://jersey.576304.n2.nabble.com/JsonP-without-using-JSONWithPadding-td7015082.html
However, that solution extends the Jackson JSON object, not the default JSON provider.
What are the best practices? If I am on the right track, what is class for the default JSON filter that I can extend? Is there any additional configuration needed? Am I completely off track?
If all your resource methods return JSONWithPadding object, then Jersey automatically figures out if it should return JSON (i.e. just the object wrapped by it) or the callback as well based on the requested media type - i.e. if the media type requested by the client is any of application/javascript, application/x-javascript, text/ecmascript, application/ecmascript or text/jscript, then Jersey returns the object wrapped by the callback. If the requested media type is application/json, Jersey returns the JSON object (i.e. does not wrap it with the callback). So, one way to make this work is to make your resource method produce all the above media types (including application/json), always return JSONWithPadding and let Jersey figure out what to do.
If this does not work for you, let us know why it does not cover your use case (at users at jersey.java.net). Anyway, in that case you can use ContainerRequest/ResponseFilters. In the request filter you can modify the request headers any way you want (e.g. adjust the accept header) to ensure it matches the right resource method. Then in the response filter you can wrap the response entity using the JSONWithPadding depending on whether the callback query param is available and adjust the content type header.
So what I ultimately ended up doing (before Martin's great response came in) was creating a Filter and a ResponseWrapper that intercepted the output. The basis for the code is at http://docs.oracle.com/cd/B31017_01/web.1013/b28959/filters.htm
Essentially, the filter checks to see if the callback parameter exists. If it does, it prepends the callback to the outputted JSON and appends the ) at the end. This works great for us in our testing, although it has not been hardened yet. While I would have loved for Jersey to be able to handle it automatically, I could not get it to work with jQuery correctly (probably something on my side, not a problem with Jersey). We have pre-existing jQuery calls and we are changing the URLs to look at the new Jersey Server and we really didn't want to go into each $.ajax call to change any headers or content types in the calls if we didn't have to.
Aside from the small issue, Jersey has been great to work with!

Replacement for <servlet-mapping> in web.xml & Spring MVC

Because my URLs are really complex and each of the parts between the slashes depends on the content of my database, I suppose the is not sufficient for me. I suppose I need to write some URL parser, which goes through the url parts between the slash and calls some kind of handler.
Is there a way how to write such URL parser, which would get string and return an object, representing the current request, that would replace the ? I only managed to find simple tutorials which use only the url-routing defined by web.xml.
Thanks
Spring is extremely flexible, so you can customize URL parsing. Take a look on this tutorial http://static.springsource.org/spring/docs/3.0.0.M3/spring-framework-reference/html/ch16s11.html, pay attention on DefaultAnnotationHandlerMapping and AnnotationMethodHandlerAdapter. It seems you should study how do they work and override some of the functionality.
But before you are starting, think again. Do you really need this and #RequestMapping does not satisfy you? Really, you can use path variable {myvar} into the URL pattern definition. The variables may be of different types including enums. I used this and found very convenient. You can for example create enum MyType ONE, TWO; define abstract method on enum level and override it for each element. Then you can use path variable of type MyType into the request mapping and call this method directly from the method marked with #RequesteMapping annotation.

Java Restlets - Match arbitrarily long URI path parameter

Using Restlets you can route URIs using a system based on the URI template specification. I want to be able to route URIs which match the following pattern
http://www.blah.com/something/...arbitrarily long path.../somethingelse/
So, the following two URIs would be matched and routed the same:
http://www.blah.com/something/a/b/c/d/somethingelse/
and:
http://www.blah.com/something/z/y/x/w/v/somethingelse/
How can I achieve this using Restlets?
Cheers,
Pete
The most common way to set up routes is with a Router, like so:
router.attach("/path/to/resource", MyResource.class);
'attach' returns a Route, which has the method setMatchingMode, so you can do this:
router.attach("/path/to/resource", MyResource.class).setMatchingMode(Template.MODE_STARTS_WITH);
This sets the route to match any URL which starts with the supplied pattern.
I hope that's sufficient for your needs. I'm not aware of any built-in way to match URLs with a particular prefix and a particular suffix. But if that's specifically what you need, you could probably implement your own subclass of Template, Route, etc (I'm not sure which would be needed.)
I'm pretty sure that regex-based routing has been discussed on the Restlet mailing list; you may want to search there.

Categories

Resources