Is posible accept all kind of resources in Restful Jersey web service? - java

Is there any way to accept and handle any resource, i.e.
I want to handle myappname/xxx where xxx could be anything, and how could I handle?
Note: I already know is posible create any class and then bind a resource to a class, but I don't want it. I want a one universal class that handles every resource.

I don't know Jersey well, but as it implements JAX-RS I expexted that would work (not tested):
#Path("/myappname")
public class CatchItAll {
#GET
#Path("/{anyThing:.*}")
public String catch(#PathParam("anyThing") String anyThing) {
}
}
It uses the regular expression feature.

Related

Is there a way to define queryparams for all endpoints in javax.ws.rs?

I am trying to document an already existing application using javax.ws.rs annotations to define what headers (#HeaderParam) and parameters (#QueryParam) a specific endpoint needs. This information would them be used to generate a swagger page for the application.
public Response SampleFunction(#RequestBody(...),
#QueryParam(...),
#HeaderParam(...),
#HeaderParam(...),
#HeaderParam(...),
etc etc etc){
return doStuff()
}
I have identified a set of "#HeaderParam" which are required for all endpoints.
I need to know if there is any way for me to define the #HeaderParam only once and use that definition for all endpoints and, since this is an already existing application, I need to do this change without any major code refactorization.
We believe to have found a solution for this matter.
By declaring the #HeaderParam globally they appear for all endpoints without having to repeat the declaration for each endpoint.
Something like this:
#Path("/")
public class myClass{
#HeaderParam("Parameter_one")
#Parameter(example = "example_one)
Type parameter_one
#HeaderParam("Parameter_two")
#Parameter(example = "example_two)
Type parameter_two
public Response SampleFunction(#RequestBody(...),
etc etc etc){
return doStuff()
}
}
In this particular case, Parameter_one and Parameter_two will become available on the Swagger page for all endpoints.

How is Jersey framework implement JAX-RS API in REST?

I know there are a lot of answers on this questions , but i am still confused about difference between JAX-RS API(the specification), and Jersey framework( reference implementation).
I read that:
Jersey framework basically uses com.sun.jersey.spi.container.servlet.ServletContainer servlet to intercept all the incoming requests. As we configure in our projects web.xml, that all the incoming rest request should be handled by that servlet. There is an init-param that is configured with the jersey servlet to find your REST service classes. REST service classes are not Servlet and they need NOT to extend the HttpServlet as you did in your code. These REST service classes are simple POJOs annotated to tell the jersey framework about different properties such as path, consumes, produces etc. When you return from your service method, jersey takes care of marshalling those objects in the defined 'PRODUCES' responseType and write it on the client stream
My question is when you say :" jersey takes care of marshalling those objects in the defined 'PRODUCES' responseType and write it on the client stream", what you mean by jersey , what is actual class or library that handles objects .
I am confused when i read that jersey is the engine that handles JAX-RS API specification. Can someone please explain what exactly is behind word jersey in this sentence? What actual class from Jersey do do the job of processing requests and responses in Jersey?
The concept of specification and implementation is really pretty basic software engineering concepts. Your specification is the high level design. To help understand, I just came up with a really simple example.
Say I want to have a parsing library. I know how I want to be able to use it. The only problem is that I am not very good at writing parsing code. So I create a high level specification, and I outsource the implementation. Here are the three classes that are part of the spec. They are all contained in one "API jar", say myparsers-api.jar
public interface Parser {
String[] parse(String s);
}
public interface ParserFactory {
Parser getBySpaceParser();
Parser getByCommaParser();
}
public class ParserDepot {
private static ServiceLoader<ParserFactory> loader
= ServiceLoader.load(ParserFactory.class);
public static ParserFactory getDefaultParserFactory() {
final List<ParserFactory> factories = new ArrayList<>();
loader.forEach(factories::add);
if (factories.isEmpty()) {
throw new IllegalStateException("No ParserFactory found");
}
return factories.get(0);
}
}
So at this point, I can actually code against this jar. If I were to uses it as is right now in another project, the project would compile just fine.
ParserFactory factory = ParserDepot.getDefaultParserFactory();
Parser parser = factory.getBySpaceParser();
String[] tokens = parser.parse("Hello World");
System.out.println(Arrays.toString(tokens));
So even though there is no implementation of this specification, I can still code against it, and compile against it. But when I try to actually run the program, it won't work, as there is no implementation. You can try to run this code, and you will get an IllegalStateException (see the docs for ServiceLoader if you're unfamiliar with this pattern).
So I outsource the implementation to say a company called Stack Overflow. They get my myparsers-api.jar and they need to give me back an implementation. They would need to implement a ParserFactory, and a couple of Parsers. They might look something like this
public class SoByCommaParser implements Parser {
#Override
public String[] parse(String s) {
return s.split("\\s+,\\s+");
}
}
public class SoBySpaceParser implements Parser {
#Override
public String[] parse(String s) {
return s.split("\\s+");
}
}
public class SoParserFactory implements ParserFactory {
#Override
public Parser getBySpaceParser() {
return new SoBySpaceParser();
}
#Override
public Parser getByCommaParser() {
return new SoByCommaParser();
}
}
Now Stack Overflow gives me back a jar (say so-myparsers-impl.jar) with these three classes and the required META-INF/services file (per the ServiceLoader pattern), and now when I add the so-myparsers-impl.jar to my project and try to run it again, the program now works, because now it has an implementation.
This is exactly how the JAX-RS spec works. It only defines the high level design of how it should work. The classes, interfaces, and annotations that are part of that design are placed in an "API jar" just like my high level parsers are put into a jar. Implementations cannot alter these classes. All the classes that are part of the JAX-RS specification (version 2.x) are put into one single jar javax.ws.rs-api. You can code against that jar, and your code will compile just fine. But there is nothing to make it "work".
You check out both the written specification and the classes defined by the specification and you will notice that the only classes included in the source code are those mentioned in the specification. But what you should notice is that the written specification doesn't mention anything at all about how it is supposed to be implementation. Take for example the following code
#Path("/test")
public class TestResource {
#GET
public String get() {
return "Testing";
}
}
#ApplicationPath("/api")
public class MyApplication extends Application {
#Override
public Set<Class<?>> getClasses() {
Set<Class<?>> classes = new HashSet<>();
classes.add(TestResource.class);
return classes;
}
}
Now the specification states that this is all we need to run a JAX-RS application in a servlet container. And that's all it says. It says nothing about how it all supposed to work. This is just how it is designed to work.
So what, is there some magic voodoo in Java that we don't know about that will make this Application class start a server, and some hocus pocus that will make a #Path annotated class automatically accept requests. No. Some body needs to provide the engine. The engine might be 20,000 lines of code just to make the above code work as specified.
That being said, Jersey is just the name of an implementation. It's like when I outsourced my parser implementation to Stack Overflow; The name Jersey itself is just the name of the project, just like Hadoop is a name of the project. In this case, what the project is, is an implementation of the JAX-RS specification. And because JAX-RS is just a specification, it means that anyone can implement it. If you wanted to, you could write your own implementation. As long as it works how it is defined to work in the written specification, then you can say that your code is an implementation of JAX-RS. There's more than just Jersey out there; you also have RESTEasy, which is another implementation.
As far as how Jersey implements the engine, that is way too broad. What I can do, is give you a high level overview of what happens behinds the scenes.
A JAX-RS application is defined to run inside of a servlet container. If you understand servlet containers and the servlet spec, then you'll know that the only way to handle requests is either by writing a HttpServlet or Filter. So if you want to implement JAX-RS then you need to able to handle requests either through a HttpServlet or a Filter. The ServletContainer you mentioned, is actually both. So for Jersey, this is the "entry point" into the Jersey application, as far as request processing is concerned. It can be configured in a number of ways (I've leave that research to you).
And if you understand how to write your own servlet, then you know all you get is an HttpServletRequest and HttpServletResponse. You need to figure out what to do from there; get request info from the request, and send response info back out in the response. Jersey handles all of this.
If you really want to get into the gory details of what is going on under the hood, you will just need to to dig into the source code, starting from the entry point, the ServletContainer. Be prepared to spend months on this to get a really good understanding of how it all works. It's not something that can be explained in one Stack Overflow post, if that's what you're expecting.
You already pointed that JAX-RS is a specification and Jersey is the implementation which is how is Java especially Java EE work, maybe this article can explain more better.
To summarize JAX-RS is just a specification, there is no real implementation. The real implementation was done by Jersey and other library that following JAX-RS specification.

