Forgive me if I am asking an obvious question (maybe I missed it in the docs somewhere?) but has anyone found a good way to organize their URLs in Jersey Java framework?
I mean organizing them centrally in your Java source code, so that you can be sure there are not two classes that refer to the same Url.
For example django has a really nice regex-based matching.
I was thinking of doing something like an enum:
enum Urls{
CARS ("cars"),
CAR_INFO ("car", "{info}");
public Urls(String path, String args)
...
}
but you can imagine that gets out of hand pretty quickly if you have urls like:
cars/1/wheels/3
where you need multiple path-ids interleaved with one another...
Any tips?
From my experiences with Jersey, when I tried to annotate two places with the same #Path, I had compilation errors and it wouldn't run. This might not always be the case, so the following might help:
You can get an application.wadl file from your Jersey app by simply requesting it from you web resource:
$ curl http://localhost:8080/application.wadl
or if you prefixed your web services under /ws/
$ curl http://localhost:8080/ws/application.wadl
The application.wadl file is an XML file that shows you all of your resources in your running application, as well as what methods you can call on a resource. See the following resource on how this file is laid out.
Well - I assume you have a #Path on each resource? This means you don't have to keep track of URLs across your entire application, rather just within each class - which is relatively easy if you annotate the interface.
Using enums won't work - you can only put contants into an annotation, but using a class holding final static String could work.
public class UrlConst {
public final static RESOURCE_MY_RESOURCE="/resource";
public final static RESOURCE_MY_RESOURCE2="/resource";
public final static OP_GET_ALL="/";
public final static OP_GET_BY_ID="/{id}";
}
#Path(UrlConst.RESOURCE_MY_RESOURCE)
public interface MyResource {
#GET
#Path(UrlConst.OP_GET_ALL)
#Produces(MediaType.APPLICATION_XML)
public ObjectList getAll();
#GET
#Path(UrlConst.OP_GET_BY_ID)
#Produces(MediaType.APPLICATION_XML)
public Object get(#PathParam("id") int id);
}
#Path(UrlConst.RESOURCE_MY_RESOURCE2)
public interface MyResource2 {
#GET
#Path(UrlConst.OP_GET_ALL)
#Produces(MediaType.APPLICATION_XML)
public ObjectList getAll();
#GET
#Path(UrlConst.OP_GET_BY_ID)
#Produces(MediaType.APPLICATION_XML)
public Object get(#PathParam("id") int id);
}
etc.
Related
I try to do something strange may be. My vision:
I need a standard architecture with controllers, services and other layers.
I need clients for my controllers that I can distrubute separate.
And I wrote something like this:
module-api
module-impl
Module-api contains only OpenFeign clients like:
#FeignClient(path = TopLevelClient.ROOT_PATH)
public interface TopLevelClient implements CommonInterfaceForClient<EntityDto> {
String ROOT_PATH = "/entity";
#GetMapping
ResponseEntity<EntityDto> getAll();
}
Module-impl contains controllers and other logic like:
#RestController
#RequestMapping(TopLevelClient.ROOT_PATH)
public class TopLevelController implements TopLevelClient {
String ROOT_PATH = "/entity";
#Override
#GetMapping
ResponseEntity<List<EntityDto>> getAll() {...}
}
And of course I have a some strange common parametrized interace like this:
CommonInterfaceForClient
Okay, that's all right. But it's ok only for an one level REST path. I mean
/entity/{id}
But I need to request sub level:
/entitiy/{id}/sub-entity/{subId}
And I can image how I have to do this. I can't implements two interfaces at once cause first interface parametrized with an other DTO. I can't use method for calculate a mapping path cause a value must be a constant.
I mean I want to do something like this:
#FeignClient(path = SubLevelClient.ROOT_PATH)
public class SubLevelClient implements ... {
String ROOT_PATH = "/entity/{entityId}/sub-entity";
#GetMapping
ResponseEntity<List<SubEntityDto>> getAll(#PathVariable long entityId);
}
May be you can tell me something useful or may be something from the best practice?
I just want to take few common interfaces, services and controllers/clients for common actions but I want to write with one's own hands. Or may be it's a stupid idea and you can tell me a turnkey solution.
This is one of those topics I don't even know how to search in google (tried already, most of the results were for C#), so here I go:
I'm messing around with our huge application, trying to get to work a brand new DAO/Entity/Service/DTO.. euh...thing. I've been left more or less on my own, and, again, more or less, I'm getting to understand some of the hows and maybe one or two of the whys.
The thing is that I got all, the way "up", from the DB to the Service:
I got a DAO class which executes a query stored on an Entity class. After executing it, it returns the Entity with the values.
The service receives the Entity and, somehow, transforms the Entity to a DTO and returns it to whenever is needed.
My problem is with the "somehow" thing the code goes like this:
DTOClass dto = ClassTransformerFromEntityToDTO.INSTANCE.apply(entityQueryResult);
I went into ClassTransformerFromEntityToDTO and found this:
public enum ClassTransfomerFromEntityToDTO implements Function<EntityClass,DTO Class> ) {
INSTANCE;
#Override
public DTOClass apply(EntityClass entityInstance) {
/*Code to transform the Entity to DTO and the return*/
}
}
The class that this... thing, implements, is this:
package com. google .common . base;
import com. google .common . annotations. GwtCompatible ;
import javax. annotation .Nullable ;
#GwtCompatible
public abstract interface Function <F , T >
{
#Nullable
public abstract T apply (#Nullable F paramF) ;
public abstract boolean equals (#Nullable Object paramObject) ;
}
I'm in the classic "everyone who where at the beginning of the project fled", and no one knows why is this or what is this (The wisest one told me that maybe it had something to do with Spring), so, I have two main questions (which can be more or less answered in the same side):
1) What's this? What's the point of using an enum with a function to make a conversion?
2) What's the point of this? Why can I just make a class with a single function and forget about this wizardry?
not sure there's much to answer here... And I'm adding an answer to illustrate my thoughts with some code I've seen, but that you have is horrible. I've actually seem similar stuff. My guess is that that codes actually precedes Spring. It's used as some sort of Singleton.
I have seen code like this, which is worse:
public interface DTO {
find(Object args)
}
public class ConcreteDTO1 implements DTO {
...
}
public class ConcreteDTO2 implements DTO {
...
}
public enum DTOType {
CONCRETE_DTO1(new ConcreteDTO1(someArgs)),
CONCRETE_DTO2(new ConcreteDTO2(someOtherArgs))
private DTO dto;
public DTOType(DTO dto) {
this.dto = dto;
}
public DTO dto() {
return dto;
}
}
and then the DTOs are basically accessed through the Enum Type:
DTOType.CONCRETE_DTO1.dto().find(args);
So everyone trying to get hold of a DTO accesses it through the enum. With Spring, you don't need any of that. The IoC container is meant to avoid this kind of nonsense, that's why my guess is that it precedes Spring, from some ancient version of the app when Spring was not there. But it could be that someone was wired to do such things regardless of whether Spring was already in the app or not.
For that kind of stuff you're trying to do, you're better of with the Visitor pattern. Here's an example from a different answer: passing different type of objects dynamically on same method
It's me. From the future.
Turns out that this construct is a propossed Singleton Implementation, at least on "Effective Java 2nd edition".
So, yeah, Ulise's guess was well oriented.
I'm implementing a RESTful service application for TomEE Plus 1.7.1 with Jettison as default json provider. I have several facade classes for my entitiy classes to provide CRUD functionalities for each of them. Service facades have been generated by netbeans.
This is the POST method:
#POST
public void create(Course entity) {
super.create(entity);
}
While using this method (to create a new instance in the database) I got following error:
No message body reader has been found for request class Object, ContentType : application/json.
After several hours of trying, I got it to work: I only had to add another parameter to the method, like that:
#POST
public void create(#Context Context uriInfo, Course entity) {
super.create(entity);
}
I don't understand why I had to add this Context parameter. I don't need the context variable, so actually I would like to remove it...
Does anybody know the reason?
Okay, I think I found the solution:
All my rest services have been implemented as facade classes. The abstract facade (super class of all services) has several methods like:
public void create(T entity) { getEntityManager().persist(entity); }
public void edit(T entity) {getEntityManager().merge(entity);}
These methods are used by the facade classes:
public void create(Course entity) {
super.create(entity);
}
public void edit(#PathParam("id") Integer id, Course entity) {
super.edit(entity);
}
(for better viewing I've removed the annotations here)
The difference between these two methods is, that the edit method has a second parameter "id" and so does not override the edit() method of the super class. But the create() method does only have a single parameter which causes override of the super class method "create()". I don't know why, but cxf is now creating two endpoints:
POST http://localhost:8080/webprog/api/course/ -> void create(Course)
POST http://localhost:8080/webprog/api/course/ -> void create(Object)
This is also the reason why I got it working with a secon parameter: The create() method is not getting overriden anymore.
So what i did now, is simply renaming the method in de super class, to not override them in the facade classes.
by the way: all services classes have been created by netbeans generator... maybe there is a bug in it
Here are some of the pointers
Make sure you have jettison jar in your classpath, CXF automatically registers jettison as json provider.
#Context Context is not mandatory, so if you want to access some context parameters you can add.
For Method create add Media Type #Consumes(MediaType.APPLICATION_JSON)
Finally Check why you are getting No message body reader has been found for request class Object Ideally you should have got No message body reader has been found for request class Course(There might be some issues with your class definations)
here is my code :
this is my application class >>>
import org.restlet.Application;
import org.restlet.Restlet;
import org.restlet.routing.Router;
import firstSteps.UserResource;
public class FirstStepsApplication extends Application {
#Override
public synchronized Restlet createRoot() {
Router router = new Router(getContext());
router.attach("/hello", UserResource.class);
router.attach("/isuserloggedin",UserResource.class);
return router;
}
}
this is resource class >>>
import org.restlet.resource.Get;
import org.restlet.resource.ServerResource;
/**
* Resource which has only one representation.
*
*/
public class UserResource extends ServerResource {
#Get
public String userLogin() {
return "This is userLogin method";
}
#Get
public boolean isUserLoggedIn(){
return false;
}
}
/hello & /isuserloggedin are mapped to same to resource class but
what i want is : when there is /hello then userLogin method should be called
and when there is /isuserloggedin then isUserLoggedIn must be called .
is this possible ??
or am i going wrong?
if this is not possible then any one can tell me any other alternative ?
In Restlet 2.1 (try M7 or above), it is possible to dispatch two HTTP GET calls to two Java methods in the same resource class. This is done by leveraging query parameters like this:
import org.restlet.resource.Get;
import org.restlet.resource.ServerResource;
/**
* Resource which has only one representation.
*
*/
public class UserResource extends ServerResource {
#Get
public String userLogin() {
return "This is userLogin method";
}
#Get("?loggedIn")
public boolean isUserLoggedIn(){
return false;
}
}
However, as pointed already, you would be better off using a separate resource class.
Some time has passed since my last experience with Restlet, anyway, if you are implementing a fully REST API, I would expect the two to be separate resources if they really need to be. Otherwise, a resource should be mapped to exactly one representation, IMHO.
What is the benefit of having two URIs mapped to one resource class, instead of having two, each implementing the GET method? It seems to add a bit of ambiguity there, with no benefit.
I would return the status (logged or not) information in the user representation.
Now, for sake of completeness, I find a bit difficult to understand your API semantics: can I ask for the logged status of any user, or just mine? It's not very clear, but I understand that it was not the main point.
Just as a nice reading, you may want to have a look at some popular REST api to see how they manage issues similar to yours, ie. I like Github Users' API particularly.
Hope it helps.
What are the recommended approaches for generating routes in a java-based Spring MVC webapp? I'd like to avoid hard-coding paths throughout the application.
Assuming we are talking about paths RequestMappings etc.
In my application I have a single class with with a bunch of public static final constants that I reference in the #RequestMapping annotations.
So the constants might look like this:
public class Pages {
public static final String FOO_URL "foo/foo.action"
public static final String FOO_VIEW "test/foo"
public static final String BAR_URL "bar/bar.action"
public static final String BAR_VIEW "test/bar"
}
then inside your controller you'd reference them like this:
#RequestMapping(value=Pages.FOO_URL, method=RequestMethod.GET)
public String handleFoo(Model model) {
return Pages.FOO_VIEW;
}
They're easy to change as they're all in one place.
You say you'd like to avoid hard-coding paths throughout the application, but typically all the controllers (and thus all the url mappings) reside in one directory. For example if you have a maven structure they'll be someplace like src/main/java/com/mycompany/myapp/web/controllers/. Do you envision yourself ever asking the question, "Just where did I put the url mapping for the /myapp/v1/search endpoint?", and not being able to figure out that it's in /src/main/java/com/mycompany/myapp/web/controllers/V1SearchController.java?
Also once you choose the urls they're pretty much fixed since they represent an interface with clients, and changing them probably means breaking backward compatibility.
Not that I think a class with a bunch of static final Strings is all that bad, I just think it's mostly unnecessary.