I'm rather new to Play Framework so I hope this is intelligible.
How can I tell play to map a form element to an Object field in the Form's class?
I have a form with a select dropdown of names of objects from my ORM. The values of the dropdown items are the ID field of the ORM objects.
The form object on the Java side has a field with the type of the ORM object, and a setter taking a string and translating it to the object, but on form submission I only get a form error "Invalid Value" indicating the translation is not taking place at all.
My template has a form component:
#helper.select(
createAccountForm("industry"),
helper.options(industries)
)
Where industries is defined in the template constructor by : industries: Map[String, String]
and consists of ID strings to User-Readable names.
My controller defines the class:
public static class CreateAccountForm {
public String name;
public Industry industry;
public void setIndustry(String industryId) {
this.industry = Industry.getIndustry(Integer.parseInt(industryId));
}
}
EDIT: I was doing the setter in the class because this answer indicated to do so, but that didn't work.
EDIT2:
Turns out the setter method was totally not the way to go for this. After banging my head a bit on trying to get an annotation working, I noticed the Formatters.SimpleFormatter and tried that out. It worked, though I don't understand why the extra block around it is necessary.
Global.java:
public class Global extends GlobalSettings {
// Yes, this block is necessary; no, I don't know why.
{
Formatters.register(Industry.class, new Formatters.SimpleFormatter<Industry>() {
#Override
public Industry parse(String industryId, Locale locale) throws ParseException {
return Industry.getIndustry(Integer.parseInt(industryId));
}
#Override
public String print(Industry industry, Locale locale) {
return industry.name;
}
});
}
}
Play is binding the form to an object for you when you use it like described in the documentation: https://github.com/playframework/Play20/wiki/JavaForms
So your controller should look like:
Form<models.Task> taskForm = form(models.Task.class).bindFromRequest();
if (taskForm.hasErrors()) {
return badRequest(views.html.tasks.create.render(taskForm));
}
Task task = taskForm.get();
The task object can have a Priority options list. And you use it in the form (view) like:
#select(editForm("priority.id"), options(Task.priorities), 'class -> "input-xlarge", '_label -> Messages("priority"), '_default -> Messages("make.choice"), 'showConstraints -> false, '_help -> "")
Notice that I am using priorities.id to tell play that a chosen value should be binded by a priority ID. And of course getting the priorities of the Tasks:
public static Map<String, String> priorities() {
LinkedHashMap<String, String> prioritiesList = new LinkedHashMap<String, String>();
List<Priority> priorities = Priority.getPrioritiesForTask("task");
for (Priority orderPrio : priorities) {
prioritiesList.put(orderPrio.getId().toString(), orderPrio.getDescription());
}
return prioritiesList;
}
Related
I'm trying to implement DataTable functionality inside my BDD framework. The case is that I've just joined the company and don't really know how that custom Selenium/ Cucumber frameworks works... It will be a bit complicated but I will try to explain it the best way I can
So the the point:
This is my feature file:
Scenario Outline: Customer is able to edit his billing address (positive)
.......
Then I enter value into specific field
| Value | Locator |
| FirstName-Test | Account.AddressesList.Create.FirstName.Input |
Nextly we're using some kind of decorator design pattern that definition is connected with class step:
#Then("^I enter value into specific field$")
#XXXXProjectTestMethod(value = "^I enter value into specific field$", writing = false)
public void enterMultipleValuesIntoField(DataTable dataTable) {
automationSteps.enterMultipleValuesIntoFields(dataTable);
}
When I'm refering to: "enterMultipleValuesIntoFields" method is pointing to interface:
void enterMultipleValuesIntoFields(DataTable dataTable );
And then it's overridden in the base class:
public void enterMultipleValuesIntoFields(DataTable dataTable) {
WebDriver webDriver = getWebDriver();
List<Map<String,String>> credList = dataTable.asMaps();
String userName = credList.get(0).get("Value");
String password = credList.get(0).get("Locator");
The case is that while debugging I'm keep receiving dataTable parameter as a null just at the start of the method
Apart from the Cucumber annotation (step definition) mapping they using custom one:
#XXXXProjectTestMethod(value = "^I enter value into specific field$", writing = false)
Which looks like below and has only String type passed (thyey were not using DataTables before).
#Retention(RetentionPolicy.RUNTIME)
#Target({ElementType.METHOD})
public #interface XXXXXProjectTestMethod {
String value();
boolean writing();
}
And then used it is used in a way like this:
private static void findAnnotatedMethods(Class<?> clazz) {
Method[] methods = clazz.getMethods();
for (Method method : methods) {
if (method.isAnnotationPresent(XXXXXProjectTestMethod.class)) {
XXXXXProjectTestMethod annotation = method.getAnnotation(XXXXXProjectTestMethod.class);
methodMap.put(annotation.value(), method);
if (annotation.writing()) {
writingMethods.add(method);
}
}
}
}
private final static Map<String, Method> methodMap = new HashMap<>();
private final static List<Method> writingMethods = new ArrayList<>();
On 95% I'm sure the problem lays with that custom annotation but can someone confirm & agree with my opinion? Or maybe the initial parameter should not be automatically set to value/ data but on null and then I need to get it somehow firstly. Can you provide me any suggestion?
Also while debugging "normal" scenarios just with strings then field from custom annotation is correctly assigned eg. value = "test123", while debugging DataTable the value is pointing to null
Looking for the name of the design pattern by which you have a POJO with public final "properties" where the property acts as a holder/wrapper for a certain type of value and contains the getter/setter for that value as well as potentially some additional logic.
This differs from the "Property Container" design pattern where you have a single properties container which contains many types, as this only holds a single value and can thus enjoy the benefits of remaining strongly typed.
An example use:
public class User extends Entity<User> {
private static final Structure<User> STRUCTURE = Structure.of(User.class, User::new)
.addPrimaryKey("user_id", UUID).property((e) -> e.userID).setDefault(() -> UUID()).build()
.addIndex("username", VCHARS_50).property((e) -> e.username).build()
.addIndex("email", VCHARS_255).property((e) -> e.email).build()
.add("password", VCHARS_255).property((e) -> e.passwordHash).build()
.add("privacy_policy_accepted", EPOCH).property((e) -> e.ppAccepted).setDefault(() -> now()).build()
.add("tos_accepted", EPOCH).property((e) -> e.tosAccepted).setDefault(() -> now()).build()
.add("registration_date", EPOCH).property((e) -> e.registrationDate).setDefault(() -> now()).build()
.buildFor(Schema.MASTER);
public final Property<UUID> userID = new Property<>();
public final Property<String> username = new Property<>();
public final Property<String> email = new Property<>();
public final Property<String> passwordHash = new Property<>();
public final Property<Long> ppAccepted = new Property<>();
public final Property<Long> tosAccepted = new Property<>();
public final Property<Long> registrationDate = new Property<>();
public User() {
super(STRUCTURE);
}
public void hashAndSetPassword(String password) {
this.passwordHash.set(Argon2Factory.create(Argon2Types.ARGON2id).hash(3, 102800, 1, password.toCharArray()));
}
public boolean verifyPassword(String attempt) {
return Argon2Factory.create(Argon2Types.ARGON2id).verify(passwordHash.get(), attempt.toCharArray());
}
}
With each entity property using the following:
public class Property<T> {
private T currentValue;
public void set(T newValue) {
this.currentValue = newValue;
}
public T get() {
return this.currentValue;
}
#Override
public boolean equals(Object o) {
return Objects.equals(currentValue, o);
}
#Override
public int hashCode() {
return Objects.hashCode(currentValue);
}
#Override
public String toString() {
return String.valueOf(currentValue);
}
}
We can extend or modify this Properties class and make it do more useful stuff for us, like have it record an original value, provided on creation (pulled from a database) and allow it to self-report on whether the current value of the property differs from what it was originally. Useful for determining which columns need to be updated in a database.
Most notably, this eliminates the need to create getters and setters for every new property because the Property has that functionality already. Moreover, the getters/setters are able to be overridden per-property if additional logic is needed.
I naturally ended up using this design while aiming for a more broad goal of eliminating the use of reflection/annotation processors and other black magic from my web framework. However, I’m having difficulty finding it on the internet so that I might be able to research its potential deficiencies.
This kind of wrapper "variable" is used for Observable properties like StringProperty and such. Its primary use is to hold state and have change listeners, binding in general.
It is fruitfully used, like in JavaFX. And as you mentioned, in entity frameworks. But it definitely is stateful, non-functional, mutable.
A pattern name I cannot find, and I think the gang of 4 would haunt one, if calling this a pattern, other than State.
Credit to #Michael and #Kayaman for answering in the comments: This is not a known design pattern, contrary to my expectations.
In other words, there is not a name by which people generally know to refer to what I’m calling a "Property" nor the design I’m suggesting which assumes public getters and setters are desired and uses public final fields to expose a wrapper which provides them.
This is likely because, as Kayaman pointed out, it’s pretty heavy while being not terribly useful.
I have facade interface where users can ask for information about lets say Engineers. That information should be transferred as JSON of which we made a DTO for. Now keep in mind that I have multiple datasources that can provide an item to this list of DTO.
So I believe right now that I can use Decorative Pattern by adding handler of the datasource to the myEngineerListDTO of type List<EngineerDTO>. So by that I mean all the datasources have the same DTO.
This picture below shows that VerticalScrollbar and HorizontalScrollBar have different behaviours added. Which means they add behaviour to the WindowDecorator interface.
My question, does my situation fit the decorator pattern? Do I specifically need to add a behaviour to use this pattern? And is there another pattern that does fit my situation? I have already considered Chain of Responsibility pattern, but because I don't need to terminate my chain on any given moment, i thought maybe Decorator pattern would be better.
Edit:
My end result should be: List<EngineersDTO> from all datasources. The reason I want to add this pattern is so that I can easily add another datasource behind the rest of the "pipeline". This datasource, just like the others, will have addEngineersDTOToList method.
To further illustrate on how you can Chain-of-responsibility pattern I put together a small example. I believe you should be able to adapt this solution to suit the needs of your real world problem.
Problem Space
We have an unknown set of user requests which contain the name of properties to be retrieved. There are multiple datasources which each have varying amounts of properties. We want to search through all possible data sources until all of the properties from the request have been discovered. Some data types and data sources might look like bellow (note I am using Lombok for brevity):
#lombok.Data
class FooBarData {
private final String foo;
private final String bar;
}
#lombok.Data
class FizzBuzzData {
private final String fizz;
private final String buzz;
}
class FooBarService {
public FooBarData invoke() {
System.out.println("This is an expensive FooBar call");
return new FooBarData("FOO", "BAR");
}
}
class FizzBuzzService {
public FizzBuzzData invoke() {
System.out.println("This is an expensive FizzBuzz call");
return new FizzBuzzData("FIZZ", "BUZZ");
}
}
Our end user might require multiple ways to resolve the data. The following could be a valid user input and expected response:
// Input
"foobar", "foo", "fizz"
// Output
{
"foobar" : {
"foo" : "FOO",
"bar" : "BAR"
},
"foo" : "FOO",
"fizz" : "FIZZ"
}
A basic interface and simple concrete implementation for our property resolver might look like bellow:
interface PropertyResolver {
Map<String, Object> resolve(List<String> properties);
}
class UnknownResolver implements PropertyResolver {
#Override
public Map<String, Object> resolve(List<String> properties) {
Map<String, Object> result = new HashMap<>();
for (String property : properties) {
result.put(property, "Unknown");
}
return result;
}
}
Solution Space
Rather than using a normal "Decorator pattern", a better solution may be a "Chain-of-responsibility pattern". This pattern is similar to the decorator pattern, however, each link in the chain is allowed to either work on the item, ignore the item, or end the execution. This is helpful for deciding if a call needs to be made, or terminating the chain if the work is complete for the request. Another difference from the decorator pattern is that resolve will not be overriden by each of the concrete classes; our abstract class can call out to the sub class when required using abstract methods.
Back to the problem at hand... For each resolver we need two components. A way to fetch data from our remote service, and a way to extract all the required properties from the data retrieved. For fetching the data we can provide an abstract method. For extracting a property from the fetched data we can make a small interface and maintain a list of these extractors seeing as multiple properties can be pulled from a single piece of data:
interface PropertyExtractor<Data> {
Object extract(Data data);
}
abstract class PropertyResolverChain<Data> implements PropertyResolver {
private final Map<String, PropertyExtractor<Data>> extractors = new HashMap<>();
private final PropertyResolver successor;
protected PropertyResolverChain(PropertyResolver successor) {
this.successor = successor;
}
protected abstract Data getData();
protected final void setBinding(String property, PropertyExtractor<Data> extractor) {
extractors.put(property, extractor);
}
#Override
public Map<String, Object> resolve(List<String> properties) {
...
}
}
The basic idea for the resolve method is to first evaluate which properties can be fulfilled by this PropertyResolver instance. If there are eligible properties then we will fetch the data using getData. For each eligible property we extract the property value and add it to a result map. Each property which cannot be resolved, the successor will be requested to be resolve that property. If all properties are resolved the chain of execution will end.
#Override
public Map<String, Object> resolve(List<String> properties) {
Map<String, Object> result = new HashMap<>();
List<String> eligibleProperties = new ArrayList<>(properties);
eligibleProperties.retainAll(extractors.keySet());
if (!eligibleProperties.isEmpty()) {
Data data = getData();
for (String property : eligibleProperties) {
result.put(property, extractors.get(property).extract(data));
}
}
List<String> remainingProperties = new ArrayList<>(properties);
remainingProperties.removeAll(eligibleProperties);
if (!remainingProperties.isEmpty()) {
result.putAll(successor.resolve(remainingProperties));
}
return result;
}
Implementing Resolvers
When we go to implement a concrete class for PropertyResolverChain we will need to implement the getData method and also bind PropertyExtractor instances. These bindings can act as an adapter for the data returned by each service. This data can follow the same structure as the data returned by the service, or have a custom schema. Using the FooBarService from earlier as an example, our class could be implemented like bellow (note that we can have many bindings which result in the same data being returned).
class FooBarResolver extends PropertyResolverChain<FooBarData> {
private final FooBarService remoteService;
FooBarResolver(PropertyResolver successor, FooBarService remoteService) {
super(successor);
this.remoteService = remoteService;
// return the whole object
setBinding("foobar", data -> data);
// accept different spellings
setBinding("foo", data -> data.getFoo());
setBinding("bar", data -> data.getBar());
setBinding("FOO", data -> data.getFoo());
setBinding("__bar", data -> data.getBar());
// create new properties all together!!
setBinding("barfoo", data -> data.getBar() + data.getFoo());
}
#Override
protected FooBarData getData() {
return remoteService.invoke();
}
}
Example Usage
Putting it all together, we can invoke the Resolver chain as shown bellow. We can observe that the expensive getData method call is only performed once per Resolver only if the property is bound to the resolver, and that the user gets only the exact fields which they require:
PropertyResolver resolver =
new FizzBuzzResolver(
new FooBarResolver(
new UnknownResolver(),
new FooBarService()),
new FizzBuzzService());
Map<String, Object> result = resolver.resolve(Arrays.asList(
"foobar", "foo", "__bar", "barfoo", "invalid", "fizz"));
ObjectMapper mapper = new ObjectMapper();
mapper.enable(SerializationFeature.INDENT_OUTPUT);
System.out.println(mapper
.writerWithDefaultPrettyPrinter()
.writeValueAsString(result));
Output
This is an expensive FizzBuzz call
This is an expensive FooBar call
{
"foobar" : {
"foo" : "FOO",
"bar" : "BAR"
},
"__bar" : "BAR",
"barfoo" : "BARFOO",
"foo" : "FOO",
"invalid" : "Unknown",
"fizz" : "FIZZ"
}
We are working with mvc design pattern, where all the data is stored under map.
I want to iterate over all the classes in the system and for each to check what the method is putting on the map and what does the method get from the map.
For example for the next code:
private void myFunc()
{
Object obj = model.get("mykey");
Object obj2 = model.get("mykey2");
.....
model.put("mykey3", "aaa");
}
I want to know that in this function we have 2 gets: mykey and mykey2 and 1 put: mykey3
How can I do it with the code.
Thanks.
You tagged this with "reflection", but that will not work. Reflection only allows you to inspect "signatures". You can use it to identify the methods of a class, and the arguments of the methods.
It absolutely doesn't help you to identify what each method is doing.
In order to find out about that, you would need to either parse the java source code side, or byte code classes. As in: write code that reads that content, and understands "enough" of it to find such places. Which is a very challenging effort. And of course: it is very easy to bypass all such "scanner" code, by doing things such as:
List<String> keysToUpdate = Arrays.asList("key1", "key2");
for (String key : keysToUpdate) {
... does something about each key
Bang. How would you ever write code that reliable finds the keys for that?
When you found that code, now imagine that the list isn't instantiated there, but far away, and past as argument? When you figured how to solve that, now consider code that uses reflection to acquire the model object, and calls method on that. See? For any "scanner" that you write down, there will be ways to make that fail.
Thus the real answer is that you are already going down the wrong rabbit hole:
You should never have written:
Object obj = model.get("mykey");
but something like
Object obj = model.get(SOME_CONSTANT_FOR_KEY_X);
Meaning: there is no good way to control such stuff. The best you can do is to make sure that all keys are constants, coming from a central place. Because then you can at least go in, and for each key in that list of constants, you can have your IDE tell you about their usage.
NOTES
I assumed that your situation is complicated enough that simple or advanced text search in codebase doesn't help you.
This is a hack not a generic solution, designed only for testing and diagnosis purposes.
To use this hack, you must be able to change your code and replace the actual model with the proxy instance while you're testing/diagnosing. If you can't do this, then you have to use an even more advanced hack, i.e. byte-code engineering with BCEL, ASM, etc.
Dynamic proxies have drawbacks on code performance, therefore not an ideal choice for production mode.
Using map for storing model is not a good idea. Instead a well-defined type system, i.e. Java classes, should be used.
A general design pattern for a problem like this is proxy. An intermediate object between your actual model and the caller that can intercept the calls, collect statistics, or even interfere with the original call. The proxied model ultimately sends everything to the actual model.
An obvious proxy is to simply wrap the actual model into another map, e.g.
public class MapProxy<K, V> implements Map<K, V> {
public MapProxy(final Map<K, V> actual) {
}
// implement ALL methods and redirect them to the actual model
}
Now, reflection doesn't help you with this directly, but can help with implementing a proxy faster using dynamic proxies (Dynamic Proxy Classes), e.g.
#SuppressWarnings("unchecked")
private Map<String, Object> proxy(final Map<String, Object> model) {
final InvocationHandler handler = new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// Collect usage stats or intervene
return method.invoke(model, args);
}
};
return (Map<String, Object>) Proxy.newProxyInstance(Map.class.getClassLoader(),
new Class<?>[] { Map.class }, handler);
}
NOTE: Either case you need to be able to replace the actual model with the proxied model at least for the duration of your test.
With another trick, you can find out who called which method of your model. Simply by accessing Thread.currentThread().getStackTrace() and retrieving the appropriate element.
Now puting all the pieces together:
InvocationLog.java
public final class InvocationLog {
private Method method;
private Object[] arguments;
private StackTraceElement caller;
public InvocationLog(Method method, Object[] arguments, StackTraceElement caller) {
this.method = method;
this.arguments = arguments;
this.caller = caller;
}
public Method getMethod() { return this.method; }
public Object[] getArguments() { return this.arguments; }
public StackTraceElement getCaller() { return this.caller; }
#Override
public String toString() {
return String.format("%s (%s): %s",
method == null ? "<init>" : method.getName(),
arguments == null ? "" : Arrays.toString(arguments),
caller == null ? "" : caller.toString());
}
}
ModelWatch.java
public final class ModelWatch {
private final Map<String, Object> modelProxy;
private final List<InvocationLog> logs = new ArrayList<>();
public ModelWatch(final Map<String, Object> model) {
modelProxy = proxy(model);
}
#SuppressWarnings("unchecked")
private Map<String, Object> proxy(final Map<String, Object> model) {
final InvocationHandler handler = new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
log(method, args, Thread.currentThread().getStackTrace());
return method.invoke(model, args);
}
};
return (Map<String, Object>) Proxy.newProxyInstance(Map.class.getClassLoader(),
new Class<?>[] { Map.class }, handler);
}
private void log(Method method, Object[] arguments, StackTraceElement[] stack) {
logs.add(new InvocationLog(method, arguments, stack[3]));
// 0: Thread.getStackTrace
// 1: InvocationHandler.invoke
// 2: <Proxy>
// 3: <Caller>
}
public Map<String, Object> getModelProxy() { return modelProxy; }
public List<InvocationLog> getLogs() { return logs; }
}
To put it in use:
private Map<String, Object> actualModel = new HashMap<String, Object>();
private ModelWatch modelWatch = new ModelWatch(model);
private Map<String, Object> model = modelWatch.getModelProxy();
// Calls to model ...
modelWatch.getLogs() // Retrieve model activity
I used PropertyModel as the part of my DropDownChoice as following:
List<String> choices = Arrays.asList(new String[] { "Library", "School Office", "Science Dept" });
String selected = "Library";
DropDownChoice<String> serviceDDC =
new DropDownChoice<String>("service", new PropertyModel(this, "choices.0"), choices);
Somehow I've got this exception thown:
caused by: org.apache.wicket.WicketRuntimeException: No get method defined for class: class com.samoo.tool.pages.CreatePrintingJob expression: choices
at org.apache.wicket.util.lang.PropertyResolver.getGetAndSetter(PropertyResolver.java:481)
at org.apache.wicket.util.lang.PropertyResolver.getObjectAndGetSetter(PropertyResolver.java:332)
at org.apache.wicket.util.lang.PropertyResolver.getObjectAndGetSetter(PropertyResolver.java:242)
at org.apache.wicket.util.lang.PropertyResolver.getValue(PropertyResolver.java:95)
at org.apache.wicket.model.AbstractPropertyModel.getObject(AbstractPropertyModel.java:130)
at org.apache.wicket.Component.getDefaultModelObject(Component.java:1724)
....
I know that there's something wrong with the expression. I've been trying different parameter inputs but it still doesn't work. Could anyone help?
Since you're using PropertyModel(this, "choices.0"), Wicket is trying to find a property named choices via reflection through a method getChoices() of the class declaring the PropertyModel. This method doesn't seem to exist in com.samoo.tool.pages.CreatePrintingJob, as the exception is stating.
Also, if that 0 is an index, you should be accessing it with the [index] expression, as this JIRA issue suggests: PropertyModel does not support index only property ("[0]")
However, it seems you want to initialize the DropDownChoice to the first element of choices. But What Wicket will do if you set the DropDownChoice's Model to PropertyModel(this, "choices.[0"]) will be mapping the selection of this DropDownChoice in the following way:
At form rendering time to present the (pre)selected choice, it will use the first element in the choices list.
At form submission time to store the user selected value, it will store the selection in the first position of the choices list.
Summarising, the backing object representing the DropDownChoice's selection would be the first element in the choices list.
So, you'll probably want to use a whole different Model, independent from the choices list, for the backing object representing the DDC's selection.
List<String> choices = Arrays.asList(new String[] { "Library", "School Office",
"Science Dept" });
String selected = "Library";
IModel dropdownModel = new Model<String>(choices[0]);
DropDownChoice<String> serviceDDC =
new DropDownChoice<String>("service", dropdownModel, choices);
You might find the following links useful:
Using the DropDownChoice component
Working with Wicket Models
you are declaring choices inside the method, in order to get the PropertyModel to work you need to declare it on a class level not on a method level. As #Xavi López pointed out the espression is not corret you nedd to use choices.[0]
It is good idea to use IModel instead of PropertyMOdel.PropertyModel has big problems in refactoring. In my cases I did it and the problems solved properly.Also I have override the toString() of my Topic object.
topicDropDown = new DropDownChoice<Topic>("topicOptions", new IModel<Topic>() {
#Override
public Topic getObject() {
return top;
}
#Override
public void setObject(Topic t) {
top = t;
}
#Override
public void detach() {
}
}, new LoadableDetachableModel<List<Topic>>() {
#Override
protected List<Topic> load() {
List<Topic> topics = top.getAllTopics();
return topics;
}
});