JAXB and constructors - java

I'm starting learning JAXB, so my question can be very silly. Now I have classes and want generate XML Schema. Going after this instruction I get exception
IllegalAnnotationExceptions ... does not have a no-arg default
constructor.
Yeah. My classes haven't default no-arg constructors. It's too easy. I have classes with package visible constructors / final methods and off course with arguments. What shall I do - create some specific momemto/builder classes or specify my constructors to JAXB (in what way?) ? Thanks.

JAXB can support this case using an XML Adapter. Consider you have the following object with no zero-arg constructor:
package blog.immutable;
public class Customer {
private final String name;
private final Address address;
public Customer(String name, Address address) {
this.name = name;
this.address = address;
}
public String getName() {
return name;
}
public Address getAddress() {
return address;
}
}
You simply need to create a mappable version of this class:
package blog.immutable.adpater;
import javax.xml.bind.annotation.XmlAttribute;
import blog.immutable.Address;
public class AdaptedCustomer {
private String name;
private Address address;
#XmlAttribute
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
}
And an XML Adapter to convert between them:
package blog.immutable.adpater;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import blog.immutable.Customer;
public class CustomerAdapter extends XmlAdapter<AdaptedCustomer, Customer> {
#Override
public Customer unmarshal(AdaptedCustomer adaptedCustomer) throws Exception {
return new Customer(adaptedCustomer.getName(), adaptedCustomer.getAddress());
}
#Override
public AdaptedCustomer marshal(Customer customer) throws Exception {
AdaptedCustomer adaptedCustomer = new AdaptedCustomer();
adaptedCustomer.setName(customer.getName());
adaptedCustomer.setAddress(customer.getAddress());
return adaptedCustomer;
}
}
Then for properties that refer to the Customer class, simply use the #XmlJavaTypeAdapter annotation:
package blog.immutable;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import blog.immutable.adpater.CustomerAdapter;
#XmlRootElement(name="purchase-order")
public class PurchaseOrder {
private Customer customer;
#XmlJavaTypeAdapter(CustomerAdapter.class)
public Customer getCustomer() {
return customer;
}
public void setCustomer(Customer customer) {
this.customer = customer;
}
}
For a more detailed example see:
http://bdoughan.blogspot.com/2010/12/jaxb-and-immutable-objects.html

You can use the annotation #XmlType and use factoryMethod / factoryClass attributes in various combinations such as:
#XmlType(factoryMethod="newInstance")
#XmlRootElement
public class PurchaseOrder {
#XmlElement
private final String address;
#XmlElement
private final Customer customer;
public PurchaseOrder(String address, Customer customer){
this.address = address;
this.customer = customer;
}
private PurchaseOrder(){
this.address = null;
this.customer = null;
}
/** Creates a new instance, will only be used by Jaxb. */
private static PurchaseOrder newInstance() {
return new PurchaseOrder();
}
public String getAddress() {
return address;
}
public Customer getCustomer() {
return customer;
}
}
Surprisingly this works and you get an initialized instance when unmarshalling. You should make note not to call the newInstance method anywhere on your code as it will return an invalid instance.

You should have a default constructor for JAXB to be able to instantiate your classes. Maybe there is a workaround I don't know though.
JAXB is especially fitted for bean-like classes, permitting to configure objects by calling setters on them.

JAXB re-creates beans from XML in a simple fashion : it creates a new instance of the bean, and then do all the setXXX needed to set the attributes. So, if your bean doesn't have a no-args constructor, JAXB can't create it. As said in other answers, JAXB works better for simple "container" beans, for which no-args constructor isn't really a problem. If you're trying to create beans that need specific initialization, you'll need to do it in the setXXX methods.

Related

How to fix " Failed to instantiate 'className' using constructor NO_CONSTRUCTOR with arguments" in immutable class

