ZK MVVM Validation - Dependent Property Array content? - java

I'm playing around with the ZK 8 MVVM form validation system and generally it seems to do what I want, but I wonder what the definition of the dependent property index is...
Let's take a simple validator...
public class FormValidator extends AbstractValidator {
#Override
public void validate(final ValidationContext ctx) {
Property[] properties = ctx.getProperties("firstName");
Object value0 = properties[0].getValue();
Object value1 = properties[1].getValue();
}
}
So, when this is called before the save command, for every property, I get a Property[] array of length 2. But somehow, I have yet to find out what is stored in [0] and what is stored in [1]. Sometimes it seems that [0] stores the current value (which may or may not be valid according the field validator there) and [1] the last valid entry... But sometimes it seems to be the other way round...
The examples in the documentation always seem to simply take the first element ([0]) for validation, but I would like the understand what both parts of this pair actually mean...
Anyone got an idea for that?

I might be off the mark with my answer, but if you are using ZK8, you should look into using Form binding
That way you do not have to handle Properties in your validator and can retrieve a proxy object matching the bean you use for your form.
If you are using a User POJO with a firstName and lastName attribut.
User myProxy= (User ) ctx.getProperty().getValue();
And then you can validate both fields by simply doing getFirstName and getLastName on myProxy.
Hope it helps.

Related

Reading CSV data in Spring Batch (creating a custom LineMapper)

