Spring Web Flow Converter - java

I have a Spring MVC and Web Flow 2.3 application.
All I would like to know is how you have a select box in SWF with some default value say, for example, 'Please Select' that is not bound to any value in the backing list.
In line with the docs I have created a conversion service:
public class ApplicationConversionServiceFactoryBean extends FormattingConversionServiceFactoryBean {
// formatters
registry.addFormatter(...);
// converters
registry.addConverter(...);
}
This all works unless I want to perform what would seem to be a perfectly simple task of having 'Please Select' in a select box.
A formatter cannot return null from its Parse Method so you cannot use that. Switching from a formatter to a one-way converter (String > Object) fixes then issue in the MVC stuff however the SWF still complains about missing converter for Object > String. Using this setup do I actually need to create another converter implementation for Object > String (essentially have two converters for every conversion).
Yes, there are other converters TwoWayConverter, ObjectToString etc. etc. however I do not see that these can be added in the above as they are all all the wrong type to be added using:
registry.addConverter(...);
The documentation around conversion is confusing to say the least:
http://docs.spring.io/spring-webflow/docs/2.3.x/reference/htmlsingle/spring-webflow-reference.html#converter-options

You can do atleast adding binding null value or empty string to your model. So you can use default value for select one menu. Like this:
<sf:option value="">Please select...</sf:option>
But in your Formatter or Converter, you should check your model property is null or empty String and if so return null or empty String as you like. Like this:
public YourEnum parse(String value, Locale local) throws ParseException {
if(YourEnum.valueOf(YourEnum.class, value.toUpperCase()) == YourEnum.VALUEONE) {
return YourEnum.VALUEONE;
} else if(YourEnum.valueOf(YourEnum.class, value.toUpperCase()) == YourEnum.VALUETWO) {
return YourEnum.VALUETWO;
} else {
return null;
}
}

Related

How can my Freemarker ObjectWrapper access a template setting

Use case: system administrator stores a Freemarker template in a database which is used (by Spring Boot REST API) to present information stored by system users (respondents) in a locale-aware way to a different user type (reviewer).
A respondent's response might be stored in this sort of object (or in lists of this sort of object, in the event a question posed to the respondent is expected to have multiple answers):
// snip
import com.fasterxml.jackson.databind.node.ObjectNode;
// more imports snipped
public class LanguageStringMap {
private Map<Language, String> languageStringMap;
public LanguageStringMap(ObjectNode languageMapNode) {
// snip of code instantiating a LanguageStringMap from JSON
}
public void put(Language language, String value) {
if (value.length() == 0)
throw new IllegalArgumentException(String.format(
"value for language '%s' of zero length", language.getCode()));
languageStringMap.put(language, value);
}
public String get(Language language) { return languageStringMap.get(language); }
}
What I think I want to do is write an ObjectWrapper that maps instances of LanguageStringMap to a string (obtained by calling the get() method with a language derived from the Locale requested by the reviewer's browser and set in the template's settings). This presents a cleaner user experience to the system administrator than making the uploaded template contain a bunch of template method calls would.
To do this, my object wrapper needs to access a template setting. I have perused the pertinent Freemarker documentation, but I am still unclear on how to do this or if it is even possible.
I think it would be a mistake to try to implement this with resource bundles uploaded to the database alongside the templates, but that is a consideration.
Typically you simply put the locale specific string into the data-model before the template is processed, along with all the other variables. In that case no ObjectWrapper customization is needed. But if you have to use an ObjectWrapper-based solution, then you can get the locale inside an ObjectWrapper method (like in the override of DefaultObjectWrapper.handleUnknownType) with Environment.getCurrentEnvironment().getLocale().

How to manipulate information from a GET response