I use MongoDBRepository in spring boot, and when I save some object in database everything is ok. but when I find object by id spring does not allow do that.
I try to change VehicleRoutingProblemSolution type to Object type, but VehicleRoutingProblemSolution have other object field PickupService and it without default constructor to. And yes, this class has immutable... I can't create default constructors, what can I do?
import com.fasterxml.jackson.annotation.JsonProperty;
import com.graphhopper.jsprit.core.problem.solution.VehicleRoutingProblemSolution;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
#Document(collection = "vrp_solutions")
public class VrpSolutionHolder {
// Specifies the solution id
#Id
#JsonProperty("id")
private String id;
// Specifies the solution id
#JsonProperty("solution")
private VehicleRoutingProblemSolution vehicleRoutingProblemSolution;
// Created at timestamp in millis
#JsonProperty("created_at")
private Long created_at = System.currentTimeMillis();
public VrpSolutionHolder(String id, VehicleRoutingProblemSolution vehicleRoutingProblemSolution) {
this.id = id;
this.vehicleRoutingProblemSolution = vehicleRoutingProblemSolution;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public VehicleRoutingProblemSolution getVehicleRoutingProblemSolution() {
return vehicleRoutingProblemSolution;
}
public void setVehicleRoutingProblemSolution(VehicleRoutingProblemSolution vehicleRoutingProblemSolution) {
this.vehicleRoutingProblemSolution = vehicleRoutingProblemSolution;
}
public Long getCreated_at() {
return created_at;
}
public void setCreated_at(Long created_at) {
this.created_at = created_at;
}
}
org.springframework.web.util.NestedServletException: Request
processing failed; nested exception is
org.springframework.data.mapping.model.MappingInstantiationException:
Failed to instantiate
com.graphhopper.jsprit.core.problem.solution.VehicleRoutingProblemSolution
using constructor NO_CONSTRUCTOR with arguments
I ran into the exact same problem. A persistent immutable class containing other class instances, throwing that aforementioned exception when retrieved by this repository method:
public interface ProjectCodeCacheRepository extends MongoRepository<CachedCode, String> {
public CachedCode findByCode(String code);
public List<CachedCode> findByClientId(UUID clientId);
}
...
List<CachedCode> cachedForClient = this.codeCacheRepo.`**findByClientId**`(clientId);
...
Following Erwin Smouts hints, this is nicely fixed by giving it a special constructor annotated org.springframework.data.annotation.PersistenceConstructor like so:
#Document(collection="cachedcodes")
public class CachedCode {
#PersistenceConstructor
public CachedCode(String code, UUID clientId, LocalDateTime expiration) {
this.code = code;
this.clientId = clientId;
this.expiration = expiration;
}
public CachedCode(String code, UUID clientId, long secondsExpiring) {
this.code = code;
this.clientId = clientId;
this.expiration = LocalDateTime.now().plusSeconds(secondsExpiring);
}
public UUID getClientId( ) {
return this.clientId;
}
public String getCode() {
return this.code;
}
public boolean hasExpired(LocalDateTime now) {
return (expiration.isBefore(now));
}
...
#Id
private final String code;
private final UUID clientId;
private final LocalDateTime expiration;
}
So, you should check if your VehicleRoutingProblemSolution has a) a constructor that matches the database fields (check in mongo client) and b) is annotated to be the one used by the driver (or whichever piece of Spring magic under the hood).
If your framework tool requires (visible) no-arg constructors (plus accompanying setters), and the class you have is required to stay as is, then you could roll your own, say, MutableVehicleRoutingProblemSolution where in the setters you could have :
this.vehicleRoutingProblemSolution = new VehicleRoutingProblemSolution(vehicleRoutingProblemSolution.getId(), newSolution);
Thus your MutableVehicleRoutingProblemSolution wraps around the existing VehicleRoutingProblemSolution.
Hacky smell to it, but it fits the requirements.
(Or you could try to find a tool that is able to use, not annotations on the contained fields, but annotations on constructor arguments.)
This is a problem where the corresponding class does not have a no-arg constructor like - I was facing an issue with java.io.File.
Solution:
In general - change the declaration to Object class and convert where we are using the class.
from
class MyClass{
File myfile;
}
to
class MyClass{
Object myFile;
}
For anyone using lombok, you need to remove the #Builder annotation on your class and use #Data instead, or follow the above solution to provide a specialized constructor
Oddly, I received this when I attempted to decorate a custom interface with ...
#Document(collection = "Person")
Example:
package test.barry.interfaces;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.UpdateDefinition;
#Document(collection = "Person")
public interface CustomRepository
{
void updatex(Query filterPredicate, UpdateDefinition updatePredicate);
}

