I have web services developed using Jersey, and a service take as parameter a Java Bean annotated with #QueryParam annotations on fields. It works fine when the service is invoked directly via its URL. Now I wish to call that service programatically from another piece of code (a JSP in the same WAR, say). I wish to have the bean parameter filled in with the query parameters of my current request, basically doing myself what Jersey does for me automatically when I call the service URL.
I want really to be able to take the request parameters and inject them into the relevant bean fields. I know I could do that myself with BeanUtils and reading the annotations myself, but surely there is an easier way?
Example code:
My service defines this method
#GET
public Response generate(#BeanParam Options options){...}
And Options is a Bean that has fields like
#QueryParam("format")
private String format="pdf";
I want to be able to write something like:
Options myoptions=new Options();
???.inject(myoptions,request);
in my JSP.
Does it make sense?
Related
I am creating an controller where there is certain attributes in json which is an doing in postman a POST request like this if all attributes are posted then its fine
if one then is missing then it would look like this
i want this response when some attribute is missing how to implement this
This is normally implemented in two steps:
Implement a validation mechanism for the method that handles the incoming request. Normally you would throw an exception here if the input is incorrect, in your example a missing JSON key.
Implement a global error handler that will process the exception from point 1 and format the response as JSON.
For point 1 the usual choice is the Java Bean Validation framework because it's integrated with Spring Boot and allows to define validation constraints with annotations like #NotEmpty. You can take a look at this example.
For point 2 the usual choice is #RestControllerAdvice or #ControllerAdvice. You would have to understand your service web server setup to implement it properly e.g. it might behave differently if you use Spring WebFlux.
I am building a service with RestAPI's. I want to put a custom annotation as mentioned below.
#CustomAnnnotation
public APIResponse apiMethod(APIRequest request) {
}
Functionality of this custom annotation :
Whenever there is a request to this apiMethod, before the execution of this method , i want to call an API in different server with some of the request parameters from this function. Example mentioned below. Basically for every method invocation i want to call a different server.
Instead of doing this
public APIResponse apiMethod(APIRequest request) {
newServiceClient.newAPI(request.getName())
}
I want to do this functionality by using a custom annotation. I know that i can use interceptors to intercept this request and call the API. Is there any other way ?
Edit :
To summarise this question. There is a method(This might not be API start point. It can also be a normal method in your application) in my java code. Whenever i annotate this method, for every invocation of this method in application, i want do some functionality. I want to have this in annotation because i am thinking of providing a library for this annotation so that any function can be annotated
I recently added AOP with aspectJ and spring-aop to my existent spring project. The goal was to actually intercept controller calls to modify the response they send back, in order to bind some values to this response I didn't want to add manually to each and everyone of my controllers, for example the expiration date of the actual token used by the end-user (which I wasn't even able to showcase within my controller in any case). I actually managed to get it working until I started my unit tests :
In my unit tests I call directly my controller methods using Reflection feature from java, then replicate usual process (calling the filter chain, pre handler and post handlers, and the controller method itself which is first manually validated using spring validator when annotation #Valid is present on one of my parameters. All this process works fine and gets executed properly). The problem is that now that the controller method is intercepted by spring-aop, it's mentionned as coming from the proxy controller created, and all of my parameters annotations disapear. Here is a controller example :
#Override
public ResponseEntity<Object> editPassword(#Valid #RequestBody PasswordEditForm passwordEditForm, HttpServletRequest request) {
return factorizedUserBaseController.editPassword(passwordEditForm, request, User.class);
}
the parameter PasswordEditForm has the annotation #Valid so in my test cases it was first validated before any other step, but now as I double checked it, the #Valid annotation is not present on the proxy method, and therefore the parameter doesn't get validated, any clue for how to fix this and make my parameters annotation still understandable from my test point of view?
Note : when running the spring through mvn spring-boot:run, parameters with #Valid annotation gets correctly validated and then goes to my error handler method properly.
Problem Solved : from several other stackoverflow posts I understand that CGLIB (aop proxy lib used by Spring) doesn't support annotations. ( see Retain annotations on CGLIB proxies?). But my problem wasn't here, I was literally sure I was finding the method using the controller class itself (the one I coded) but what I was wrong about is that I was giving the controller instance as a parameter to some other parts of my code which in turn would use this controller class to find the method which of course wasn't working because thanks to Spring proxies, it wasn't anymore my controller itself but a proxy class extending my own controller class. Instead, I just had to replace :
Class<?> controllerClass = controllerInstanciationContainer
.getController()
.getClass();
with
Class<?> controllerClass = controllerInstanciationContainer
.getController()
.getClass()
.getSuperclass();
It seems like I can do everything that the Controller class do inside Spring Web-Flow, for example decision making and switching from page to page. To my understanding, its the C inside the MVC model. Am I correct about this?
So my question is, is there any advantage to still include a Controller class when using Spring Web-Flow?
If you need access to the request and response, an appropriate design might still include a controller while also having a flow.xml. For example, if you had this code:
HttpServletRequest request = (HttpServletRequest)context.getExternalContext().getNativeRequest();
HttpServletResponse response = (HttpServletResponse)context.getExternalContext().getNativeResponse();
It's more intelligible to put that in a controller rather than a service.
Also, if you want to register a custom editor, it might make sense to have the controller have this logic in the initBinder() method.
Spring Web Flow uses the Spring MVC framework. The DispatcherServlet handles the request. A FlowHandlerMapping is used to map the request to a particular Web Flow.
Web Flow is to solve the problem involved with controller logic that spans multiple-page navigation (a pageflow, or wizard).
Web Flow can eliminate the need for specialized controller classes to accomplish following a path of page transitions/form updates along a predefined workflow. If you don't need to do this, you can save yourself a lot of configuration/complexity just by using MVC.
If I have a #Controller method whose parameter is a #RequestBody param, I usually have to write some jQuery script or something similar to perform an AJAX request with JSON object in order to call that method. If I tried calling that method via a web browser directly, it returns with a Error 415 Unsupported Media Type.
Is there any alternative to just quickly call such method using browser without having to write some jQuery code? Like perhaps a way to write the JSON object in the URL/address bar?
code:
#RequestMapping("testCall")
#ResponseBody
public List<TestObject> getTestCall (#RequestBody TestParams testParams) {
return stuff;
}
public class TestParams {
private Integer testNumber;
//getter/setter for testNumber
}
I thought maybe I could just do:
http://localhost/testCall?testNumber=1
maybe Spring would auto populate a new TestParams instance with that property set to 1 but that didnt work...
maybe I need to do something extra for that?
The whole point of a #RequestBody annotated parameters is for the Spring MVC stack to use the HTTP request body to produce an argument that will be bound to the parameter. As such, you need to provide a request body. Sending a request body is very atypical for a GET request. As such, browsers don't typically support it, at least not when simply entering an address in the address bar and submitting the request.
You'll need to use a different HTTP client, like jQuery. I typically have a small Java project in Eclipse that's setup with an Apache HTTP components client which can send HTTP requests to whatever server. It takes a few seconds/minutes to setup the correct request body and run.
I have spent the last year building a REST API, and by far the best way to exercise that API manually is using the Chrome Extension, Postman. I cannot recommend this tool enough.
https://chrome.google.com/webstore/detail/postman-rest-client/fdmmgilgnpjigdojojpjoooidkmcomcm?hl=en
To test your simple example you'll need to invoke a POST (I assume that as you have a request body, but your controller method doesn't define a HTTP Verb) using POSTMAN to your Url (like the following example):
POST /contextRoot/testCall
{
"testNumber": 1
}
If you want to test your API automatically (which I recommend), you can use the excellent Spring Mvc Test project. This allows your to call your API via a rest-like DSL and assert that the response is in the shape you want. More details can be found here:
http://docs.spring.io/spring/docs/3.2.x/spring-framework-reference/html/testing.html#spring-mvc-test-framework
you can add request params to the getTestCall method:
#RequestParam(value = "testNumber", required = false, defaultValue = "") String testNumber
There is a chrome app called Advanced REST client. You can pass the data in form of json to your controller using this chrome app. For eg. json data is
id:1,
name:"xyz"
whereas the controller can have #RequestBody Person form.
The Person class would be a POJO having id and name as instance variables. The Spring would automatically map the json data to the form.
I think this is the easiest and simplest way of checking your spring controller.
Check the extension Advanced REST client here
From what I know You can send JSON object to the webbrowser and it will be displayed without further need of AJAX.
useful tutorial:
http://www.mkyong.com/spring-mvc/spring-3-mvc-and-json-example/