How to Validate a Collection of annotated objects in XML - java

I was looking over this post of using JSR-303 to validate a collection of objects. The solution works great with annotations, but I can't seem to get it to work with the Hibernate Validator XML formatted configuration.
For example, I have code similar to this:
public class DataSet
{
Collection<Data> dataCollection;
public Collection<Data> getDataCollection() {...}
}
From there, I have a custom validator/annotation DataValidator/#ValidData.
In XML, I do this first:
<bean class="DataSet"
ignore-annotations="true">
<field name="dataCollection">
<valid/>
<constraint annotation="ValidData"/>
</field>
</bean>
However, I get the following exception:
Exception in thread "main" javax.validation.UnexpectedTypeException: No validator could be found for type: java.util.Collection<DataSet>
So I swap the <valid> tag with the <constraint> one in the XML. It seems this is not valid with the XSD schema and the XML can no longer be parsed.
<bean class="DataSet"
ignore-annotations="true">
<field name="dataCollection">
<constraint annotation="ValidData"/>
<valid/>
</field>
</bean>
Exception in thread "main" javax.validation.ValidationException: Error parsing mapping file.
Does anyone know how I can use XML to validate this collection with must custom validator?

The key was adding a class-level constraint annotation in the XML to the Data POJO itself.
<bean class="DataSet"
ignore-annotations="true">
<field name="dataCollection">
<valid/>
</field>
</bean>
<bean class="Data" ignore-annotations="true">
<class>
<constraint annotation="ValidData"/>
</class>
</bean>

Related

Custom Meta atribute in hibernate xml?

What is the purpose of custom meta tags? I have seen them at class level and at property level.
Example of Propery level level:
</property>
<property name="name" column="name" type="string">
<meta attribute="Test"/>
</property>
Example of class level
<class name="mypackage.user" table="user">
<meta attribute="Test"/>
......
....
</class>
How does hibernate use this custom values in meta tag?
In Hibernate, custom meta tags used while generating Java POJOs from hbm config file.
Refer https://docs.jboss.org/tools/archive/3.0.1.GA/en/hibernatetools/html/codegen.html. Note that there is a list of Supported meta tags.

Hibernate 5 and HBM Mapping issue, Schema-validation: missing table

