I know this question is very similar to this one, but I feel its different and specific enough to warrant its own question here.
I've just inherited a Java web app project from a sole developer who left no documentation behind. Its a Spring MVC app with a basic package structure as follows:
com.ourOrg.app.controllers
ImageController
ProgramController
UserController
com.ourOrg.app.otherPackages
Each Controller class is just a POJO annotated with #Controller and #RequestMapping("/blah"). For instance:
#Controller
#RequestMapping("/images")
public class ImageController() {
#RequestMapping(value="/saveImage", method = RequestMethod.POST)
#ResponseBody
public ResponseEntity<String> saveImage(#RequestParam(value="imageData", required=true) String imageXML, HttpServletRequest request){
// This method gets executed whenever the:
// http://ourSite.com/images/saveImage
// URL is hit
}
}
I have been asked to add the following HTTP headers to the Spring config so that we disable browser caching:
Pragma: no-cache
Cache-Control: no-cache
Expires: -1
The article I linked to above makes it sound like our controllers should be extending this WebContentGenerator class. Unfortunately, there are dozens of controllers with an enormous number of methods, so refactoring each one to extend or inherit some base type is not really a viable option (unless its the only option!).
I've also seen articles that make it sound like you have to configure Spring to use AOP interceptors that modify your response headers, but now I'm really getting into unfamiliar territory.
Given our setup and implementation of Spring MVC, whats the easiest way for me to add these three simple headers to every response sent back by the server (regardless of which controller or method is executed)?
Thanks in advance!
Hoping you are using Spring 3, you can look at an interceptor, then you won't have to modify all of your controllers (since you said you had many). It looks like they may already have one implemented that you can just use. Check out Bozho's answer to this question how to set header no cache in spring mvc 3 by annotation
I realize this is an old post but maybe this will help somebody. I am using Spring for this example.
The main thing is use the annotation for parameters:
#Controller
public class HelloController {
#RequestMapping(value = "/hello.htm")
public String hello(#RequestHeader(value="User-Agent") String userAgent)
//..
}
}
Related
I am designing a REST controller layer with the concept of different versioning which might happen in the future.
I am thinking of having separate classes with version number as follows.
#RequestMapping("/v1/api")
#RestController
class V1RestController {
}
#RequestMapping("/v2/api")
#RestController
class V2RestController {
}
Or V2RestController might extend V1RestController depending on the requirements. This is just a draft idea. But my question is if there is any Spring MVC api which can catch the URL and look up the version '/v1/api or /v2/api' and delegate the request to the right controller.
Based on my research, the best way is to make it backward-compatible, but i am sure that the reality is different and there would be some cases to have different implementations.
I know that there are other ways to design the rest controller layer for different versioning, but for now, i would like to take this approach.
Any help would be appreciated.
But my question is if there is any Spring MVC api which can catch the URL and look up the version '/v1/api or /v2/api' and delegate the request to the right controller.
DispatcherServlet intercepts the request (what to intercept it looks in "web.xml" ), and then DispatcherServlet looks at the request URL and looks for the controller whose "value" parameter (the "#RequestMapping" annotation) matches the request URL, if a match is found: control is transferred in the corresponding controller. Something like this.
I'm having some trouble regarding the authorization endpoint of my Spring based OAuth2 provider. I need more information from the client than there is currently possible. This is what I want to achieve:
I need the custom parameter in the authentication process later on. Is there any simple way to extend the default parameters with my custom one or do I need to implement a certain class myself?
Did some research on how the authentication endpoint works in the current Spring code. I found that the Authorization Endpoint uses a method named authorize that takes all the parameter that are being set and converts then into an AuthorizationRequest. While looking further into the AuthorizationRequest class I found that it holds a map with extensions that is being filled throughout the authorization process. But it does not seem to get filled with my custom parameter (as shown above). This is in fact by only looking at the code, so I might be wrong.
Would it be a good idea to extend the AuthorizationEndpoint with my custom implementation or is there a better and cleaner way to do this?
Update #1 (07-10-2015)
The place where I'd like to use the custom parameter is in my own implementation of the AuthenticationProvider. I need to information to be available inside the authenticate method of this class.
Update #2 (07-10-2015)
It seems that the AuthorizationProvider gets called before the AuthorizationEndpoint. This means that the custom parameter is obtained after the class where I need it (so that's too late).
Maybe I can get the referral Url by either extending part of the Spring security classes or by obtaining it in the HTML through JavaScript. Is this a good idea or should I use another approach?
So I managed to fix the problem myself by searching some more on Google.
What you need to do is speak to the HttpSessionRequestCache to get the referral URL. This is how I solved it in my own implementation of the AuthenticationProvider
#Component
public class CustomProvider implements AuthenticationProvider {
#Autowired
private HttpServletRequest httpRequest;
#Autowired
private HttpServletResponse httpResponse;
#Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
SavedRequest savedRequest = new HttpSessionRequestCache().getRequest(httpRequest, httpResponse);
logger.info("Referral URL: " + savedRequest.getRedirectUrl());
logger.info("Parameters: " + savedRequest.getParameterMap().keySet().toString());
}
}
This will print out the URL of the request that was called before heading to the login page of spring security. The second log method prints out the parameters that where found in this URL. This question and answer helped me in creating a solution for my problem.
I need inputs related to Spring MVC, I have a URL to which a client will send a post request with an xml as the pay load. I plan to have a controller method which maps to the requested url, I want that xml to be validated/converted to an object using jaxb before controller method is executed. And also, the controller method should have only the object as the parameter to its methods and no httprequest etc.
So, how do I achieve this? Will interceptor be helpful? If yes, how will it be done?
I plan to use Spring 3.
Simply use #RequestBody in conjunction with #Valid on a method argument and that is all you need.
public void myRequestHandlingMethod(#Valid #RequestBody YourJaxbObject jaxbObject) { … }
I strongly suggest you take a look at the Spring reference guide
We use Spring to implement REST controller, for example:
#Controller
#RequestMapping("/myservice")
public class MyController {
#RequestMapping(value = "foo", method = RequestMethod.GET)
public #ResponseBody string foo() {...}
}
I can call this service using spring RestTemplate, and it works fine, but I would prefer to invoke it using a proxy, instead of typeless invocation using string url:
// client code:
MyController proxy = getProxy("baseUrl", MyController.class);
String results = proxy.foo();
So the input to proxy generation is java interface with annotations describing REST details.
I read this article and it looks like all types of remote calls do have proxies, and all I need for REST is something like RestProxyFactoryBean, that would take my REST java interface and return type-safe proxy that uses RestTemplate as implementation.
The closest solution I found is JBoss RESTEasy.
But it seems to use different set of annotations, so I am not sure it will work with annotations I already have: #Controller, #RequestMapping.
Are there other options, or RESTEasy is the only one?
Note, I am spring newbie so some obvious spring things are pretty new to me.
Thank you.
Dima
You can try Feign by Netflix, a lightweight proxy-based REST client. It works declaratively through annotations, and it's used by Spring Cloud projects to interact with Netflix Eureka.
One of the reasons the REST paradigm was invented was because expirience with other remoting technologies (RMI, CORBA, SOAP) shows us that often, the proxy-based approach creates more problems than it solves.
Theoretically, a proxy makes the fact that a function call is remote transparent to its users, so they can use the function exactly the same way as if it were a local function call.
In practice however this promise cannot be fulfilled, because remote function calls simply have other properties than local calls. Network outages, congestion, timeouts, load problems to name just a few. If you choose to ignore all these things that can go wrong with remote calls, your code probably won't be very stable.
TL;DR: You probably shouldn't work with a proxy, it's not state of the art any more. Just use RestTemplate.
Here is a project trying to generate runtime proxies from the controller annotations (using RestTemplate in the background to handle proxy calls): spring-rest-proxy-client Very early in implementation though.
This seems to do it: https://swagger.io/swagger-codegen/, and swagger has many other nice things for REST API.
Have a look at https://github.com/ggeorgovassilis/spring-rest-invoker.
All you need is to register FactoryBean:
#Configuration
public class MyConfiguration {
#Bean
SpringRestInvokerProxyFactoryBean BankService() {
SpringRestInvokerProxyFactoryBean proxyFactory = new SpringRestInvokerProxyFactoryBean();
proxyFactory.setBaseUrl("http://localhost/bankservice");
proxyFactory.setRemoteServiceInterfaceClass(BankService.class);
return proxyFactory;
}
and after that you can autowire the interface class:
#Autowired
BookService bookService;
I also ended up making my own library for this. I wanted something that is as small as possible, adds only itself to classpath and no transitive dependencies.
A client is created like:
final StoreApi storeApi = SpringRestTemplateClientBuilder
.create(StoreApi.class)
.setRestTemplate(restTemplate)
.setUrl(this.getMockUrl())
.build();
And rest-requests will be performed when invoking the methods:
storeApi.deleteOrder(1234L);
The is supports both method signatures:
ResponseEntity<X> deleteOrder(Long)
X deleteOrder(Long)
I have a JIRA plugin that I'm developing that has a REST service. That service should be able to accept POSTed requests, unmarshall some data and store it. The seemingly suggested way to do this in JIRA is to make use of the Bandana persistence framework. According to this page, I should be able to simply define a setter that Spring should call to give me my Bandana manager.
#Path("/path")
public class SCMService {
private BandanaManager bandanaManager;
// setter called by Spring
public void setBandanaManager(BandanaManager bandanaManager) {
this.bandanaManager = bandanaManager;
}
//...More methods...
}
However, when I test this, the setter is never being called and my manager is null. I'm guessing this should be as simple as registering this service with Spring for injection somehow but I can't seem to find anything like that.
How would I get my setter called? Is there a better way to do this?
Er, I'm not sure that JIRA uses Bandana in that way, though Confluence does. You can certainly post data to a JIRA rest resource and then store it using properties tables
Something like this:
#POST
#Consumes (MediaType.APPLICATION_XML)
public Response createComponentAndIssues(#Context HttpServletRequest request, ...