JAXB #XmlIDREF in XmlAdapter for immutable objects - java

I'm using XmlAdapter for immutable objects as proposed in this blog post: http://blog.bdoughan.com/2010/12/jaxb-and-immutable-objects.html. This works fine, but not with references to other immutable objects in my adapters. Is there any way to handle this with JAXB?
Below there is an example which does not work if the person's xml tag comes after the company's xml tag which references the person.
Immutable objects:
#XmlJavaTypeAdapter(PersonAdapter.class)
public class Person {
private final String id;
private final String name;
public Person(String id, String name) {
this.id = id;
this.name = name;
}
public String getId() {
return id;
}
public String getName() {
return name;
}
}
#XmlJavaTypeAdapter(CompanyAdapter.class)
public class Company {
private final String name;
private final Person principal;
public Company(String name, Person principal) {
this.name = name;
this.principal = principal;
}
public String getName() {
return name;
}
public Person getPrincipal() {
return principal;
}
}
PersonAdapter:
public class PersonAdapter extends XmlAdapter<AdaptedPerson, Person> {
public static class AdaptedPerson {
#XmlID
#XmlAttribute
String id;
#XmlAttribute
String name;
}
#Override
public AdaptedPerson marshal(Person v) throws Exception {
AdaptedPerson a = new AdaptedPerson();
a.id = v.getId();
a.name = v.getName();
return a;
}
#Override
public Person unmarshal(AdaptedPerson v) throws Exception {
return new Person(v.id, v.name);
}
}
CompanyAdapter:
public class CompanyAdapter extends XmlAdapter<AdaptedCompany, Company> {
public static class AdaptedCompany {
#XmlAttribute
String name;
#XmlIDREF
#XmlAttribute
Person principal;
}
#Override
public AdaptedCompany marshal(Company v) throws Exception {
AdaptedCompany a = new AdaptedCompany();
a.name = v.getName();
a.principal = v.getPrincipal();
return a;
}
#Override
public Company unmarshal(AdaptedCompany v) throws Exception {
return new Company(v.name, v.principal);
}
}

Related

Hazelcast Deserialization: Parent class attributes values are null after deserializatioin

I have two class Parent Class and Child classes as below:
#MappedSuperclass
public class ParentEntity implements DataSerializable {
private String createdBy;
private Date createdAt;
public String getCreatedBy() {
return createdBy;
}
public void setCreatedBy(String createdBy) {
this.createdBy = createdBy;
}
public Long getCreatedAt() {
return createdAt.getTime();
}
public void setCreatedAt(Date createdAt) {
this.createdAt = createdAt;
}
#Override
public void writeData(ObjectDataOutput out) throws IOException {
out.writeUTF(createdBy);
out.writeLong(this.getCreatedAt());
}
#Override
public void readData(ObjectDataInput in) throws IOException {
createdBy = in.readUTF();
createdAt = new Date(in.readLong());
}
}
Child class is as below:-
public class Child_Entity extends ParentEntity implements DataSerializable {
private String id;
private String name;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#Override
public void writeData(ObjectDataOutput out) throws IOException {
out.writeUTF(id);
out.writeUTF(name);
}
#Override
public void readData(ObjectDataInput in) throws IOException {
id = in.readUTF();
name = in.readUTF();
}
}
I fetch these value from database and put into hazelcast cache iMap.
While getting values from cache I am getting id and name value correct, but createdAt and createdBy (Parent Class attributes ) values are null.
How can it is possible to serialize parent class also with child class.
You need to call super-class serialization methods in the child class methods. For instance;
public class Child_Entity extends ParentEntity implements DataSerializable {
private String id;
private String name;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id; }
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#Override
public void writeData(ObjectDataOutput out) throws IOException {
super.writeData(out);
out.writeUTF(id);
out.writeUTF(name);
}
#Override
public void readData(ObjectDataInput in) throws IOException {
super.readData(in);
id = in.readUTF();
name = in.readUTF();
}}