I am taking an existing Java application and working on updating it from Hibernate 3 where we used hbm.xml files for Entity Mappings. We are now using Hibernate 5.5.5.Final and the code compiles with ehcache, but now I get an error with the code when starting to run it.
I should start off that one of the Hibernate properties is:
validate
The error message I am getting now is:
org.hibernate.tool.schema.spi.SchemaManagementException: Schema-validation: missing table [my_db_dev.Project_myTemplateInfos]
at org.hibernate.tool.schema.internal.AbstractSchemaValidator.validateTable(AbstractSchemaValidator.java:121)
at org.hibernate.tool.schema.internal.GroupedSchemaValidatorImpl.validateTables(GroupedSchemaValidatorImpl.java:42)
at org.hibernate.tool.schema.internal.AbstractSchemaValidator.performValidation(AbstractSchemaValidator.java:89)
at org.hibernate.tool.schema.internal.AbstractSchemaValidator.doValidation(AbstractSchemaValidator.java:68)
at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.performDatabaseAction(SchemaManagementToolCoordinator.java:200)
at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.process(SchemaManagementToolCoordinator.java:81)
at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:327)
at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:471)
I would love to completely remove all the hbm.xml files and replace with them with Entity Mapping POJO's with annotations, however, that is not an option right now. The existing application has this different object model that goes throughout, so I don't want to mess with that right now. That will be in the next phase.
According to the error I am missing a table named 'Project_myTemplateInfos' and there is no table with this name. Instead, there is a table named 'Project' and the hbm.xml file for this is as follows.
<hibernate-mapping package="com.myApp.server.model">
<class name="Project" table="project" dynamic-update="true">
<id name="id" column="id">
<generator class="native" />
</id>
<property name="name" not-null="true"/>
<property name="displayCity" not-null="true"/>
<list name="myTemplateInfos" cascade="all, delete-orphan" lazy="false" >
<key column="projectId" not-null="false" />
<list-index column="listIndex" />
<composite-element class="com.myApp.server.model.MyTemplateInfo" >
<property name="name" not-null="false" />
<property name="frequency" not-null="false" />
</composite-element>
</list>
</class>
</hibernate-mapping>
As you can see 'myTemplateInfos' is a List within the Project table. After the POJO is created, it looks like something like this.
#ModelBean(IProject.class)
#PermissionIdentifier("project")
public class Project extends ModelObject implements Serializable, IProject {
private Long id;
private String displayCity = "";
private List<IMyTemplateInfo> myTemplateInfos = Lists.newArrayList();
// getters and setters
// hashcode and equals
}
Next we do have another table in the database that is called 'myTemplateInfos' and we do have an hbm xml file for that table as follows ... actually we do not have an hbm xml file for this, so maybe that is the issue. I am going to create a hbm xml file for this and see if that solves the problem.
We do have a POJO for this object 'MyTemplateInfo' though.
If I simply remove his List from the hbm mapping and the Project object, the problem goes away of course, but there is another Set in the hbm.xml file which would give me the same problem, but with a new missing table.
The question becomes how to fix this error message. Is the problem within the hbm xml file for 'Project', or is it in the Project POJO, or the fact that an hbm file does not exist for the 'MyTemplateInfo'?
The solution to this was to fix the hbm xml mapping. Since I haven't had to do this in over 15 years, I am very rusty with it. I can't tell you how happy I was back then to switch to Java POJO's for Hibernate Entity classes with Annotations. But now, unfortunately, I am back having to deal with these xml files again.
The table I had 'mycommunitytemplateinfos' I created a new hbm xml file for it as follows, and put this in the hibernate.cfg.xml file before the other hbm xml mapping.
<hibernate-mapping package="com.myapp.server.model">
<class name="MyTemplateInfo" table="mytemplateinfos">
<id name="id" column="projectId">
<generator class="native"/>
</id>
<property name="name" not-null="false" />
<property name="frequency" not-null="false" />
</class>
</hibernate-mapping>
The mapping between this and the actual class is fine as I have tested this out. I put the hbm file in the hibernate.cfg.xml file before the Project.hbm.xml file and modified the Project.hbm.xml with a one-to-many tag as follows:
<list name="myTemplateInfos" cascade="all, delete-orphan" lazy="false" >
<key column="projectId" not-null="false" />
<list-index column="listIndex" />
<one-to-many class="com.myApp.server.model.MyTemplateInfo" />
</list>
And this seemed to work. I had to do something like this a few times until I got the mapping right. In this day of age, there isn't a lot of information about hbm xml files. Hibernate 5 does use these, but I understand that the preferred way is annotated Java POJO's. Unfortunately, I am stuck in a situation where I can't do that yet.

How to remove namespace from Jaxb2 generated xml

I have a problem a little problem related to the namespaces in the XML marshalled by Jaxb2 . When I print out the xml file, I get this "extra" annotations on the xml tags. Is there any way to get rid of the extra namespace annotations ?
Here is an example:
<?xml version="1.0" encoding="UTF-8" standalone="yes">
<root xmlns:ns2="http://www.something.com/something">
<ns2:food>steak</ns2:food>
<ns2:beverage>water</ns2:beverage>
</root>
I want to get rid of the ns2: namespace.
I tried with :
<bean id="glsJaxb2Marshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
<property name="contextPath" value="${gls.jaxb2.contextpath}"/>
<property name="marshallerProperties">
<map>
<entry key="com.sun.xml.bind.namespacePrefixMapper">
<bean class="es.fs.fswarehousing.gls.ws.EmptyNamespacePrefixMapper"/>
</entry>
</map>
</property>
</bean>
But im getting :
ERROR [TaskExecutor-master-555-ProcessTask [8796749431734]]
[ActionNode] Error executing
org.springframework.oxm.UncategorizedMappingException: Unknown JAXB
exception; nested exception is javax.xml.bind.PropertyException: name:
com.sun.xml.bind.namespacePrefixMapper value:
es.fs.fswarehousing.gls.ws.EmptyNamespacePrefixMapper#17f6a8fe
Can someone give me any hint :) ?

