My requests look like:
http://...
?type[A].size=14
&type[B].query=test
My #Controller has a method which should accept those generic request params:
#RequestMapping(...)
public void test(MyModel m) {
...
}
public static class MyModel {
Map<String, ?> type;
}
The problem is: ? should be some class which is defined by the key of the Map.
This means: key=A should Map to class A and key=B should map to class B. According to the given request above: Class A will have a property int size and class B will have a property String query.
I just can't figure out, how I can tell Spring to use class A for key A and class B for key B.
(I know I could do it with POST and Jackson, but I'd like to solve this using a GET request).
Thanks for your help :)
Related
I am working on a Spring MVC application and I have the following problem.
I have this RegistrazioneInfo class that contains some information inserted into a form by the user:
public class RegistrazioneInfo {
#NotNull
#Size(min=16, max=16)
private String codiceFiscale;
String gRecaptchaResponse;
public String getCodiceFiscale() {
return codiceFiscale;
}
public void setCodiceFiscale(String codiceFiscale) {
this.codiceFiscale = codiceFiscale;
}
public String getgRecaptchaResponse() {
return gRecaptchaResponse;
}
public void setgRecaptchaResponse(String gRecaptchaResponse) {
this.gRecaptchaResponse = gRecaptchaResponse;
}
}
Then I have this controller class:
#Controller
public class RegistrazioneController extends BaseController {
private RegistrazioneInfo registrazioneInfo;
...............................................
...............................................
...............................................
}
that contains some methods handling request towards some resources.
Ok, my problem is that I want to use an instance of the previous RegistrazioneInfo class as session attribute by the use of the #SessionAttributes Spring annotation as shown here: http://docs.spring.io/spring/docs/3.2.x/spring-framework-reference/html/mvc.html#mvc-ann-sessionattrib
My problem is, in the previous example do something like this:
#SessionAttributes("pet")
public class EditPetForm {
// ...
}
So what exactly is pet? I think that it is something like an id that identify the object that have to be used as a session attribute or something like this. How can I say to put an instance of my RegistrazioneInfo as session attribute?
#SessionAttributes is declared in a Controller Class (#Controller), so on the class level.
Pet is an Bean Object that persist in HttpSession
From the documentation:
This will typically list the names of model attributes which should be transparently stored in the session or some conversational storage, serving as form-backing beans. Declared at the type level, applying to the model attributes that the annotated handler class operates on.
(emphasis is mine)
Also note that, as indicated in the documentation, you should not use that for "non temporary" elements.
i want to exclude specific properties of spring rest response body. after hours of googling around i found this: http://www.jroller.com/RickHigh/entry/filtering_json_feeds_from_spring due to its date i like to ask if there is something more up-to-date for jackson and or fasterxml. JsonView doesnt fit my requirements as i need to have such case covered:
if A is the set of all my attributes: one time i need to expose B with B ⊂ A. another time C with C ⊂ A. And B ∩ C != ∅
this would cause complex view declarations as well as annotating every class and might not be possible as well in some cases. so what i would like to do is something similar to this:
#RequestMapping("/test1")
#JsonIgnoreProperties( { "property1"})
public TestObject test1(HttpRequest request){
return new TestObject();
}
#RequestMapping("/test2")
#JsonIgnoreProperties( { "property2"})
public TestObject test1(HttpRequest request){
return new TestObject();
}
with output:
{property2:ipsum,property3:dolor}
{property1:lorem,property3:dolor}
In my opinion Jackson View is what you need.
You have to define three interfaces which should cover all properties:
Public - all common properties.
A - properties which belong to set A.
B - properties which belong to set B.
Example interfaces:
class Views {
static class Public { }
static class A extends Public { }
static class B extends Public { }
}
Assume that your POJO class looks like this:
class TestObject {
#JsonView(Views.A.class) String property1;
#JsonView(Views.B.class) String property2;
#JsonView(Views.Public.class) String property3;
}
Now, your controller should contain below methods with annotations:
#RequestMapping("/test1")
#JsonView(Views.B.class)
public TestObject test1(HttpRequest request){
return new TestObject();
}
#RequestMapping("/test2")
#JsonView(Views.A.class)
public TestObject test2(HttpRequest request){
return new TestObject();
}
All of this I has created without testing. Only by reading documentation but it should work for you. I am sure that similar solution worked for me once.
Simple problem:
#Controller
class MyController {
#RequestMapping(...)
void test(MyModel m) {
...
}
}
class MyModel {
MyNestedModel a;
}
class MyNestedModel {
#RequestParam("b[]")
List<String> b;
}
This apperantly does not work, because #RequestParam only works with method parameters.
Is there a way to define the name of the request param within the model object?
Reason:
My MyModel and MyNestedModel classes is of course much bigger and I'd like to use for example ?a.b[]=TEST.
Thanks for your help :)
EDIT: Looks like this is exactly my problem: How to customize parameter names when binding spring mvc command objects
Spring mvc can transfer the parameter for you. But the post data should be like:
{a.b[0] : "b1", a.b[1] : "b2"}
then you can get a list in m.a.b
I would like to use both #Post and #Get on the same method like
#GET
#POST
#Path("{mode}")
public void paymentFinish(#PathParam("mode") String mode, String s) {
logger.debug("Enter PayStatus POST");
logger.debug(mode);
}
Even I write like this, I got error. What I want is whatever get or post to the sameurl, the same method works. Is it possible? Now I separate two methods, one for get and one for post.
Unfortunately, only one should be used in order to avoid Jersey exception.
But you could do something like :
#GET
#Path("{mode}")
public void paymentFinish(#PathParam("mode") String mode, String s) {
commonFunction(mode);
}
#POST
#Path("{mode}")
public void paymentFinishPOST(#PathParam("mode") String mode, String s) {
commonFunction(mode);
}
private void commonFunction(String mode)
{
logger.debug("Enter PayStatus POST");
logger.debug(mode);
}
By doing so, if you want to change inner behavior of your functions, you will only have to change one function.
Note that method name in java for get vs post need to be different.
After searching a lot trying to avoid the solution above, I found nothing....
Then I decided to create a custom annotation so I didn't have to waste time duplicating methods.
Here's the github link: Jersey-Gest
It allows you to create GET and Post Methods on a single Annotation by generating a new class from it.
I hope it helps you the same way it helped me :)
Edit:
If for some reason the above link stops working, here's what I did:
Created a compile-time annotation #RestMethod for class methods.
Created a compile-time annotation #RestClass for classes.
Create an AnnotationProcessor which generates a new class with Jersey's corresponding annotations and for each method creates a GET and a POST method which callsback to the original method annotated with #RestClass.
All methods annotated with #RestMethod must be static and contained within a class annotated with #RestClass.
Example (TestService.java):
#RestClass(path = "/wsdl")
public class TestService
{
#RestMethod(path = "/helloGest")
public static String helloGest()
{
return "Hello Gest!";
}
}
Generates something like (TestServiceImpl.java):
#Path("/wsdl")
#Produces("application/xml")
public class TestServiceImpl
{
#GET
#Path("/helloGest")
#Produces(MediaType.APPLICATION_XML)
public String helloGestGet()
{
return TestService.helloGest();
}
#POST
#Path("/helloGest")
#Consumes(MediaType.WILDCARD)
#Produces(MediaType.APPLICATION_XML)
public String helloGestPost()
{
return TestService.helloGest();
}
}
I have a whole bunch of methods as shown below in a class.
#RequestMapping(value="/person/foo" method = RequestMethod.POST, headers = "Accept=application/xml, application/json")
public #ResponseBody Person update(#RequestBody final Person person) {
//
}
I want to put the annotations at the class level so my methods look like below:
#RequestMapping(value="foo") // for Post requests
public #ResponseBody Person update(#RequestBody final Person person) {
//
}
Most of my methods are POST, so I use that at the class level. The methods that are GET, I want to put it at the method level.
But it doesn't work. Some of the Post methods work, but GET methods don't work at all.
If you have #RequestMapping defined at the class level e.g.:
#Controller
#RequestMapping( value="/person" )
public class BeautifulPeopleController { ... }
You cannot make some of the methods to ignore it => all of the methods would assume they are prepended with /person.
Here is from the #RequestMapping API docs:
Method-level mappings are only allowed to narrow the mapping expressed at the class level (if any)