I've been doing a bit of work writing some batch processing code on CSV data. I found a tutorial online and so far have been using it without really understanding how or why it works, which means I'm unable to solve a problem I'm currently facing.
The code I'm working with is below:
#Bean
public LineMapper<Employee> lineMapper() {
DefaultLineMapper<Employee> lineMapper = new DefaultLineMapper<Employee>();
DelimitedLineTokenizer lineTokenizer = new DelimitedLineTokenizer();
lineTokenizer.setNames(new String[] { "id", "firstName", "lastName" });
lineTokenizer.setIncludedFields(new int[] { 0, 1, 2 });
BeanWrapperFieldSetMapper<Employee> fieldSetMapper = new BeanWrapperFieldSetMapper<Employee>();
fieldSetMapper.setTargetType(Employee.class);
lineMapper.setLineTokenizer(lineTokenizer);
lineMapper.setFieldSetMapper(fieldSetMapper);
return lineMapper;
}
I'm not entirely clear on what setNames or setIncludedFields is really doing. I've looked through the docs, but still don't know what's happening under the hood. Why do we need to give names to the lineTokenizer? Why can't it just be told how many columns of data there will be? Is its only purpose so that the fieldSetMapper knows which fields to map to which data objects (do they all need to be named the same as the fields in the POJO?)?
I have a new problem where I have CSVs with a large amount of columns (about 25-35) that I need to process. Is there a way to generate the columns in setNames programmatically with the variable names of the POJOs, rather than editing them in by hand?
Edit:
An example input file may be something like:
test.csv:
field1, field2, field3,
a,b,c
d,e,f
g,h,j
The DTO:
public class Test {
private String field1;
private String field2;
private String field3;
//setters and getters and constructor
I see the confusion, so I will try to clarify how key interfaces work together. A LineMapper is responsible for mapping a single line from your input file to an instance of your domain type. The default implementation provided by Spring Batch is the DefaultLineMapper, which delegates the work to two collaborators:
LineTokenizer: which takes a String and tokenizes it into a FieldSet (which is similar to the ResultSet in the JDBC world, where you can get fields by index or name)
FieldSetMapper: which maps the FieldSet to an instance of your domain type
So the process is: String -> FieldSet -> Object:
Each interface comes with a default implementation, but you can provide your own if needed.
DelimitedLineTokenizer
The names attribute in DelimitedLineTokenizer is used to create named fields in the FieldSet. This allows you to get a field by name from the FieldSet (again, similar to ResultSet methods where you can get a field by name). The includedFields allows to select a subset of fields from your input file, just like in your use case where you have 25 fields and you only need to extract a subset of fields.
BeanWrapperFieldSetMapper
This FieldSetMapper implementation expects a type and uses the JavaBean naming conventions for getters/setters to set fields on the target object from the FieldSet.
Is there a way to generate the columns in setNames programmatically with the variable names of the POJOs, rather than editing them in by hand?
This is what the BeanWrapperFieldSetMapper will do. If you provide field names in the FieldSet, the mapper will call the setter of each field having the same name. The name matching is fuzzy in the sense that it tolerates close matches, here is an excerpt from the Javadoc:
Property name matching is "fuzzy" in the sense that it tolerates close matches,
as long as the match is unique. For instance:
* Quantity = quantity (field names can be capitalised)
* ISIN = isin (acronyms can be lower case bean property names, as per Java Beans recommendations)
* DuckPate = duckPate (capitalisation including camel casing)
* ITEM_ID = itemId (capitalisation and replacing word boundary with underscore)
* ORDER.CUSTOMER_ID = order.customerId (nested paths are recursively checked)
This mapper is also configurable with a custom ConversionService if needed. If this still does not cover your use case, you need to provide a custom mapper.

How can I put a bean object to sessionMap, and then retrieve its properties on jsp page using Struts 2 property tag

In login Action I am checking user authentication, and if it is validated, I am putting the user bean into sessionMap:
public String execute()
{
if(userValid)
sessionMap.put("userBean", userBean); //userBean retrieved from DB
}
Now on the landing jsp, when trying to retrieve the session items:
<s:property value="#session.userBean.name" />
Obviously this would return an Object type, as I am storing it that way, so how can I type caste this to UserBean class.
I was expecting to get a solution for this on Google, but found it nowhere since this seems to be a basic implementation. So please let me know if there is any other way to implement this functionality using Struts2.
This works fine for me...
<sp:property value="#session.usertype"/>
<sp:property value="#session.bean.loginID"/>
This both worked fine for me...
sessionMap.put("bean", loginBean);
sessionMap.put("usertype", loginBean.getUserType());
I declared something like this....
Just make sure that in property tag you you same name you used while setting the bean in sessionMap ....
This should probably work....
Obviously you can't cast it to UserBean class if the object is not the instance of that class. In the value attribute you have put a string "#session.userBean.name". Struts parse this string for OGNL expression and if it's a valid expression that returns a value, it will replace it with that value. The returned type is Object, but this type is determined by ValueStack implementation.
Then property tag writes this object to the out. It uses toString() to convert the object to string. And if your object implements this method, then this value would be written.
Looks like your expression returns an Object, which has instance type String, so it's already implemented this method.

Java Soap Services: Add non-persistent result field based on a persistent one

So I need to add a new field to a SOAP service response. The thing is that the field has to take the value from a persistent field. I cannot add that persistent field directly. The persistent field returns a "Calendar" instance, which is, in fact, a DATETIME from MySQL. The current object uses the XmlAdapter.
I did something like this:
class SomeClassImpl extends SomeClass
{
#Transient
#XmlSchemaType(name="someDate")
private String someDate;
...
public void defSomeDate()
{
this.someDate = this.getPersistentDate().toString();
}
public String retSomeDate()
{
return this.someDate();
}
}
The new field appears in the soap result, but the value is an exception, which I don't remember right now and I am not able to reproduce it now.
How would you do this? Is it possible to annotate a method instead of the member so it appears in the SOAP result? If yes, how would an annootation would look like?
Thank you in advance!
The problem was the following piece of code:
#XmlSchemaType(name="someDate")
There "name" parameter should be one of the standard data types for xml. In this case, because it contains the date and the time, it should be 'dateTime'. It could also be a string, but declaring it as dateTime makes the field more restrictive. Therefore, the correct annotation is:
#XmlSchemaType(name="dateTime")
With the date and time in mind, the second observation is that private String someDate; should be private CalendarsomeDate;, to be consistent and also for the actual code to work.
Annotating the methods is not required. Simply annotating the member/property is enough and as long as the member/property is set somewhere at runtime.
I hope this would be helpful for someone else too. It took me few hours to get this, but now I know how to proceed in the future.

Map as parameter for all fields for EJB backend calls

I am designing backend EJB calls to be called by REST api.
Example for EJB calls;
Get all Systems
getSystems(String systemId)
Now I know that i would get system id to get all systems.
There is a possibility of retrieving them by some another unique id as well
getSystemsByOtherId(String otherId)
There is requirement that there could be sort parameter passed in
getSystems(String systemId, String sort_by, String sort_how)
Would it be better to have something like Map as param and have it passed in with every information
getSystems(Map criteria)
So the key- value pair for Map would have systemId, otherId, sort_by, sort_how and more if needed in future. Or is it better to follow other approach to have unique methods for different params. Or if there is some other better approach.
Thank you.
The first solution is a little cumbersome, in case you want to add or remove parameters you'd have to modify the signature of your EJB every time, the map solution is a little dirty since you'd have to keep track of your parameters names at runtime and if you want to use parameters of a type other than String you'd lose typing info at runtime as well.
This is how I would do it, define a class that encapsulates your parameters:
public class Criteria {
private String systemId;
private String otherId;
private String sortBy;
private String sortHow;
.
.
.
}
and in your EJB,
getSystem(Criteria criteria)

jXPath quering attribute in super class

I have a couple of domain classes which all inherit a BaseDomain class.
In this BaseDomain class I have a field that is public final String name;
The value of name is set in the constructor.
public class BaseDomain {
public final String name;
public BaseDomain() {
this.name = this.getClass().getCanonicalName();
}
}
This BaseDomain is extended by a few classes
public class Trip extends BaseDomain {
private int id;
public Trip(int id){
this.id = id;
}
}
So far so good.
I want to get the value of the field "name" in an object instance of Trip of a with the help of JXPath but can't. I can access the "id" field but not the "name" field.
JXPathContext jxPathContext = JXPathContext.newContext(trip);
jxPathContext.setLenient(true);
int id = (int)jxPathContext.getValue("/#id"); // This works.
String name = (String)jxPathContext.getValue("/#name"); // This does not work.
Is it possible to get the value of "name" with this setup and JXPath?
The code might have some syntax errors and/or other errors. I hope you all get the idea and understand my question.
Any help or pointer are welcome.
First of: I want to thank Kelly S. French for his quick replay.
It made me realize that I have to explain some more.
I want to use jxpath because I will eventually do a deeper search. For example: The Trip might hold a list of Locations which also extends the BaseDomain. Each Location can hold a list of PointOfInterest that extends BaseDomain.
Via reflection in other part of the code I want to be able to get a list of BaseDomain based on their type (class.getCanonicalName())
The object-tree is not based on xml, it is pure POJO.
As far as I have figured out, there is no way of writing a jxpath-query for finding a list of objects based on their type, class name and so on.
Is this correct?
Does some one know of a way to do that?
The easiest way out, even if it's ugly, is to have a field in the super class that holds the class-name. That is why I have done this ugly solution.
Eventually I want to create a jxpath-query that based on the trip returns an iterator of which ever object that is an instance of BaseDomain at any depth and not depending on which branch in the object tree the node is located, as long as I can get the class-name of the object I'm looking for.
Does any one know if it is possible to achive this with a jxpath-query?
Code example, links to blogs or other documentation is welcome and appreciated.
As before, I'm very grateful for any help.
if you have the trip instance, why can't you do this
string n = trip.name;
I can see that you have an XML representation of the trip, but using XPath would be for when you only have the XML for 'trip'.
If you still need to get name using XPath, post the XML that is generated. I would be willing to bet that the name attribute is not part of Trip, but part of the enclosing BaseDomain. If you are basing the jxPathContext on the Trip, you've already passed the nodes for the BaseDomain. You'd have to navigate back up somehow (like node.parent) or do that when you create the context,
// not sure about this approach
JXPathContext jxPathContext = JXPathContext.newContext(trip.super);
After looking at the JXPath manual on parent/child relationships why don't you try this:
String name = (String)jxPathContext.getValue("/Trip/../#name");
// or use "../#name", not sure it wouldn't need to be "/../#name"

Categories

Resources