javax.validation.ValidationException: %class% has already be configured in xml

There's a bean validation in a project's jar which validation.xml contains field-level validation of Address bean.
The other project uses Address class and needs to have specific Address validation. So extended-validation.xml was created with class-level validation of Address bean.
As a result, during the app deployment, ValidationException occures: javax.validation.ValidationException: my.base.datatypes.Address has already be configured in xml..
Here are two validation xml files with basic validation and "extended validation".
validation.xml
<bean class="my.base.datatypes.Address" ignore-annotations="true">
<getter name="country">
<constraint annotation="my.imp.services.validation.ValidCode">
<message>{msg01}</message>
<groups>
<value>my.imp.services.validation.ImportGroup</value>
</groups>
<element name="name">Country</element>
</constraint>
</getter>
</bean>
extended-validation.xml
<bean class="my.base.datatypes.Address" ignore-annotations="true">
<class ignore-annotations="true">
<constraint annotation="my.extended.imp.services.validation.ValidAddress">
<message>ERROR DURING ADDRESS VALIDATION</message>
<groups>
<value>my.imp.services.validation.ImportGroup</value>
</groups>
</constraint>
</class>
</bean>
Is it possible to extend already existing validation?
The solution appears to be very simple and trivial. If you want to extend validation rules, use different validator which will load extended-validation.xml constraints configuration. In this case, base validator validates data according to validation.xml config, and another validator validates data according to extended-validation.xml config. So no more config collisions occur.

Java Castor Unmarshal byte array

Good Day Community,
I have a question regarding castor unmarshaling in java. As mentioned I am using castor to unmarshal a webservice response that contains a byte array (byte[])
.. please refer to below:
public class ViewReportResponse {
private String reportId;
private byte[] report;
//getters and setters here ...
I have used castor before to unmarhsal webservice responses, but admittedly, the responses previously where always strings. The problem lyes with the byte array returned as I believe castor chokes on unmarshaling it.
My castor-mapping file is provided below:
<class name="com.domain.reporting.client.service.ViewReportResponse">
<map-to xml="viewReportResponse"
xsi:schemaLocation="http://domain.com/schemas/reportingService/generateReport"
ns-uri="http://domain.com/schemas/reportingService/generateReport"
ns-prefix="ns2" />
<field name="reportId">
<bind-xml name="reportId"
node="element"
type="string"/>
</field>
<field name="report">
<bind-xml name="report"
node="element"
type="bytes" />
</field>
I'm not sure what I am missing, but the message is received but fails at the point of unmarshaling.
I've attached a clip of the error below.
org.springframework.oxm.UnmarshallingFailureException: Castor unmarshalling exception; nested exception is org.exolab.castor.xml.MarshalException: unable to find FieldDescriptor for 'report' in ClassDescriptor of viewReportResponse.
Please any assistance is much appreciated.
Thank-you kindly
Solved:
The general problem is not the maping to and from the byte[]. The problem is related to the use of namespace in this case.
<field name="reportId">
<bind-xml name="ns:reportId" xmlns:ns="http://domain.com/schemas/reportingService/generateReport"
node="element"
type="string"/>
<field name="report">
<bind-xml name="ns:report" xmlns:ns="http://domain.com/schemas/reportingService/generateReport"
node="element"
type="bytes"/>
This post is now effectively solved and closed.

Categories

Resources