I'm new to java / rest / jersey, so please bear with me.
Problem: I want to use a GET method to retrieve some information I have previously POSTed. My only confusion is...where is the information after I call the GET?
Here is my post (you can ignore it as I know this part works):
#POST #Path("/tools")
public Response createTool(JsonNode tool) throws URISyntaxException {
//use custom validator to de-couple implementation from validation
ToolValidator validator = new ToolValidator(tool);
if(validator.isNotNull() == false) {
System.out.println("in not null");
return Response.status(400).entity("Please add tool details").build();
}
if (validator.hasValidType() == false) {
System.out.println("in valid timestamp");
return Response.status(400).entity("Please provide a valid tool type").build();
}
if(validator.haveValidValues() == false ) {
System.out.println("in valid values");
return Response.status(400).entity("Please provide a tools list with valid numerical values").build();
}
String type= tool.get("type").asText();
return Response.status(201).entity(tool).build().created(new URI("/tools/"+type)).build();
}
It definitely posts a tool correctly (I've tested it and seen it, I believe this works but it might not).
Now what I want to do is get the json, see if adheres to some requirements, and return an answer. Basically, irrelevant of the POST code above, for any url that returns some json when you navigate to it, I want to be able to grab that json and do something with it.
#GET #Path("/tools/{type}")
public Response getToolInfo(#PathParam("type") String type) {
return Response.ok().build();
}
My only question here is..."where" is the information to manipulate?? I feel like I'm asking an extremely fundamental, basic question for REST / Jersey, so I apologize if this is like the ABCs here.
Basically, I use my POST method to POST a tool with some specific json. I can navigate to that page and see the json object. Now I want to use a GET method to analyze the json but...I have no idea how / where this information is stored when I decide to use a GET method.
Does the #get annotation automatically store the information returned from the specified path somewhere? Does anything?
From the code you pasted it doesn't look like anything is stored. In your #POST it looks like you pass JsonNode tool, from that you create an object of type ToolValidator which you use to do some sort of validation. From your JsonNode tool you retrieve a field called "type".
At last you create a response instance with the parameter you already passed and you change the Uri to "/tools/" and the String value of whatever is in the variable "type".
So it doesn't look like you are doing any database access to store the JsonNode passed as parameter.
It definitely posts a tool correctly (I've tested it and seen it).
It posts the tool because of this Response.status(201).entity(tool).build()
You are just simply telling it to set the response entity in the builder. Whereas build() a response instance.
For testing purposes only create a global variable, in your class, of type JsonNode and copy the passed parameter (JsonNode tool), in your POST method, to your global variable. Then you can retrieve it in your GET method. Don't forget to create getter and setter for your global variable.
In a real life scenario though you would be storing things in your database. If it's just for some prototype then a global variable should be enough
Here is a tiny example of what I mean:
public class SomeClass {
private JsonNode copiedTool;
#POST #Path("/tools")
public Response createTool(JsonNode tool) throws URISyntaxException {
setCopiedTool(tool);
String type= tool.get("type").asText();
return Response.status(201).entity(getCopiedTool()).build().created(new URI("/tools/"+type)).build();
}
#GET #Path("/tools/{type}")
public Response getToolInfo(#PathParam("type") String type) {
if(getCopiedTool().get("type").equals(type)) {
return Response.ok(getCopiedTool()).build();
}
return Response.status(204).build();
}
public JsonNode getCopiedTool() {
return copiedTool;
}
public void setCopiedTool(JsonNode copiedTool) {
this.copiedTool = copiedTool;
}
}

Can I access property keys with Selenium on a wicket generated html page?

I am trying to automate frontend tests with Selenium for a wicket based web application.
Therefore I have:
- Different languages
- language property files (submit.signup.form=Submit) and wicket messages () using them
- HTML pages which are generated by wicket (input type:button and value:Submit)
If I go ahead and automate a test case with that, it will work properly.
The problems start when somebody decides to change the property file to f.i. submit.signup.form=Send.
If that happens I will have to adjust all Selenium tests to check for the correct label again to make a test successful (this is not really applicalbe for that example but for error messages it will be a problem)
Now the question:
Is there a way to make wicket to put the property key onto/into the generated html files?
Desired benefit:
I can use Java and make Selenium take the property ke and check the property file for the text. That way a change of a label in the property file would not effect the Selenium tests at all and would make it much more easy to handle.
I am grateful for any answer. :)
Best regards
By default, Wicket starts in development mode. In development mode you should see the wicket tags, you should take a look in to IDebugSettings
, however you will not see the properties gathered from the java code, but you can add the key as attribute, for example
new Label(getString("propertieKey")).add(new AttributeAppender("key","propertieKey"))
It's quite easy to do actually.
Put in your application init method:
getResourceSettings().getStringResourceLoaders().add(0, new NoResourceLoader());
Implement NoResourceLoader:
public class NoResourceLoader implements IStringResourceLoader {
#Override
public String loadStringResource(Class<?> clazz, String key, Locale locale, String style, String variation) {
if ("noProperties".equals(style)) {
return key;
}
return null;
}
#Override
public String loadStringResource(Component component, String key, Locale locale, String style, String variation) {
if ("noProperties".equals(style)) {
return key;
}
return null;
}
}
This resource loader just returns the key if the style is set to noProperties. As it returns null, the localizer will try the next resourceloader for any other invocation.
In order to set style to "noProperties" I'd suggest adding a parameter check to your pages' constructor that would set the style on the session object when you call your application with the parameter.
public BasePage(PageParameters pp) {
String style = pp.get("st").toOptionalString();
if (style != null) {
getSession().setStyle("noProperties");
}
It would be enough to call your first url with this parameter set, then you should walk through the whole session with property keys instead of values in the html. I'd also disable this check when the app is running in production.

Play 2.0/Java - Is there a way to get the validation done post request data binding?

In play 2.0 you can get the request binding with validation done (via annotations) by :
ABCForm abcForm=(ABCForm)form(ABCForm.class).bindFromRequest().get();
The problem I have is , I want to get the validation done after trimming the form values.
So is there a way to either defer or call the validation stuff post binding in play 2.0 ?
Binding and validation are combined. So validation after the binding is not possible, as far as I know. However you can create a validate() method, in which you trim your values before validating them. For example:
public class User {
public String name;
public String validate() {
name.trim
if(name == "") {
return "Name is required";
}
return null;
}
}
The validate() method will be invoked when you bind a form. So you can make sure your data is valid, but errors won't be automatically added to the Form.Field objects. So it is certainly a nice solution.
There are also pretty much discussions about Form validation in Play's Google Group, so if you want to know more about the binding/validation problems I recommend reading them: https://groups.google.com/forum/#!searchin/play-framework/%5B2.0%5D$20validation.
If you need to modify your values before validation. You can create a setter for your field and do your trims there.

Is there an easy way to turn empty form inputs into null strings in Spring MVC?

I'm using Spring MVC and SimpleJdbcInsert to insert objects into a MySQL database. I'd like to set the blank input to NULL in the database rather than ''. I have quite a few fields, and I'm hoping for a way to do this without manually checking every value.
Thanks!
UPDATE
So I'm an idiot. Several errors combined on my part led me to believe the correct answers below were not correct. I'd written a PropertyEditorSupport like this:
class StringEditor extends PropertyEditorSupport {
public void setAsText(String text) {
String value = text.trim();
if ("" == value) {
setValue(null);
} else {
setValue(value);
}
}
}
There are two problems:
no getAsText, so my form was getting populated with "null" strings!
my equality check is C++, not Java. When I tried the recommended
setter, I just reloaded the post, which already contained the "null"
strings. Once I cleaned all that up, everything started working.
Thanks for the help, and sorry for my "operator error"!
Brett
The class you're looking for is:
org.springframework.beans.propertyeditors.StringTrimmerEditor
If you construct it with a true it will convert empty/whitespace strings to null. How to get it registered onto the binder depends on if you want it to be the default or only apply to certain views.
e.g., on a single controller you can just add
#InitBinder
public void initBinder(WebDataBinder binder) {
binder.registerCustomEditor(String.class, new StringTrimmerEditor(true));
}
instructions here
I know this is old, but I wasted about 2 or 3 hours until I found a very easy way to apply a StringTrimmerEditor with a binder for all my controllers.
Once again: I must remember to RTFM.
In spring 3.2 you can create a #ControllerAdvice-annottated controller class and use the #InitBinder-annotated method just like the example #Affe gave.
http://docs.spring.io/spring/docs/3.2.x/spring-framework-reference/html/mvc.html#mvc-ann-initbinder-advice
Here is an example:
#ControllerAdvice
#Controller
public class AppBindingInitializer {
#InitBinder
public void initBinder(WebDataBinder binder) {
binder.registerCustomEditor(String.class, new StringTrimmerEditor(true));
}
}
Hope it helps someone.
Perhaps you can use a custom Binder
Set the default value for your optional fields to NULL - actually is it not NULL by default?
Parse your input string and then explicitly specify only populated columns with
usingColumns
oh, and I'd advise to always sanitise your inputs...

Categories

Resources