JAXB unmarshalling inner class - java

Suppose I have some POJO class that can be stored in my DB.
class SomeClass {
private String name;
private String surname;
private Address address;
//getters and setters
}
In this class, I have some inner class that defines some location.
class Address {
private String country;
private String city;
//getters and setters
}
My task - to collect some information from external sources using XML with different schemas e.g.:
schema1:
<someClass>
<first>John</first>
<last>Blue</last>
<location>Country, City, 123456</location>
</someClass>
schema2:
<someClass>
<credentials>John Blue</credentials>
<address>Country, City</p1>
<p>123456</p>
</someClass>
and so on.
For this task I'm using JAXB and inheritance for each schema, every object I define as #XmlElement with name and this works ok with simple strings and even with location with appropriate #XmlJavaTypeAdapter. But I have problems when parent class has the same element as inherited, but different type, e.g:
<someClass>
<credentials>John Blue</credentials>
<address>Country, City</p1>
<p>123456</p>
</someClass>
class InheritedClass extends SomeClass {
#Override
#XmlElement(name = "address")
public void setAddress(String address) {
//do some work to parse string to Address.class
//also i tried to use XmlJavaTypeAdapter for this method(with Address.class)
//also i tried to use XmlElementRef for Address.class
super.setAddress(addressClass);
}
}
When I'm trying to unmarshal such schema JAXB avoid my overridden method and uses parent with null Address object. I've tried such solutions:
#XmlElementRef
http://blog.bdoughan.com/2010/11/jaxb-and-inheritance-using-substitution.html
static inner #XmlJavaTypaAdapter http://blog.bdoughan.com/2012/01/jaxb-and-inhertiance-using-xmladapter.html
The main problem that I cannot modify external XML, only adapts it for my purposes. Also, i cannot modify POJO class because it store in DB and a have a lot of external XML's (so a lot of JAXB entities to unmarshal and adapt).

Related

How to generate Entity classes from Java Model (dto) classes

I have a Java Bean class which has some attributes having some Object type as datatype. Again that Object is having attributes which is again have some Object datatype and so on...
public class MyService {
private String id;
private String href;
private Category category;
}
public class Category {
private String id;
private Type type;
}
public class Type {
private String id;
private SomeObject someObject;
}
so on ...
Now I want to create JPA Entity classes for the class MyService with all the Mappings (OneToMany etc.). I know from database table we can generate the Entity classes but can we do it from the Java bean classes?
Because if I do manually it will take much time. So please suggest if I can generate those Entity classes or some other alternative ways instead of manually creating those Entity classes.

MongoDB map Java POJO without org.bson.types.ObjectId

I want to map Java POJO to MongoDB and implement CRUD operations. I follow manual https://mongodb.github.io/mongo-java-driver/3.11/driver/getting-started/quick-start-pojo/ and all seems fine but one Person property is MongoDB dependent:
public final class Person {
private ObjectId id;
private String name;
private int age;
private Address address;}
This is org.bson.types.ObjectId id. This makes my domain layer dependent on MongoDB, and this actually what I would not call a POJO at all. Instead of ObjectId I would like to have String or other Java core class like Long or something like that. It could could be a kind of getter/setter too. How can I achieve this?
I tried to remove id from Person
package com.mongo_demo.domain;
public final class Person {
private String name;
private int age;
private Address address;}
and use this as my domain object, while to operate with MongoDB in DAO I will use child class:
package com.mongo_demo.mongo_domain;
public final class Person extends com.mongo_demo.domain.Person {
private ObjectId id;
}
Obviously my domain class now not have dependencies on MongoDB, but still lacks String id and no way to have getter method for it, as ObjectId id attribute is in child class.
I not sure is it fine to not have access to id value in my services code, because I could need to call delete by id operation, otherwise I will have to create my own object unique identifier, in addition to ObjectId id attribute, which will be natural key with consequent drawbacks.
PS No getter-setter methods shown, as I use Lombok #Data annotations instead.

does not have a corresponding accessor for data binding Play framework 2.5.3