How can JAXB be used to map attributes on an element to fields of an intrinsic property of a POJO?

Let's pretend I have the following XML:
<company name="Sun" country="Atlantis" state="Syracuse" city="Troy">
</company>
With JAXB, and without using third-party extensions such as EclipseLink's #XmlPath, is there a way to unmarshall it into the following POJO structure:
#XmlRootElement
public class Company {
private String name;
private Address address;
// getters and setters
}
public class Address {
private String country;
private String state;
private String city;
// getters and setters
}
company.getAddress().getCountry(); // Atlantis
This particular scenario can be handled using an XmlAdapter:
import javax.xml.bind.annotation.adapters.XmlAdapter;
import java.time.format.DateTimeFormatter;
public class CompanyAdapter extends XmlAdapter<CompantType, Company> {
#Override
public CompanyType marshal(Company in) throws Exception {
CompanyType out = new CompanyType();
out.setName(in.getName());
out.setCountry(in.getAddress().getCountry());
// ...
return out;
}
#Override
public Company unmarshall(CompanyType in) throws Exception {
Company out = new Company();
out.setName(in.getName());
Address add = new Address();
add.setCountry(in.getCountry());
out.setAddress(add);
// ...
return out;
}
}

Programming difference between POJO and Bean

I have the following two classes. Can I say the first one is a POJO class and the second one as a Bean class?
1) POJO class, since it has only getter and setter method, and all the member are declared as private
public class POJO {
private int id;
private String name;
public int getId() {
return id;
}
public String getName() {
return name;
}
public void setId() {
this.id = id;
}
public void setName() {
this.name = name;
}
}
2) Bean class - all the member variables are private, has getters and setters and implements Serializable interface
public class Bean implements java.io.Serializable {
private String name;
private Integer age;
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return this.age;
}
public void setAge(Integer age) {
this.age = age;
}
}
It also has a no-arg constructor.
Only difference is bean can be serialized.
From Java docs - http://docs.oracle.com/javase/7/docs/api/java/io/Serializable.html
Serializability of a class is enabled by the class implementing the java.io.Serializable interface. Classes that do not implement this interface will not have any of their state serialized or deserialized. All subtypes of a serializable class are themselves serializable. The serialization interface has no methods or fields and serves only to identify the semantics of being serializable.
the JavaBean class must implement either Serializable or Externalizable, must have a no-arg constructor,all JavaBean properties must public setter and getter methods (as appropriate)
all JavaBean instance variables should be private

JSR-303 Validation on sub-class

I have the following class structure
public Abstract class Person {
private String fullName;
private Address address;
private Phone ;
}
class Staff extends Person{
private String staffId;
}
I want to apply validation using JSR-303 on class Staff whereby Staff address and phone cannot have the value of null. However, I have some other classes that are class of Person where I don't wish to have the validation to be applied.
One way to do this that I could think of is by refactor Person and push the fields 'address' and 'phone' to Staff, but this means refactoring a lot of other classes (and not to mention redundancy this shall cause), and hence something I want to avoid.
Update.
I have changed Staff class, as follows
public class Staff extends Person {
#NotNull
private String staffEmploymentId;
public String getStaffEmploymentId() {
return staffEmploymentId;
}
public void setStaffEmploymentId(String id) {
this.staffEmploymentId = id;
}
#Override
#NotNull
public void setPhones(List<Phone> phones) {
super.phones = phones;
}
#Override
#NotNull
public void setAddress(Address a) {
super.address = a;
}
#Override
#NotNull
public Address getAddress(){
return super.address;
}
}
However, I've got the following error.
javax.validation.ValidationException: Property setAddress does not follow javabean conventions.
I am using Apache BVal, as opposed to Hibernate Validator.
Annotate getters instead of fields using annotations from JSR-330.
You can override getters in Stuff and annotate them.

How to create a POJO?