getter setter in inner private class in java [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I want to create bean in java corresponding to below json
{
"name": "",
"id": "",
"dept": {
"deptId": "",
"deptName": "",
"course": {
"courseId": "",
}
}
}
My idea is to create parent class and keep dept and course as inner private classes and then have getters setters to get or set data and form parent bean. But I am getting error "Change visibility to the public"
How can I access private fields of inner private class to get and set data?
try this way its will work
public class firstClass{
private String name;
private String id;
Department dept;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public Department getDept() {
return dept;
}
public void setDept(Department dept) {
this.dept = dept;
}
}
class Department{
private int departId;
private String deptName;
Course course;
public int getDepartId() {
return departId;
}
public void setDepartId(int departId) {
this.departId = departId;
}
public String getDeptName() {
return deptName;
}
public void setDeptName(String deptName) {
this.deptName = deptName;
}
public Course getCourse() {
return course;
}
public void setCourse(Course course) {
this.course = course;
}
}
class Course{
private int courseId;
public int getCourseId() {
return courseId;
}
public void setCourseId(int courseId) {
this.courseId = courseId;
}
}
You can't access private fields. Why don't you create a getter and setter for the inner class private fields?
And, maybe you should consider using gson library.
You at least have to make say nested public interfaces, say Dept and Course, with your private (static) nested private classes DeptImpl and SourceImpl.
public class X {
public interface Dept { ... }
private static class DeptImpl extends Dept { ... }
public Dept getDept() { ... }
public Dept createDept(...) {
DeptImpl dept = new DeptImpl(...); ...
return dept;
}
Maybe you need to provide a factory method createDept.
In some cases the implementing class can be anonymous new Dept() { ... }.
You can use Builder Design pattern with immutable Objects:
public class Class {
private final String name;
private final int id;
private final Department dept;
private Class(ClassBuilder classBuilder){
this.name = classBuilder.getName();
this.id = classBuilder.getId();
this.dept = classBuilder.getDept();
}
public String getName() {
return name;
}
public int getId() {
return id;
}
public Department getDept() {
return dept;
}
private static class Department{
private final int deptId;
private final String deptName;
private final Course course;
private Department(DepartmentBuilder departmentBuilder){
this.deptId = departmentBuilder.getDeptId();
this.deptName = departmentBuilder.getDeptName();
this.course = departmentBuilder.getCourse();
}
public int getDeptId() {
return deptId;
}
public String getDeptName() {
return deptName;
}
public Course getCourse() {
return course;
}
private static class Course{
private final int courseId;
private Course(CourseBuilder courseBuilder){
this.courseId = courseBuilder.getCourseId();
}
public int getCourseId() {
return courseId;
}
}
}
public static class ClassBuilder{
private final String name;
private final int id;
private final Department dept;
public ClassBuilder(String name, int id, Department dept){
this.name = name;
this.id = id;
this.dept = dept;
}
public Department getDept() {
return dept;
}
public String getName() {
return name;
}
public int getId() {
return id;
}
public Class build(){
return new Class(this);
}
}
public static class DepartmentBuilder {
private final int deptId;
private final String deptName;
private final Department.Course course;
public DepartmentBuilder(int deptId, String deptName, Department.Course course ){
this.deptId = deptId;
this.deptName = deptName;
this.course = course;
}
public int getDeptId() {
return deptId;
}
public String getDeptName() {
return deptName;
}
public Department.Course getCourse() {
return course;
}
public Department build(){
return new Department(this);
}
}
public static class CourseBuilder{
private final int courseId ;
public CourseBuilder(int courseId){
this.courseId = courseId;
}
public int getCourseId() {
return courseId;
}
public Department.Course build(){
return new Department.Course(this);
}
}
}
public class Sample {
public static void main(String ... strings){
Class clazz = new Class.ClassBuilder("ClassName", 1, new Class.DepartmentBuilder(1, "departmentName", new Class.CourseBuilder(2).build()).build()).build();
System.out.println(clazz.getDept());
}
}

GSON - Deserialize nested Parameterized Object

For the below code, my nested parameterized object is always deserialized as LinkedTreeMap instead of the original class
I am using GSON for json serializing & deserializing
Here are the models:
Cart containing wrapped items
public class Cart {
private String id;
private String owner;
private List<ItemWrapper> relatedItems;
.......
public List<ItemWrapper> getRelatedItems() {
return relatedItems;
}
public void setRelatedItems(List<ItemWrapper> relatedItems) {
this.relatedItems = relatedItems;
}
}
Item wrapper
public class ItemWrapper<T> {
private String type;
private String decription;
private T item;
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
........
public T getItem() {
return item;
}
public void setItem(T item) {
this.item = item;
}
}
Car Item ..
public class Car {
private String model;
private double price;
public String getModel() {
return model;
}
.....
public void setPrice(double price) {
this.price = price;
}
}
Book Item ..
public class Book {
private String name;
private String mediaType;
public String getName() {
return name;
}
.....
public void setMediaType(String mediaType) {
this.mediaType = mediaType;
}
}
When I run the below snippet
Cart cart = gson.fromJson(
"{\"id\":\"id123\",\"owner\":\"Usama\",\"relatedItems\":[{\"type\":\"Book\",\"decription\":\"book item\",\"item\":{\"name\":\"Love\",\"mediaType\":\"pdf\"}},{\"type\":\"Car\",\"decription\":\"car item\",\"item\":{\"model\":\"BMW\",\"price\":500000.0}}]}\n"
+ "",
Cart.class);
System.out.println(cart.getClass().getName());
System.out.println(cart.getRelatedItems().get(0).getItem().getClass().getName());
I got that result
model.Cart
com.google.gson.internal.LinkedTreeMap
instead of
model.Cart
model.Book
Any idea how to fix this.

map 2 collection types using modelmapper

I am developing and spring application and for object mapping I am using ModelMapper library.
I am able to map basic class mapping but when I am trying to map 2 collection elements, source is set of enumeration with additional property like name and description and destination is pojo having id, name and description.
I have tried typemap and converters in mapping profile but I am getting exception of mapper.
And the source class is from other application(whose dependency have been added in pom.xml). I also don't want source type as an argument in setter of destination.
Ex.
SOURCE:
public class VType{
private int id;
private String name;
private String description;
}
public class VDTO{
private Set<VType> vTypes;
public Set<VType> getVTypes(){
return this.vTypes;
}
public void setVType() { //here I don't want to pass source type as an argument
//code stuff that I don't know what to do here
}
}
SOURCE ENUM:
public enum SourceVType{
V1(1, "Name1", "Desc1");
V2(2, "Name2", "Desc2");
private Integer id;
private String name;
private String description;
SourceVType(Integer id, String name, String description) {
this.id = id;
this.name = name;
this.description = description;
}
//getter-setter
}
Have you tried converter feature of modelmapper. You can use typemap converter to achieve this requirement.
#RunWith(JUnit4.class)
public class TempTest {
#Test
public void TestThis(){
final ModelMapper mapper = new ModelMapper();
mapper.addMappings(new PropertyMap<SrcClass, DestClass>() {
#Override
protected void configure() {
this.map().setId(this.source.getId());
this.map().setName(this.source.getName());
mapper.createTypeMap(TypeEnum.class, TypeClass.class).setConverter(
new Converter<TypeEnum, TypeClass>() {
#Override
public TypeClass convert(MappingContext<TypeEnum, TypeClass> mappingContext) {
if (mappingContext.getSource() == null) {
return null;
}
TypeEnum typeEnum = mappingContext.getSource();
TypeClass typeClass = new TypeClass();
typeClass.setId(typeEnum.getId());
typeClass.setName(typeEnum.getName());
return typeClass;
}
});
}
});
SrcClass srcObj = new SrcClass();
srcObj.setId(1);
srcObj.setName("name");
srcObj.setTypes(new HashSet<>(Arrays.asList(TypeEnum.TYPE1, TypeEnum.TYPE2)));
DestClass dstObj = mapper.map(srcObj, DestClass.class);
Assert.assertEquals(srcObj.getId(), dstObj.getId());
Assert.assertEquals(srcObj.getName(), dstObj.getName());
Assert.assertEquals(srcObj.getTypes().size(), dstObj.getTypes().size());
for(TypeClass c : dstObj.getTypes()) {
TypeEnum e = TypeEnum.getById(c.getId());
Assert.assertNotNull(e);
Assert.assertTrue(srcObj.getTypes().contains(e));
}
}
public static <Source, Result> Set<Result> convertAll(Set<Source> source, Function<Source, Result> projection)
{
Set<Result> results = new HashSet<>();
if(source == null) return results;
for (Source element : source)
{
results.add(projection.apply(element));
}
return results;
}
public static class SrcClass{
private Integer id;
private String name;
private Set<TypeEnum> types;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Set<TypeEnum> getTypes() {
return types;
}
public void setTypes(Set<TypeEnum> types) {
this.types = types;
}
}
public static class DestClass{
private Integer id;
private String name;
private Set<TypeClass> types;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Set<TypeClass> getTypes() {
return types;
}
public void setTypes(Set<TypeClass> types) {
this.types = types;
}
}
public static enum TypeEnum{
TYPE1(1, "Type 1")
, TYPE2(2, "Type 2")
, TYPE3(3, "Type 3")
, TYPE4(4, "Type 4");
private Integer id;
private String name;
TypeEnum(Integer id, String name) {
this.id = id;
this.name = name;
}
private static final Map<Integer, TypeEnum> byId = new HashMap<>();
private static final Map<String, TypeEnum> byName = new HashMap<>();
static {
for (TypeEnum e : TypeEnum.values()) {
if (byId.put(e.getId(), e) != null) {
throw new IllegalArgumentException("duplicate id: " + e.getId());
}
if (byName.put(e.getName(), e) != null) {
throw new IllegalArgumentException("duplicate name: " + e.getName());
}
}
}
public Integer getId() {
return this.id;
}
public String getName() { return this.name; }
public static TypeEnum getById(Integer id) {
return byId.get(id);
}
public static TypeEnum getByName(String name) {
return byName.get(name);
}
}
public static class TypeClass{
private Integer id;
private String name;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
}

Json Object conversion to java object using jackson

I have following json data
{"id":10606,
"name":"ProgrammerTitle",
"objectMap":{"programme-title":"TestProgramme","working-title":"TestProgramme"}
}
I want to set this data to my pojo object
public class TestObject {
private Long id;
private String name;
#JsonProperty("programme-title")
private String programmeTitle;
#JsonProperty("working-title")
private String workingTitle;
}
Here i am able to set id and name in my test object but for object map i am not able to set data.
So i have made on more class for ObjectMap which contains programmeTitle & workingTitle this works fine but i can't set this fields directly to my pojo object
is this possible to set?
I am using Jackson Object Mapper to convert json data.
It is working fine if i create another java object inside my pojo like:
public class TestObject {
private Long id;
private String name;
#JsonProperty("objectMap")
private ObjectMap objectMap;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public ObjectMap getObjectMap() {
return objectMap;
}
public void setObjectMap(ObjectMap objectMap) {
this.objectMap = objectMap;
}
}
public class ObjectMap {
#JsonProperty("programme-title")
private String programmeTitle;
#JsonProperty("working-title")
private String workingTitle;
public String getProgrammeTitle() {
return programmeTitle;
}
public void setProgrammeTitle(String programmeTitle) {
this.programmeTitle = programmeTitle;
}
public String getWorkingTitle() {
return workingTitle;
}
public void setWorkingTitle(String workingTitle) {
this.workingTitle = workingTitle;
}
}
If your JSON is like this
{"id":10606,
"name":"ProgrammerTitle",
"objectMap":{"programme-title":"TestProgramme","working-title":"TestProgramme"}
}
then you may write your object mapper class like this..
public class Program{
public static class ObjectMap{
private String programme_title, working_title;
public String getprogramme_title() { return programme_title; }
public String getworking_title() { return working_title; }
public void setprogramme_title(String s) { programme_title= s; }
public void setworking_title(String s) { working_title= s; }
}
private ObjectMap objMap;
private String name;
public ObjectMap getobjectMap () { return objMap; }
public void setObjectMap (ObjectMap n) { objMap= n; }
private Long id;
public Long getId() {return id;}
public void setId(Long id) {this.id = id;}
private String name;
public String getName() {return name;}
public void setName(String name) {this.name = name;}
}
please refer this check it
You can write your own deserializer for this class:
class EntityJsonDeserializer extends JsonDeserializer<Entity> {
#Override
public Entity deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
Root root = jp.readValueAs(Root.class);
Entity entity = new Entity();
entity.setId(root.id);
entity.setName(root.name);
if (root.objectMap != null) {
entity.setProgrammeTitle(root.objectMap.programmeTitle);
entity.setWorkingTitle(root.objectMap.workingTitle);
}
return entity;
}
private static class Root {
public Long id;
public String name;
public Title objectMap;
}
private static class Title {
#JsonProperty("programme-title")
public String programmeTitle;
#JsonProperty("working-title")
public String workingTitle;
}
}
Your entity:
#JsonDeserialize(using = EntityJsonDeserializer.class)
class Entity {
private Long id;
private String name;
private String programmeTitle;
private String workingTitle;
//getters, setters, toString
}
And usage example:
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
public class JacksonProgram {
public static void main(String[] args) throws IOException {
ObjectMapper mapper = new ObjectMapper();
Entity entity = mapper.readValue(jsonString, Entity.class);
System.out.println(entity);
}
}
Above program prints:
Entity [id=10606, name=ProgrammerTitle, programmeTitle=TestProgramme, workingTitle=TestProgramme]

Categories