I want to save user data to database. play version 2.5.3
I am getting this error:
JSR-303 validated property 'first_name' does not have a corresponding accessor for data binding - check your DataBinder's
configuration (bean property versus direct field access)]
My model class
#Entity
public class UserRegisterModel extends Model
{
#Id
#GeneratedValue
protected Long ID;
#Constraints.Required
protected String first_name;
protected String last_name;
protected String user_name;
#Constraints.Required
protected String password;
protected String password_confirmation;
#Constraints.Email
#Column(unique = true)
protected String email;
}
Controller class
public Result submitUserRegistrationForm()
{
play.data.Form<UserRegisterModel> form = play.data.Form.form(UserRegisterModel.class).bindFromRequest();
UserRegisterModel register = form.bindFromRequest().get();
}
Also I want to match password and conform password. I should do this in Model or controller.
Could you please provide me some sample code(Model,Controller) with form validation?
As discussed at the comments, you have to add play-enhancer as documented here:
https://www.playframework.com/documentation/2.5.x/PlayEnhancer#Setting-up
Also, the enhancer just works under the following conditions:
The enhancer looks for all fields on Java classes that:
are public
are non static
are non final
For each of those fields, it will generate a getter and a setter if they don’t already exist. If you wish to provide a custom getter or setter for a field, this can be done by just writing it, the Play enhancer will simply skip the generation of the getter or setter if it already exists.
So, you have two options here: keep the fields protected and write your own getters and setters or made the public and let the enhancer generate getters and setters required by other libraries (like form binding).

Inheritance with JAXB (unmarshalling)

I have many entities with common properties. There is no xml schema, so I write jaxb entities on my own.
abstract class SuperEntity {
protected String id;
protected String name;
#XmlElement
public void setId() { .. sets Id .. }
#XmlElement
public void setName() { .. sets name .. }
}
// id and name are null after deserialization .. they are completely ignored
// there are other entities such as this, I don't want to repeat my code
#XmlRootElement
#XmlSeeAlso({SuperEntity.class})
class SpecificEntity extends SuperEntity {
protected String specificField;
#XmlElement
public void setSpecificField() { .. sets specific field .. }
}
SuperEntity is not deserialized (unmarshelled) at all, leaving fields null. If i copy fields and setters from superclass to specific class, it works, but I dont want to just copy that code to every child entity. Thank you for your help.
Change the class definitions to
#XmlRootElement
#XmlSeeAlso({SpecificEntity.class})
abstract class SuperEntity {
#XmlRootElement
class SpecificEntity extends SuperEntity {
When JAXB is processing a class model it will also process super classes (the ones not annotated with #XmlTransient). By default it won't process subclasses. The #XmlSeeAlso needs to go on the super class and reference the subclasses.

Using embedded nested class to represent complicated state in JPA

I am trying to use an inner class as embeddable to represent some complicated properties of the outer class. When I store this, there is no information from the inner class in the database schema generated by eclipselink.
Does what I'm trying to do seem like a good idea? Why doesn't eclipselink seem to recognize them #Basic attribute on the getRate() in Attributes?
Some other info: Measure must be instantiated using a factory which is provided to the constructor of Person, so I don't even know how I'm going to be able to use this at all. It seems more and more likely that I'll have to make a separate class just to store the state of Person in simple terms (like doubles, not Measures) and use those to create the real Person-type objects, but that has very sad implications for the rest of my application.
#Entity
public static class Person {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
#Transient
public Measure<Double, CleanupRate> rate;
#Embedded
private Attributes attributes;
#Embeddable
public static class Attributes {
#Transient
private Person person;
public Attributes() {
}
public Attributes(Person person) {
this.person = person;
}
#Basic
public double getRate() {
return person.rate.getInternalValue();
}
public void setRate(double value) {
person.rate.setInternalValue(value);
}
}
public Person() {
rate = udm.getMeasureFactory().createMeasure(0.0, CleanupRate.class);
attributes = new Attributes(this);
}
public void setRate(double rate) {
this.rate.setValue(rate);
}
}
Edit:
In order to inject the measure dependency into my objects when they are retrieved from storage, I've added an interface which injects the dependency and used it in my DAO. Since the DAO can be injected, I can propagate the dependency down to the retrieved objects. I got the idea from a blog.
private <T extends UomInjectable> List<T> //
getListOfUomInjectableType(final Class<T> klass) {
List<T> result = getListOfType(klass);
for (UomInjectable injectable : result) {
injectable.injectUomFactory(udm);
}
return result;
}
It is using the access type from the Person class, which is set to field, and so not seeing the annotation at the property level.
You will need to change the access type using Access(PROPERTY) on the embeddable class, and should remove the #Transient annotation on the person attribute.
I think in general you're going to be in trouble having Entities (Embeddable or otherwise) that need constructors with arguments. I'm not sure how that might be related to your schema generation issue, but I think this will be a problem trying to persist/retrieve these objects.
As you hinted, JPA requires all entity types to have a no-argument constructor. While your Attributes class has one, it leaves the 'person' field as null which will fairly quickly result in NPE's. Same with the Person constructor (maybe you left out the one that passes in 'udm' from the sample code?).
The set the Person for the Attributes, just use property access in Person and set it in your setAttributes method.
See,
http://en.wikibooks.org/wiki/Java_Persistence/Embeddables#Relationships

Categories