Recently I've started hearing about "POJOs" (Plain Old Java Objects). I googled it, but still don't understand the concept well. Can anyone give me a clear description of a POJO?
Consider a class "Person" with variables "id, name, address, salary" -- how would I create a POJO for this scenario? Is the code below a POJO?
public class Person {
//variables
People people = new People();
private int id;
private String name;
private String address;
private int salary;
public int getId() {
return id;
}
public String getName() {
return name;
}
public String getAddress() {
return address;
}
public int getSalary() {
return salary;
}
public void setId() {
this.id = id;
}
public void setName() {
this.name = name;
}
public void setAddress() {
this.address = address;
}
public void setSalary() {
this.salary = salary;
}
}
A POJO is just a plain, old Java Bean with the restrictions removed. Java Beans must meet the following requirements:
Default no-arg constructor
Follow the Bean convention of getFoo (or isFoo for booleans) and setFoo methods for a mutable attribute named foo; leave off the setFoo if foo is immutable.
Must implement java.io.Serializable
POJO does not mandate any of these. It's just what the name says: an object that compiles under JDK can be considered a Plain Old Java Object. No app server, no base classes, no interfaces required to use.
The acronym POJO was a reaction against EJB 2.0, which required several interfaces, extended base classes, and lots of methods just to do simple things. Some people, Rod Johnson and Martin Fowler among them, rebelled against the complexity and sought a way to implement enterprise scale solutions without having to write EJBs.
Martin Fowler coined a new acronym.
Rod Johnson wrote "J2EE Without EJBs", wrote Spring, influenced EJB enough so version 3.1 looks a great deal like Spring and Hibernate, and got a sweet IPO from VMWare out of it.
Here's an example that you can wrap your head around:
public class MyFirstPojo
{
private String name;
public static void main(String [] args)
{
for (String arg : args)
{
MyFirstPojo pojo = new MyFirstPojo(arg); // Here's how you create a POJO
System.out.println(pojo);
}
}
public MyFirstPojo(String name)
{
this.name = name;
}
public String getName() { return this.name; }
public String toString() { return this.name; }
}
POJO:- POJO is a Java object not bound by any restriction other than those forced by the Java Language Specification.
Properties of POJO
All properties must be public setter and getter methods
All instance variables should be private
Should not Extend prespecified classes.
Should not Implement prespecified interfaces.
Should not contain prespecified annotations.
It may not have any argument constructors
Example of POJO
public class POJO {
private String value;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
A POJO is a Plain Old Java Object.
From the wikipedia article I linked to:
In computing software, POJO is an
acronym for Plain Old Java Object. The
name is used to emphasize that a given
object is an ordinary Java Object, not
a special object, and in particular
not an Enterprise JavaBean
Your class appears to already be a POJO.
POJO class acts as a bean which is used to set and get the value.
public class Data
{
private int id;
private String deptname;
private String date;
private String name;
private String mdate;
private String mname;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getDeptname() {
return deptname;
}
public void setDeptname(String deptname) {
this.deptname = deptname;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getMdate() {
return mdate;
}
public void setMdate(String mdate) {
this.mdate = mdate;
}
public String getMname() {
return mname;
}
public void setMname(String mname) {
this.mname = mname;
}
}
When you aren't doing anything to make your class particularly designed to work with a given framework, ORM, or other system that needs a special sort of class, you have a Plain Old Java Object, or POJO.
Ironically, one of the reasons for coining the term is that people were avoiding them in cases where they were sensible and some people concluded that this was because they didn't have a fancy name. Ironic, because your question demonstrates that the approach worked.
Compare the older POD "Plain Old Data" to mean a C++ class that doesn't do anything a C struct couldn't do (more or less, non-virtual members that aren't destructors or trivial constructors don't stop it being considered POD), and the newer (and more directly comparable) POCO "Plain Old CLR Object" in .NET.
According to Martin Fowler
The term was coined while Rebecca Parsons, Josh MacKenzie and I were preparing for a talk at a conference in September 2000. In the talk, we were pointing out the many benefits of encoding business logic into regular java objects rather than using Entity Beans. We wondered why people were so against using regular objects in their systems and concluded that it was because simple objects lacked a fancy name. So we gave them one, and it’s caught on very nicely.
Generally, a POJO is not bound to any restriction and any Java object can be called a POJO but there are some directions. A well-defined POJO should follow below directions.
Each variable in a POJO should be declared as private.
Default constructor should be overridden with public accessibility.
Each variable should have its Setter-Getter method with public accessibility.
Generally POJO should override equals(), hashCode() and toString() methods of Object (but it's not mandatory).
Overriding compare() method of Comparable interface used for sorting (Preferable but not mandatory).
And according to Java Language Specification, a POJO should not have to
Extend pre-specified classes
Implement pre-specified interfaces
Contain pre-specified annotations
However, developers and frameworks describe a POJO still requires the use prespecified annotations to implement features like persistence, declarative transaction management etc. So the idea is that if the object was a POJO before any annotations were added would return to POJO status if the annotations are removed then it can still be considered a POJO.
A JavaBean is a special kind of POJO that is Serializable, has a no-argument constructor, and allows access to properties using getter and setter methods that follow a simple naming convention.
Read more on Plain Old Java Object (POJO) Explained.
there are mainly three options are possible for mapping purpose
serialize
XML mapping
POJO mapping.(Plain Old Java Objects)
While using the pojo classes,it is easy for a developer to map with the database.
POJO classes are created for database and at the same time value-objects classes are created with getter and setter methods that will easily hold the content.
So,for the purpose of mapping in between java with database, value-objects and POJO classes are implemented.
import java.io.Serializable;
public class Course implements Serializable {
protected int courseId;
protected String courseName;
protected String courseType;
public Course() {
courseName = new String();
courseType = new String();
}
public Course(String courseName, String courseType) {
this.courseName = courseName;
this.courseType = courseType;
}
public Course(int courseId, String courseName, String courseType) {
this.courseId = courseId;
this.courseName = courseName;
this.courseType = courseType;
}
public int getCourseId() {
return courseId;
}
public void setCourseId(int courseId) {
this.courseId = courseId;
}
public String getCourseName() {
return courseName;
}
public void setCourseName(String courseName) {
this.courseName = courseName;
}
public String getCourseType() {
return courseType;
}
public void setCourseType(String courseType) {
this.courseType = courseType;
}
#Override
public int hashCode() {
return courseId;
}
#Override
public boolean equals(Object obj) {
if (obj != null || obj instanceof Course) {
Course c = (Course) obj;
if (courseId == c.courseId && courseName.equals(c.courseName)
&& courseType.equals(c.courseType))
return true;
}
return false;
}
#Override
public String toString() {
return "Course[" + courseId + "," + courseName + "," + courseType + "]";
}
}
public class UserInfo {
String LoginId;
String Password;
String FirstName;
String LastName;
String Email;
String Mobile;
String Address;
String DOB;
public String getLoginId() {
return LoginId;
}
public void setLoginId(String loginId) {
LoginId = loginId;
}
public String getPassword() {
return Password;
}
public void setPassword(String password) {
Password = password;
}
public String getFirstName() {
return FirstName;
}
public void setFirstName(String firstName) {
FirstName = firstName;
}
public String getLastName() {
return LastName;
}
public void setLastName(String lastName) {
LastName = lastName;
}
public String getEmail() {
return Email;
}
public void setEmail(String email) {
Email = email;
}
public String getMobile() {
return Mobile;
}
public void setMobile(String mobile) {
Mobile = mobile;
}
public String getAddress() {
return Address;
}
public void setAddress(String address) {
Address = address;
}
public String getDOB() {
return DOB;
}
public void setDOB(String DOB) {
this.DOB = DOB;
}
}
File-setting-plugins-Browse repositories
Search RoboPOJOGenerator and install, Restart Android studio
Open Project and right click on package select on Generate POJO from JSON
Paste JSON in dialogbox and select option according your requirements
Click on Generate button
If a class is not bogged down from a framework or a library, then an object created from that class is recognized as a POJO.
Let's see some examples:
class MyServlet extends HttpServlet{
//....
}
The sole meaning of MyServlet class is given by the HttpServlet class. Therefore the objects created from the MyServlet are not POJOs.
class MyClass implements Serializable{
//...
}
The Serializable interface does not give a meaning to the class MyClass. Therefore the objects created from the MyClass are POJOs.

Categories