I'm using Spring for form input and validation. The form controller's command contains the model that's being edited. Some of the model's attributes are a custom type. For example, Person's social security number is a custom SSN type.
public class Person {
public String getName() {...}
public void setName(String name) {...}
public SSN getSocialSecurtyNumber() {...}
public void setSocialSecurtyNumber(SSN ssn) {...}
}
and wrapping Person in a Spring form edit command:
public class EditPersonCommand {
public Person getPerson() {...}
public void setPerson(Person person) {...}
}
Since Spring doesn't know how to convert text to a SSN, I register a customer editor with the form controller's binder:
public class EditPersonController extends SimpleFormController {
protected void initBinder(HttpServletRequest req, ServletRequestDataBinder binder) {
super.initBinder(req, binder);
binder.registerCustomEditor(SSN.class, "person.ssn", new SsnEditor());
}
}
and SsnEditor is just a custom java.beans.PropertyEditor that can convert text to a SSN object:
public class SsnEditor extends PropertyEditorSupport {
public String getAsText() {...} // converts SSN to text
public void setAsText(String str) {
// converts text to SSN
// throws IllegalArgumentException for invalid text
}
}
If setAsText encounters text that is invalid and can't be converted to a SSN, then it throws IllegalArgumentException (per PropertyEditor setAsText's specification). The issue I'm having is that the text to object conversion (via PropertyEditor.setAsText()) takes place before my Spring validator is called. When setAsText throws IllegalArgumentException, Spring simply displays the generic error message defined in errors.properties. What I want is a specific error message that depends on the exact reason why the entered SSN is invalid. PropertyEditor.setAsText() would determine the reason. I've tried embedded the error reason text in IllegalArgumentException's text, but Spring just treats it as a generic error.
Is there a solution to this? To repeat, what I want is the specific error message generated by the PropertyEditor to surface to the error message on the Spring form. The only alternative I can think of is to store the SSN as text in the command and perform validation in the validator. The text to SSN object conversion would take place in the form's onSubmit. This is less desirable as my form (and model) has many properties and I don't want to have to create and maintain a command that has each and every model attribute as a text field.
The above is just an example, my actual code isn't Person/SSN, so there's no need to reply with "why not store SSN as text..."
You're trying to do validation in a binder. That's not the binder's purpose. A binder is supposed to bind request parameters to your backing object, nothing more. A property editor converts Strings to objects and vice versa - it is not designed to do anything else.
In other words, you need to consider separation of concerns - you're trying to shoehorn functionality into an object that was never meant to do anything more than convert a string into an object and vice versa.
You might consider breaking up your SSN object into multiple, validateable fields that are easily bound (String objects, basic objects like Dates, etc). This way you can use a validator after binding to verify that the SSN is correct, or you can set an error directly. With a property editor, you throw an IllegalArgumentException, Spring converts it to a type mismatch error because that's what it is - the string doesn't match the type that is expected. That's all that it is. A validator, on the other hand, can do this. You can use the spring bind tag to bind to nested fields, as long as the SSN instance is populated - it must be initialized with new() first. For instance:
<spring:bind path="ssn.firstNestedField">...</spring:bind>
If you truly want to persist on this path, however, have your property editor keep a list of errors - if it is to throw an IllegalArgumentException, add it to the list and then throw the IllegalArgumentException (catch and rethrow if needed). Because you can construct your property editor in the same thread as the binding, it will be threadsafe if you simply override the property editor default behavior - you need to find the hook it uses to do binding, and override it - do the same property editor registration you're doing now (except in the same method, so that you can keep the reference to your editor) and then at the end of the binding, you can register errors by retrieving the list from your editor if you provide a public accessor. Once the list is retrieved you can process it and add your errors accordingly.
As said:
What I want is the specific error message generated by the PropertyEditor to surface to the error message on the Spring form
Behind the scenes, Spring MVC uses a BindingErrorProcessor strategy for processing missing field errors, and for translating a PropertyAccessException to a FieldError. So if you want to override default Spring MVC BindingErrorProcessor strategy, you must provide a BindingErrorProcessor strategy according to:
public class CustomBindingErrorProcessor implements DefaultBindingErrorProcessor {
public void processMissingFieldError(String missingField, BindException errors) {
super.processMissingFieldError(missingField, errors);
}
public void processPropertyAccessException(PropertyAccessException accessException, BindException errors) {
if(accessException.getCause() instanceof IllegalArgumentException)
errors.rejectValue(accessException.getPropertyChangeEvent().getPropertyName(), "<SOME_SPECIFIC_CODE_IF_YOU_WANT>", accessException.getCause().getMessage());
else
defaultSpringBindingErrorProcessor.processPropertyAccessException(accessException, errors);
}
}
In order to test, Let's do the following
protected void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) {
binder.registerCustomEditor(SSN.class, new PropertyEditorSupport() {
public String getAsText() {
if(getValue() == null)
return null;
return ((SSN) getValue()).toString();
}
public void setAsText(String value) throws IllegalArgumentException {
if(StringUtils.isBlank(value))
return;
boolean somethingGoesWrong = true;
if(somethingGoesWrong)
throw new IllegalArgumentException("Something goes wrong!");
}
});
}
Now our Test class
public class PersonControllerTest {
private PersonController personController;
private MockHttpServletRequest request;
#BeforeMethod
public void setUp() {
personController = new PersonController();
personController.setCommandName("command");
personController.setCommandClass(Person.class);
personController.setBindingErrorProcessor(new CustomBindingErrorProcessor());
request = new MockHttpServletRequest();
request.setMethod("POST");
request.addParameter("ssn", "somethingGoesWrong");
}
#Test
public void done() {
ModelAndView mav = personController.handleRequest(request, new MockHttpServletResponse());
BindingResult bindingResult = (BindingResult) mav.getModel().get(BindingResult.MODEL_KEY_PREFIX + "command");
FieldError fieldError = bindingResult.getFieldError("ssn");
Assert.assertEquals(fieldError.getMessage(), "Something goes wrong!");
}
}
regards,
As a follow up to #Arthur Ronald's answer, this is how I ended up implementing this:
On the controller:
setBindingErrorProcessor(new CustomBindingErrorProcessor());
And then the binding error processor class:
public class CustomBindingErrorProcessor extends DefaultBindingErrorProcessor {
public void processPropertyAccessException(PropertyAccessException accessException,
BindingResult bindingResult) {
if(accessException.getCause() instanceof IllegalArgumentException){
String fieldName = accessException.getPropertyChangeEvent().getPropertyName();
String exceptionError = accessException.getCause().getMessage();
FieldError fieldError = new FieldError(fieldName,
"BINDING_ERROR",
fieldName + ": " + exceptionError);
bindingResult.addError(fieldError);
}else{
super.processPropertyAccessException(accessException, bindingResult);
}
}
}
So the processor method's signature takes a BindingResult instead of a BindException on this version.
This sounds similar to an issue I had with NumberFormatExceptions when the value for an integer property could not be bound if, say, a String was entered in the form. The error message on the form was a generic message for that exception.
The solution was to add my own message resource bundle to my application context and add my own error message for type mismatches on that property. Perhaps you can do something similar for IllegalArgumentExceptions on a specific field.
I believe you could just try to put this in your message source:
typeMismatch.person.ssn=Wrong SSN format
Related
Hello I have question about #ModelAttribute annotation. As i understand, we use #ModelAttribute in method arguments to get data from the model. But it's quite hard to understand clearly when and how its used.
(Code samples are from Spring in Action 5 book)
Why in this case in the code below in public String processOrder() method we do not use #ModelAttribute annotation on #Valid Order order
#Controller
#RequestMapping("/orders")
#SessionAttributes("order")
public class OrderController {
private OrderRepository orderRepo;
public OrderController(OrderRepository orderRepo) {
this.orderRepo = orderRepo;
}
#GetMapping("/current")
public String orderForm(#AuthenticationPrincipal User user,
#ModelAttribute Order order) {
if (order.getDeliveryName() == null) {
order.setDeliveryName(user.getFullname());
}
//following conditions
return "orderForm";
}
#PostMapping
public String processOrder(#Valid Order order, Errors errors, // <<< Here
SessionStatus sessionStatus,
#AuthenticationPrincipal User user) {
if (errors.hasErrors()) {
return "orderForm";
}
order.setUser(user);
orderRepo.save(order);
sessionStatus.setComplete();
return "redirect:/";
}
}
but in this case, DesignTacoController class, #ModelAttribute on a method processDesign() is used on #Valid Taco taco:
#Slf4j
#Controller
#RequestMapping("/design")
public class DesignTacoController {
#PostMapping
public String processDesign(#Valid #ModelAttribute("design") Taco design, // <<< Here
Errors errors, Model model) {
if (errors.hasErrors()) {
return "design";
}
// Save the taco design...
// We'll do this in chapter 3
log.info("Processing design: " + design);
return "redirect:/orders/current";
}
And then in the next chapter author removes #ModelAttribute from processDesign() method from the same DesignTacoController class.
#Controller
#RequestMapping("/design")
#SessionAttributes("order")
#Slf4j
public class DesignTacoController {
#ModelAttribute(name = "order")
public Order order() {
return new Order();
}
#ModelAttribute(name = "design")
public Taco design() {
return new Taco();
}
#PostMapping
public String processDesign(
#Valid Taco taco, Errors errors, // <<< Here
#ModelAttribute Order order) {
log.info(" --- Saving taco");
if (errors.hasErrors()) {
return "design";
}
Taco saved = tacoRepo.save(taco);
order.addDesign(saved);
return "redirect:/orders/current";
}
And in this code snippet(from the code above):
#PostMapping
public String processDesign(
#Valid Taco taco, Errors errors, // <<< Here
#ModelAttribute Order order) {
....
}
quote from book: "The Order parameter is annotated with #ModelAttribute to indicate that its
value should come from the model and that Spring MVC shouldn’t attempt to bind
request parameters to it."
This I don't understand what author meant here, because in all tutorials it is said that when #ModelAttribute is used as a method arguments,it binds request parameters to it. Binds the form data with a POJO bean, model attribute is populated with data from a form submitted.
The documentation is pretty clear on this:
https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc-ann-methods
#ModelAttribute
For access to an existing attribute in the model (instantiated if not
present) with data binding and validation applied. See #ModelAttribute
as well as Model and DataBinder.
Note that use of #ModelAttribute is optional (for example, to set its
attributes). See “Any other argument” at the end of this table.
.
Any other argument
If a method argument is not matched to any of the earlier values in
this table and it is a simple type (as determined by
BeanUtils#isSimpleProperty, it is a resolved as a #RequestParam.
Otherwise, it is resolved as a #ModelAttribute.
So essentially it is optional. You may wish to use just to make it explicit that that is how the argument is resolved or you may need to use if binding should not happen (by specifying binding = false) See futher: https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/bind/annotation/ModelAttribute.html. It is normally my preference to specify it regardless.
This wasn't clear to me either.
Here we need specify the name if the model attribute.
Because in our view we assume it is named "design" and not "taco".
#PostMapping
public String processDesign(#Valid #ModelAttribute("design") Taco design, Errors errors) {
If we rename the Taco class to Design ...
We don't need to specify the name if the model attribute.
It will be deduced from the simple name of the class.
com.example.Design -> "design"
#PostMapping
public String processDesign(#Valid Design design, Errors errors) {
See the javadoc for ModelAttribute:
The default model attribute name is inferred from the declared
attribute type (i.e. the method parameter type or method return type),
based on the non-qualified class name: e.g. "orderAddress" for class
"mypackage.OrderAddress", or "orderAddressList" for
"List".
I have asked a similar question before: this one
Now I have a similar but different issue.
My Spring MVC controller model is a JSON payload with a defined set of attributes that, unfortunately, are not part of a class in my project.
E.g.
{
"userId" : "john",
"role" : "admin"
}
I need to treat userId and role as separate Strings.
I currently have two ways to declare the controller method
public ResponseObject mvc(#RequestBody MyCustomDTO dto){
String userId = dto.getUserId();
String role = dto.getRole();
}
public ResponseObject mvc(#RequestBody ModelMap map){
String userId = (String)map.get("userId");
String role = (String)map.get("role");
}
I have been asked to find a different implementation because 1) requires to create a custom DTO class for each combination of parameters (most cases need 1 named parameter, e.g. delete(productId)) and 2) involves an entity that is not strictly defined. Especially when dealing with lists, it can contain arbitrary values that need to be checked at runtime.
Spring MVC, as I have found, does not support resolving #ModelAttribute from a JSON request body. Am I doing something wrong or is it just Spring not doing it? Can I grab a specific property, be it a plain primitive or an entire POJO, from the Request Body into a method argument?
In the second case it would be better to request a useful feature to Spring developers.
Spring version is 4.2.x.
This question is related with the previously linked but differs in the fact that now I will be encapsulating the single property into a Javascript object, so the object that Jackson needs to deserialize won't be a primitive but a POJO.
You won't be able to get individual members as easily, simply because Spring MVC doesn't have any builtin tools to do that. One option is to write your own annotation that describes a parameter at the root of an excepted JSON object body. Then write and register a new HandlerMethodArgumentResolver implementation which processes that annotation on a handler method parameter.
This is not a simple task. Since you can't consume the request content multiple times, you have to save it somehow, in a Filter, for example. For now, let's ignore this restriction and assume we only wanted one parameter. You'd define an annotation
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.PARAMETER)
#interface JsonObjectProperty {
String name();
}
And the HandlerMethodArgumentResolver
class JsonObjectPropertyResolver implements HandlerMethodArgumentResolver {
/**
* Configured as appropriate for the JSON you expect.
*/
private final ObjectMapper objectMapper = new ObjectMapper();
#Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.hasParameterAnnotation(JsonObjectProperty.class);
}
#Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest,
WebDataBinderFactory binderFactory) throws Exception {
Class<?> parameterType = parameter.getParameterType();
HttpServletRequest servletRequest = webRequest.getNativeRequest(HttpServletRequest.class);
ServletServerHttpRequest inputMessage = new ServletServerHttpRequest(servletRequest);
MediaType contentType = inputMessage.getHeaders().getContentType();
if (!contentType.equals(MediaType.APPLICATION_JSON_UTF8)) {
throw new HttpMessageNotReadableException(
"Could not read document. Expected Content-Type " + MediaType.APPLICATION_JSON_UTF8 + ", was " + contentType + ".");
}
// handle potential exceptions from this as well
ObjectNode rootObject = objectMapper.readValue(inputMessage.getBody(), ObjectNode.class);
if (parameterType == String.class) {
JsonObjectProperty annotation = parameter.getParameterAnnotation(JsonObjectProperty.class);
return rootObject.get(annotation.name()).asText();
}
// handle more
throw new HttpMessageNotReadableException("Could not read document. Parameter type " + parameterType + " not parseable.");
}
}
and finally the handler method
#RequestMapping(value = "/json-new", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
#ResponseBody
public String handleJsonProperty(#JsonObjectProperty(name = "userId") String userId) {
String result = userId;
System.out.println(result);
return result;
}
You'll have to register the JsonObjectPropertyResolver appropriately. Once you do, it will be able to extract that JSON property directly into the parameter.
You can use some JSON inline parsers (similar to XML Xpath) where you can provide your JSON string and ask your parser to retrieve some subdocument as String, List or Map. One of the examples is OGNL. It's quite powerful tool, although it is not the only one and not the most performance efficient, but still mature and stable Apache product. So, in your case you would be able feed your JSON string to OGNL and tell it to retrieve properties "userId" and "role" as separate strings. See the OGNL documentation at Apache OGNL page
In my spring project, I am trying set up generic classes for my controllers and service classes, with commons methods used by that classes. In my generic controller, each possible action the entities could receive (like insert, update, delete, select), are implemented with a pair of methods like that:
#RequestMapping(value="cadastra")
#PreAuthorize("hasPermission(#user, 'permission')")
public ModelAndView cadastra() throws InstantiationException, IllegalAccessException {
return new ModelAndView("privado/"+this.entity_name+"/cadastra", "command", this.entity.getClass().newInstance());
}
#RequestMapping(value="cadastra", method=RequestMethod.POST)
#ResponseBody
public String cadastra(#ModelAttribute("object") E object, BindingResult result) {
if(service.cadastra(object))
return "yes";
else
return "not";
}
and in my generic service class, this same action have related methods like that:
#PreAuthorize("hasPermission(#user, 'permissao')")
public boolean cadastra(E object) {
return dao.persist(object);
}
My question is which value I should use as atribute replacing permission and object above. The value for permssion follow this scheme:
<name_of_action>_<name_of_entity>
and the value for object is the name of each entity.
I try use the same structure I use inside the method (+this.entity_name+), but this cause an compilation error, because this annotations only accept constant arguments.
It was sugested to me use a generic class for my entities, but I can't figure out how to use that in my case.
Anyone can give a direction of how to accomplish what I want?
UPDATE
After some sugestions from other users from stackoverflow, I get to solve my problem with the ModelAtribute annotation. The final solution was this:
#RequestMapping(value="cadastra", method=RequestMethod.POST)
#ResponseBody
public String cadastra(#ModelAttribute("object") E object, BindingResult result) {
if(serv.cadastra(object))
return "yes";
else
return "not";
}
and I add this new method to my controller:
#ModelAttribute("object")
public E createCommandObject() throws InstantiationException, IllegalAccessException {
return (E) this.entityClass.newInstance();
}
Now I need only a solution for the PreAuthorize annotation, which uses the instruction #this.
So, I solve this issue with this approach:
1) For annotation PreAuthorize:
1.1) Adding a new method to my generic controller, where I return the name of the class:
public String getName() {
String expressao = entityClass.getName();
String nome_classe = new String();
StringTokenizer st = new StringTokenizer(expressao, ".");
while (st.hasMoreTokens()) {
nome_classe = st.nextToken();
}
return nome_classe;
}
1.2) Inside the annotation, I use the returned value by this method and concatenate the result with the constant string (using the notation described by the user #pgjecek in this topic):
#PreAuthorize("hasPermission(#user, 'cadastra_'+#this.this.name)")
and now it1s working perfectly.
2) For annotation ModelAtribute:
I keep using the form #ModelAttribute("object") E object, but add the method:
#ModelAttribute("object")
public E createCommandObject() throws InstantiationException, IllegalAccessException {
return (E) this.entityClass.newInstance();
}
which return a new instance of the desired object.
I'm testing out the #InitBinder annotation so I can have String objects converted into appropriate Enum objects during web requests.
I created the following simple Enum:
SampleEnum.java
public enum SampleEnum {
ONE,
TWO,
THREE,
FOUR,
FIVE;
}
Then, I created an editor extending PropertyEditorSupport to be called from the #InitBinder code:
EnumPropertyEditor.java
#SuppressWarnings("rawtypes")
public class EnumPropertyEditor extends PropertyEditorSupport {
private Class clazz;
public EnumPropertyEditor(Class clazz) {
this.clazz = clazz;
}
#Override
public String getAsText() {
return (getValue() == null ? "" : ((Enum) getValue()).name());
}
#SuppressWarnings("unchecked")
#Override
public void setAsText(String text) {
Enum e = Enum.valueOf(clazz, text);
setValue(e);
}
}
Then, in my controller I added the #InitBinder and a simple request mapping:
Controller
#InitBinder
public void initBinder(WebDataBinder binder) {
binder.registerCustomEditor(SampleEnum.class, new EnumPropertyEditor(SampleEnum.class));
}
#RequestMapping(method = POST, value = "/postSampleEnum")
#ResponseBody
public SampleEnum postSampleEnum(#RequestBody SampleEnum sampleEnum) {
return sampleEnum;
}
From my understanding, a request for this controller method should attempt to convert a string value into the SampleEnum object. However, no breakpoints are hit in either initBinder, request mapping method, nor any of the methods in the EnumPropertyEditor.
I'm testing with RESTClient in FireFox, and have tried sending in the request body "THREE", which I would expect to work. Instead, I get a 415 error regardless of the what's in the request body. (The server refused this request because the request entity is in a format not supported by the requested resource for the requested method ().)
If I change the request mapping to take in a string instead of a SampleEnum, the postSampleEnum gets called and doesn't use the custom editor (as expected).
Am I missing anything that allows the custom editor code to be called? What is the best way to continue debugging this?
First of all, I forgot to add the application/json content-type to the request header in RESTClient. >_<
However, I noticed that the code execution still doesn't go through the custom property editor. As GriffeyDog said, it looks like the code only executes if I switch to a RequestParam or ModelAttribute.
I'm running a webapp in Spring Web MVC 3.0 and I have a number of controller methods whose signatures are roughly as follows:
#RequestMapping(value = "/{level1}/{level2}/foo", method = RequestMethod.POST)
public ModelAndView createFoo(#PathVariable long level1,
#PathVariable long level2,
#RequestParam("foo_name") String fooname,
#RequestParam(value = "description", required = false) String description);
I'd like to add some validation - for example, description should be limited to a certain length or fooname should only contain certain characters. If this validation fails, I want to return a message to the user rather than just throw some unchecked exception (which would happen anyway if I let the data percolate down to the DAO layer). I'm aware of JSR303 but have not worked with it and don't quite understand how to apply it in a Spring context.
From what I understand, another option would be to bind the #RequestBody to an entire domain object and add validation constraints there, but currently my code is set up to accept individual parameters as shown above.
What is the most straightforward way to apply validation to input parameters using this approach?
This seems to be possible now (tried with Spring 4.1.2), see https://raymondhlee.wordpress.com/2015/08/29/validating-spring-mvc-request-mapping-method-parameters/
Extract from above page:
Add MethodValidationPostProcessor to Spring #Configuration class:
#Bean
public MethodValidationPostProcessor methodValidationPostProcessor() {
return new MethodValidationPostProcessor();
}
Add #Validated to controller class
Use #Size just before #RequestParam
#RequestMapping("/hi")
public String sayHi(#Size(max = 10, message = "name should at most 10 characters long") #RequestParam("name") String name) {
return "Hi " + name;
}
Handle ConstraintViolationException in an #ExceptionHandler method
There's nothing built in to do that, not yet anyway. With the current release versions you will still need to use the WebDataBinder to bind your parameters onto an object if you want automagic validation. It's worth learning to do if you're using SpringMVC, even if it's not your first choice for this task.
It looks something like this:
public ModelAndView createFoo(#PathVariable long level1,
#PathVariable long level2,
#Valid #ModelAttribute() FooWrapper fooWrapper,
BindingResult errors) {
if (errors.hasErrors() {
//handle errors, can just return if using Spring form:error tags.
}
}
public static class FooWrapper {
#NotNull
#Size(max=32)
private String fooName;
private String description;
//getset
}
If you have Hibernate Validator 4 or later on your classpath and use the default dispatcher setup it should "Just work."
Editing since the comments were getting kind of large:
Any Object that's in your method signature that's not one of the 'expected' ones Spring knows how to inject, such as HttpRequest, ModelMap, etc, will get data bound. This is accomplished for simple cases just by matching the request param names against bean property names and calling setters. The #ModelAttribute there is just a personal style thing, in this case it isn't doing anything. The JSR-303 integration with the #Valid on a method parameter wires in through the WebDataBinder. If you use #RequestBody, you're using an object marshaller based on the content type spring determines for the request body (usually just from the http header.) The dispatcher servlet (AnnotationMethodHandlerAdapter really) doesn't have a way to 'flip the validation switch' for any arbitrary marshaller. It just passes the web request content along to the message converter and gets back a Object. No BindingResult object is generated, so there's nowhere to set the Errors anyway.
You can still just inject your validator into the controller and run it on the object you get, it just doesn't have the magic integration with the #Valid on the request parameter populating the BindingResult for you.
If you have multiple request parameters that need to be validated (with Http GET or POST). You might as well create a custom model class and use #Valid along with #ModelAttribute to validate the parameters. This way you can use Hibernate Validator or javax.validator api to validate the params. It goes something like this:
Request Method:
#RequestMapping(value="/doSomething", method=RequestMethod.GET)
public Model dosomething(#Valid #ModelAttribute ModelRequest modelRequest, BindingResult result, Model model) {
if (result.hasErrors()) {
throw new SomeException("invalid request params");
}
//to access the request params
modelRequest.getFirstParam();
modelRequest.getSecondParam();
...
}
ModelRequest class:
class ModelRequest {
#NotNull
private String firstParam;
#Size(min = 1, max = 10, message = "You messed up!")
private String secondParam;
//Setters and getters
public void setFirstParam (String firstParam) {
this.firstParam = firstParam;
}
public String getFirstParam() {
return firstParam;
}
...
}
Hope that helps.