My problem concerns the creation of a custom method within an action. I'm using Struts2 and REST Plugin in order to implement a RESTful WebService. My action class is the following:
public class SampleController implements ModelDriven<Object> {
private Sample sample = new Sample();
private Collection<Sample> list;
private int id;
public HttpHeaders create() {
sdao.save(sample);
return new DefaultHttpHeaders("create");
}
public HttpHeaders destroy() {
return new DefaultHttpHeaders("destroy");
}
public HttpHeaders show() {
return new DefaultHttpHeaders("show").disableCaching();
}
public HttpHeaders update() {
sdao.save(sample);
return new DefaultHttpHeaders("update");
}
public HttpHeaders index() {
list = sdao.findAll();
return new DefaultHttpHeaders("index").disableCaching();
}
public Object getModel() {
return (list != null ? list : sample);
}
public int getId() {
return id;
}
public void setId(Integer id) {
if (id != null) {
this.sample = (Sample) sdao.findById(id);
}
this.id = id;
}
}
I can access to a resource via a GET HTTP method correctly. In order to use a custom method, called by passing a parameter to search resources i.e
public searchBySenderName(String senderName) {
list.addAll(sdao.findBySenderName(senderName))
}
What is the correct procedures? How can I call it via GET following URL?
You can call custom method from any of the predefined methods for GET (index, show) in your case, see RESTful URL mapping logic .
RESTful URL Mapping Logic
This Restful action mapper enforces Ruby-On-Rails REST-style mappings.
If the method is not specified (via '!' or 'method:' prefix), the
method is "guessed" at using REST-style conventions that examine the
URL and the HTTP method. Special care has been given to ensure this
mapper works correctly with the codebehind plugin so that XML
configuration is unnecessary.
Of course you can change the method names used by the action mapper, but it will affect a whole application. If you already occupied a resource URL then you should use another to perform its job. This is in case if you are using a strict rest mapper. In the mixed mode you can map an usual action to some action method.
REST and non-RESTful URL's Together Configuration
If you want to keep using some non-RESTful URL's alongside your REST
stuff, then you'll have to provide for a configuration that utilizes
to mappers.
Plugins contain their own configuration. If you look in the Rest
plugin jar, you'll see the struts-plugin.xml and in that you'll see
some configuration settings made by the plugin. Often, the plugin just
sets things the way it wants them. You may frequently need to override
those settings in your own struts.xml.
And last, you mightn't specify a method via ! or method: prefix because it's restricted by default configuration.
Related
I new to spring boot application development. I using service layer in my application, but came across the repository method that return Optional as shown below.
#Override
public Questionnaire getQuestionnaireById(Long questionnaireId) {
Questionnaire returnedQuestionnaire = null;
Optional<Questionnaire> questionnaireOptional = questionnaireRepository.findById(questionnaireId);
if(questionnaireOptional.isPresent()) {
returnedQuestionnaire = questionnaireOptional.get();
}
return returnedQuestionnaire;
}
My question is ,
whether I am using the Optional correctly here. And is it ok to check this optional (isPresent()) in the RestController and throughing exception is not present.Like below
public Optional<Questionnaire> getQuestionnaireById(Long questionnaireId) {
return questionnaireRepository.findById(questionnaireId);
}
I wouldn't go for either option tbh, especially not the first. You don't want to introduce null values inside your domain. Your domain should stay as simple as possible, readable and void of clutter like null checks.
You might want to read through the optional API for all your options, but personally I would go for something like this:
In repository:
public interface TodoBoardRepository {
Optional<Questionnaire> findByQuestionnaireId(String questionnaireId);
// ...
}
In service:
#Service
#RequiredArgsConstructor // Or generate constructor if you're not using Lombok
public class QuestionnaireService {
private final QuestionnaireRepository questionnaireRepository;
// ...
public Questionnaire getQuestionnaireById(Long questionnaireId) {
Questionnaire questionnaire = questionnaireRepository.findById(questionnaireId)
.orElseThrow(() -> new QuestionaireNotFoundException(questionnaireId));
// Do whatever you want to do with the Questionnaire...
return questionnaire;
}
}
I go with way 1 that you have mentioned. In case the object is not present, throw a validation exception or something. This approach also ensures that service layer is in charge of the logic and controller is just used your interacting with the outside world.
We are using Guice in our project for DI. Currently we have some configurations(properties) that we load a t server startup from a file. These are then bound to all the components & used for all the requests.
But now, we have multiple property files & load them at startup. These configurations can be different per REST(Jersey) request as they depend on the input.
So, we need to bind these configurations dynamically for each request. I looked into Guice API for #RequestScoped, but did not find anything specificallyu helpful.
There are few questions similar to this, but no luck yet. Can you please help me with this.
I'm providing 2 ways of doing this and both are request scoped.
Using HttpServletRequest, for classes where you can Inject request object.
Using ThreadLocal, Generic way. It can be used in any class.
(NOTE: This method wouldn't work if your creating new threads in your code and want to access the value. In which case you'll have to pass the values through Objects to those threads)
I meant something like this:
public class RequestFilter implements ContainerRequestFilter {
#Context
private HttpServletRequest request;
#Override
public void filter(ContainerRequestContext requestContext) throws IOException {
List listOfConfig = //load Config;
request.setAttribute("LOADED_CONFIG",listOfConfig);
// If you want to access this value at some place where Request object cannot be injected (like in service layers, etc.) Then use below ThreadLocals.
ThreadLocalWrapper.getInstance().get().add("adbc"); // In general add your config here, instead of abdc.
}
}
My ThreadLocalWrapper looks like this:
public class ThreadLocalWrapper {
private static ThreadLocal<List<String>> listOfStringLocals; // You can modify this to a list of Object or an Object by itself.
public static synchronized ThreadLocal<List<String>> getInstance() {
if (listOfStringLocals == null) {
listOfStringLocals = new ThreadLocal<List<String>>() {
#Override
protected List<String> initialValue() {
return new ArrayList<String>();
}
};
}
return listOfStringLocals;
}
}
To Access the value:
In Controller - Inject HttpServletRequest Object and do getAttribute() to get the value. Since HttpServletRequest Object is requestScoped, you can set the loaded config. into this and access it in your controller's using request Object again.
In Any other part of the code - If HttpServletRequest is not available then you can always use the ThreadLocal example shown. To access this value.
public class GuiceTransactionImpl implements GuiceTransaction {
private String value = "";
public GuiceTransactionImpl(String text) {
value = text;
}
#Override
public String returnSuccess() {
return value + " Thread Local Value " + ThreadLocalWrapper.getInstance().get();
}
}
First at all I read the previous question: Exposing link on collection entity in spring data REST
But the issue still persist without trick.
Indeed if I want to expose a link for a collections resources I'm using the following code:
#Component
public class FooProcessor implements ResourceProcessor<PagedResources<Resource<Foo>>> {
private final FooLinks fooLinks;
#Inject
public FooProcessor(FooLinks fooLinks) {
this.FooLinks = fooLinks;
}
#Override
public PagedResources<Resource<Foo>> process(PagedResources<Resource<Foo>> resource) {
resource.add(fooLinks.getMyCustomLink());
return resource;
}
}
That works correctly except when collection is empty...
The only way to works is to replace my following code by:
#Component
public class FooProcessor implements ResourceProcessor<PagedResources> {
private final FooLinks fooLinks;
#Inject
public FooProcessor(FooLinks fooLinks) {
this.FooLinks = fooLinks;
}
#Override
public PagedResources process(PagedResources resource) {
resource.add(fooLinks.getMyCustomLink());
return resource;
}
}
But by doing that the link will be exposed for all collections.
I can create condition for exposing only for what I want but I don't think is clean.
I think spring does some magic there trying to discover the type of the collection - on an empty collection you cannot tell which type it is of - so spring-data-rest cannot determine which ResourceProcessor to use.
I think I have seen in
org.springframework.data.rest.webmvc.ResourceProcessorHandlerMethodReturnValueHandler.ResourcesProcessorWrapper#isValueTypeMatch that they try to determine the type by looking at the first element in the collection and otherwise just stop processing:
if (content.isEmpty()) {
return false;
}
So I think you cannot solve this using spring-data-rest. For your controller you could fall back to writing a custom controller and use spring hateoas and implement your own ResourceAssemblerSupport to see the link also on empty collections.
I've a webservice similar to the following:
#RequestMapping(value = "/getMovies", method = RequestMethod.POST, produces = "application/json")
public #ResponseBody ResponseVO getMoviesList(#RequestBody RequestVO vo) { .... }
The RequestVO class is :
public class RequestVO {
private String[] genreList;
public void updateRequest() {
if (genreList != null) {
// remove the duplicates from the list
// or something else
}
}
public String[] getGenreList() {
return genreList;
}
public void setGenreList(String[] genreList) {
this.genreList = genreList;
}
}
Now I want the method updateRequest to be called automatically after the request json is processed as RequestVO. One thing I currently think of is #PostConstruct, but seems to be of no use in this case.
My question is does Spring provide any such annotation or mechanism ? Or #PostConstruct will do the trick ?
NB : I don't need workarounds as I've plenty of them. So please refrain yourself from posting them. Again above codes are mere samples (please ignore minor mistakes).
Couple of thins to consider:
Don't use verbs in Rest Service method names (like getMovies) because you specify action using HTTP verbs like GET, POST and so on.
POST should be used to create a resource on the server not to retrieve them (what is implied by the method name: 'getMovies')
What do you want to achieve is RequestVO.updateRequest() invoked before passing RequestVO instance to getReportData(), is it right? If so, could you elaborate, why can't you invoke this method on the beginning of the getReportData()?
If you want to achieve this kind of functionality despite the fact it's sensible or not, try:
create new aspect which will be invoked before getReportData() and invoke updateRequest()
use #JsonFactory (provided you use Jackson to map JSON to Java objects) like:
public class RequestVO {
private String[] genreList;
public void updateRequest() {
if (genreList != null) {
...
}
}
public String[] getGenreList() {
return genreList;
}
public void setGenreList(String[] genreList) {
this.genreList = genreList;
}
#JsonFactory
public static RequestVO createExample(#JsonProperty("genreList") final String[] genreList) {
RequestVO request = new RequestVO(genreList);
request.updateRequest();
return request;
}
}
As you are saying, #PostConstruct is only call after a bean creation and is of no use here. But you have 2 simple ways of calling a method after the end of another method.
explicit : just wrap your real method in another one, and do all pre- or post-processing there
#RequestMapping(value = "/getMovies", method = RequestMethod.POST, produces = "application/json")
public #ResponseBody ResponseVO getMoviesList(#RequestBody RequestVO vo) {
// pre_processing
ResponseVO resul = doGetMoviesList(vo);
// post_processing
return resul;
}
public ResponseVO doGetMoviesList(RequestVO vo) { ... }
Is is simple to write, even if not very nice.
use Spring AOP. You can define an after returning advice that will be called after the advised method returns normally. The advice can be shared across multiple classes if you need it and write your pointcut accordingly. It is really powerfull, but has one caveat : Spring implementation uses proxies and by default JDK proxies. That means that any advised method should be member of an interface and called through that interface. So it would be much simpler and cleaner to advise a service than a controller. IMHO, if you really need to do AOP on a controller, you should use full AspectJ including class weaving ... In short, it is very nice, very powerfull, but a little harder to implement.
I am working on creating a RESTful API for a project. I am facing a few problems trying to implement it with jersey:
My object model does not contain uri info obviously. e.g, lets say I have a Fruit class. Fruit object would have let's say a FruitName and a FruitColor. But in the response I also need to send a URI. How is this usually handled? Should I create a separate "FruitResource" that has a constructor which takes a "Fruit" and creates a full resource from it, including URI? I need URIs in the nested objects as well, e.g if I am returning a list of Child objects, I need each Child object to also have a URI, but I donlt want the URI to be part of the object model. What is the cleanest way to do this?
I want to have capability to return full and partial views of the same resource. Partial views would just have the name and the URI for example. How to get this done?
Right now what I have is a Service class that accepts the requests, which uses the DAO to create and return the objects as they are modelled from the DB, serialized to JSON using jackson.
There i a way to use JaxB class and you can pass Object Model to JaxB class and JaxB class generates URI.
The below is small prototype.
UserResource Class
#Path("/user")
public class UserResource {
#GET
#Produces(MediaType.APPLICATION_JSON)
#Path("{user-id}")
public UserJaxB getUser(#PathParam("user-id") String userId, #Context
HttpServletRequest request) {
// now XYZ is hard-coded value
String serviceEndpoint = request.getContextPath() + "/" + "user";
UserModel userModel = new UserModel(userId, "XYZ");
return new UserJaxB(serviceEndpoint,userModel);
}
}
User JAXB Class
#XmlRootElement
public class UserJaxB {
private String name;
private String id;
private String serviceEndpoint;
private String URI;
public UserJaxB(String serviceEndpoint, UserModel userModel) {
this.name = userModel.getName();
this.id = userModel.getId();
this.serviceEndpoint = serviceEndpoint;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getURI() {
return this.serviceEndpoint + "/" + id;
}
}
User Model Class
public class UserModel {
String name;
String id;
public UserModel(String name, String id) {
this.name = name;
this.id = id;
}
public String getId() {
return id;
}
public String getName() {
return name;
}
}
I'm working on a project that supports both of those concerns: https://github.com/skyscreamer/yoga with more information at http://yoga.skyscreamer.org/, including a demo.
It replaces the JAX-RS (or Spring MVC) rendering mechanism with a custom built solution that's more in tune with the needs of a REST System.
For #1, we have an annotation that you have to apply to your Child pojo. JAX-RS's annotations are meant to map URLs to controllers not to the underlying object, so we needed a custom solution... but it's really just comes down to 1 additional annotation per pojo.
For #2, we have a URL based mechanism of specifying which additional information you want from a pojo or a pojo's children (and can be nested further).
I hope this helps.
1) I'm not aware of any Jersey or JAX-RS mechanism supporting this. Seems like a bad practice to have to add the URI to the constructor for each of your domain classes, though. You could create an aspect that would intercept the method and wrap the response in a new object - adding the URI of the resource in the wrapper (you could get the URIInfo via reflection from the interceptor). I've done this when building etag support so I don't have to add cache code to every response. I suppose you could also add something in the same aspect to handle the child URI issue...
You might also want have a look at these dicussions:
http://java.net/projects/jersey/lists/users/archive/2009-01/message/357
http://markmail.org/search/?q=list%3Anet.java.dev.jersey.users+brett.dargan%40gmail.com#query:list%3Anet.java.dev.jersey.users%20brett.dargan%40gmail.com+page:1+mid:7ln7wixfihfodngg+state:results
2) For building "lighter" response entities I typically have a BeanLite.class with just the properties I need for a summary and then a Bean.class extending it with more detail. You can add both to your ORM and provide an option to switch representations in your DAO.
Thanks for all your responses. Going through all the approaches you guys presented and after a little bit of research on my own, this is what I settled on:
1) I am adding uri as part of the object model. This seems to be the cleanest solution to me currently. The URI can be automatically populated whenever the object is created (using other properties of the object). Earlier I thought this is a bad idea, but I am not able to foresee any problems with this approach other than the extra field that will have to keep moving with the objects.
2) For supporting full/partial views, I am trying to use the #JsonView annotation. This seems to be a good approach.
Let me know if there are any other potential issues with this way of handling things.