RESTEasy: How to fall back to other matching resource methods?

In a RESTEasy application I need to determine at runtime if a certain path can be handled by a specific resource method, based on it's path/query parameters. If it can't be handled I want the request to fallback to other methods. E.g.:
#Path("/")
class MyResource {
#GET
#Path("{path : .*}")
public Response handleRedirects(#PathParam("path") String path) {
if (hasRedirectFor(path)) {
return redirectTo(path);
}
else {
//somehow pretend that this method didn't exist and fallback to the next best match
}
}
#GET
#Path("img/{image}")
public Response handleImage(#PathParam("image") String someParam) {
return createImageResponse(image);
}
#GET
#Path("{template : .*\\.html}")
public Response handleTemplate(#PathParam("template") String template) {
return createTemplateResponse(template);
}
}
Is this somehow possible, without having to use a RequestFilter? (I don't want to use a RequestFilter since then I need to implement URL matching for handleSometimes myself).
EDIT: The comments requested to provide more details, so I changed the example to match closer to my real world situation. I have a typical webserver that handles all sorts of requests, in the above example I reduced that to just images and templates. For legacy reasons there are some incoming links from 3rd parties to URLs that don't (or no longer) exists, but which we don't want to break. We therefore want to serve redirects on those URLs, which is what the handleRedirects function is supposed to do.
Unfortunately there is overlap in the patterns for legacy and supported urls, which prevents me from writing #Path annotations to statically route to the correct method. Moreover, I only know if I can actually generate a redirect from legacy -> new when I examine the path at runtime, if this fails I want to fall back to the other methods. I therefore want to be able to determine in the method itself whether I can handle the request or not, and let RESTEasy fallback to the next matching resource if it can't. Usually this is something were filters would come in handy, but then I loose the ability to automatically extract path parameters or to route to different methods, which I really like to keep.

How do I support localization with Jersey?

I am designing a REST API that I would like to be localizable in the future.
Therefore I am defining the URLs to be of the form
/en/<resource_url>
With the intention of being able to support
/fr/<resource_url>
In the future if need be.
However I only want to define each resource url service once. Therefore I figure I need to get the URL parsed and rewritten without the language piece of the URL before it is matched to services. Finally that language should be made available to the services somehow for them to localize if necessary.
How can I achieve this?
I am using Jersey 1.17 inside Jetty container embedded in a larger server process.
You can make the /en/ or the /fr/ part a variable. Then set your locale to the value of the variable. Here's an example:
#Path("/{locale}/username")
public class UserResource {
#GET
#Produces("text/xml")
public String getUser(#PathParam("locale") String locale) {
...
}
}
But that may not be the best way to go about it. After answering, I found this other SO question that is a better way to solve the problem: Getting the client locale in a jersey request With this way, you don't need to add this to the URL. Just make the client set a header.

How to expose services written in Java thru REST as well as locally?

I want to create a new system that will be built completely using services. I want to expose these services thru REST for client applications. But for performance reasons, I also want to make sure that other services can call a given service using local calls without paying the penalty of a remote call. Is there a framework that can help me do that.
Well, the way we have implemented this is by using something like Spring MVC where the controller just calls out to a Service class - our notion of Model. The Controller thus acts as "exposing the services" as RESTful services. The rest of the codebase accesses these Services just like any other object. Since we use spring, we leverage the IOC massively.
For example, we would have something like:
public class BillingService {
public void doSomething(String someParam) {}
}
public class BillingController {
#Autowired private BillingService billingService;
public void doSomething(#RequestParam String someParam) {
billingService.doSomething(someParam);
}
}
In the above examples, the annotations are all from Spring, but you get the picture. Any other class which wants to access the BillingService method, they can do so just by accessing that class's method.
I am not sure of any framework which is targeted at exactly this problem, but my guess is, you do not need one.

Categories

Resources