I have a Jaxb object that has an object tree 3 deep. I have created a seperate object that mirrors this Jaxb object. I am using the builder pattern to copy values from Jaxb to the bean. The issue is, when building A, I require an instance of B. But, the verion of B that the builder requires is different from the Jaxb version of B -the 'source'.
How do I build A?
public class A {
private B b;
public void setB(B b) {
this.b = b;
}
public static class ABuilder {
private B b;
public ABuilder withB(B b) {
this.b = b;
return this;
}
A build() {
A a = new A();
a.setB(b);
return a;
}
}
}
class B {
private C c;
private String name;
}
class C {
private int count;
}
class myMain {
com.myJaxb.B jaxbB;
A myA = new A.ABuilder().withB(jaxbB).build(); //error - withB doesnt take jaxb B
}
Related
I have got the following scenario in which I got four classes autogenerated (in a JAR):
Class A{
B bEl = ...;
}
Class B{
C cEl = ...;
}
Class C{
D dEl = ...;
}
Class E{
E eEl=...;
}
Setting up those objects it is quite painful and error prone. Therefore, I was wondering if there is a better way to automatically construct a builder. I am aware of Lombok but I cannot edit that code and I cannot add the #Builder annotation.
Any recommendation?
If you are not allowed to change existing classes you can extend them:
public class Existing {
String a;
String b;
public Test(String a, String b) {
this.a = a;
this.b = b;
}
public String getA() {
return a;
}
public void setA(String a) {
this.a = a;
}
public String getB() {
return b;
}
public void setB(String b) {
this.b = b;
}
}
public class ExistingBuilder extends Existing {
#Builder
public ExistingBuilder(String a, String b) {
super(a, b);
// in case super class doesn't have all arguments constructor just call setters
// setA(a);
// setB(b);
}
}
So as you can see it's doable, but super class should have getters/setters or all args constructor.
I have a system which makes some action. This system creates for each object a separate thread using:
stp.scheduleWithFixedDelay((EditSite) ctx.getBean("EditSite", site), threadTimeParams);
I want to create a constructor with "Site" parameter, but I should keep somehow my autowired constructor working.
public class EditSite{
private final A a;
private final B b;
private final C c;
private Site site;
public EditSite(#Autowired A a, #Autowired B b,#Autowired C c) {
this.a = a;
this.b = b;
this.c = c;
}
public void run(){ check(); }
public void check(){}
}
My IDE said that I can't create public EditSite(Site site, #Autowired A a, #Autowired B b,#Autowired C c). I used to have a field annotations before, but recently I saw an article that said that field annotations are bad and decided to refactor my code. How can I do it?
You need to create your bean explicitly in the configuration.
You don't need any autowiring inside your class:
public class EditSite{
private final A a;
private final B b;
private final C c;
private Site site;
public EditSite(Site site, A a, B b , C c) {
this.site=site;
this.a = a;
this.b = b;
this.c = c;
}
public void run(){ check(); }
public void check(){}
}
And config for that:
#Configuration
public class EditSiteConfig {
#Bean
public EditSite editSite(A a, B b, C c){
Site site = getSite(); //since site is not a bean, you need to get it manually
return new EditSite(site, a, b, c);
}
}
Use field autowiring, for example:
#Autowired
private final A a;
#Autowired
private final B b;
#Autowired
private final C c;
private Site site;
My program has 3 class. A, B, C. An instance variable is a private instance
class A {
private int a;
public int getX() {return a;}
public void setX(int a){this.a = a;}
}
class B extends A {
private int b;
public int getX() {return b;}
public void setX(int b){this.b = b;}
}
class C extends B {
private int c;
....
}
In class C I want to write a method that I must be used method getter and setter form class A and B
for getter and setter form class B I can write it but Class A I try to write this
class C extends B {
private in c;
public void method(){
A a = (A) this;
System.out.println(a.getX());
}
}
but the output is a value of class B, not A
how to do I can write it while No need to add method in class A, B, and C
My problem defines a private instance
I have two classes : class A , class B
class A{
private int F1;
private String F2;
}
class B{
private int F3;
private String F4;
private String F5;
}
I want a JSON like this:
{
"F1": 123
"F2": "ABC"
"F3": 456
"F4": "CDE"
"F5": "FGH"
}
I am using springboot which creates JSON as soon as I return object from #RestController. How can I achieve the above json using these two classes.
Note :
1.) I already know that by using class A extends B , I can achieve
this but I am looking for some spring based method to achieve this
2.) Using #Embeddable in class B & then creating reference in Class A creates
additional tag B in JSON as shown :
{
"F1": 123
"F2": "ABC"
b: {
"F3": 456
"F4": "CDE"
"F5": "FGH"
}
}
How about using jackson #JsonUnwrapped?
http://fasterxml.github.io/jackson-annotations/javadoc/2.0.0/com/fasterxml/jackson/annotation/JsonUnwrapped.html
public class A{
#JsonUnwrapped
private B b;
public User getB() ...
}
Create a delegating class AB:
public final class AB {
private final A a;
private final B b;
public AB(A a, B b) {
this.a = a;
this.b = b;
}
// Delegation methods to A
public int getF1() { return this.a.getF1(); }
public String getF2() { return this.a.getF2(); }
// Delegation methods to B
public int getF3() { return this.b.getF3(); }
public String getF4() { return this.b.getF4(); }
public String getF5() { return this.b.getF5(); }
}
I have a fairly complex POJO that I need to deserialize from a JSON string and persist in a MySQL database. The following is a very simplified example class:
#Entity
#Table(name="a")
public class A{
private Long id;
private B b;
private C c;
private D d;
}
#ManyToOne
#JoinColumn(name="b_id")
public B getB(){
return this.b;
}
public void setB(B b){ this.b = b; }
#ManyToOne
#JoinColumn(name="c_id")
public C getC(){
return this.c;
}
public void setC(C c){ this.c = c; }
#ManyToOne
#JoinColumn(name="d_id")
public D getD(){
return this.d;
}
public void setD(D d){ this.d = d; }
Each class B, C, and D also have a number of fields and objects (some with even more required objects and fields) that can not be null according to the database schema, which I can't change. I can deserialize and persist this no problem, but the JSON required to do so is really massive. I only need to persist the deserialized A, so I really just need the _id fields from B, C, and D.
Right now my JSON is something like:
{
"id":1,
"b":{"id":2, ...},
"c":{"id":3, ...},
"d":{"id":4, ...}
}
where I have to fill in all the non-nullable database fields. What I would like to do is read a JSON string like:
{
"id":1,
"b_id":2,
"c_id":3,
"d_id":4
}
and just have Hibernate/JPA update those fields in the database. I think the real tricky part is that other classes/methods in my application will need the entire object hierarchy for reading from the database. The only time I can use just the _id fields is during the deserialization of the JSON. When this is the case, I only need to update the top-most object (A in my example) and some other trivial fields. In a perfect world, I can just throw some annotations on my class to solve this problem, but I haven't found anything capable of doing this.
Is this even possible? If so, can it be done with JPA/Jackson annotations?
Thanks!
If mapping the JSON directly to your entities is akward, I would simply make the translation from the incoming JSON string to your entities explicit via an intermediate object (call it a DTO if you will).
I also have a gut feeling that if you save associated object references (the #ManyToOnes) with only the id populated, Hibernate will in fact save the association correctly (root object here represents A):
{
"id" : 1,
"b" : {
"id" : 2
},
...
}
Make sure you don't cascade the persist operation for the b, c etc. fields.
You should create new classes which define only this fields which you want to deserialize. For example if you want to deserialize only ID your class could looks like this:
class JsonEntity {
private Long id;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
#JsonAnySetter
public void setUnknownProperties(String name, String value) {
//do nothing
}
#Override
public String toString() {
return String.valueOf(id);
}
}
In this example annotation JsonAnySetter do the trick. Now, you have to create some class which will be simulating your A class. For example:
class DtoA extends JsonEntity {
private JsonEntity b;
private JsonEntity c;
private JsonEntity d;
public JsonEntity getB() {
return b;
}
public void setB(JsonEntity b) {
this.b = b;
}
public JsonEntity getC() {
return c;
}
public void setC(JsonEntity c) {
this.c = c;
}
public JsonEntity getD() {
return d;
}
public void setD(JsonEntity d) {
this.d = d;
}
#Override
public String toString() {
return "A [id=" + getId() + ", b=" + b + ", c=" + c + ", d=" + d + "]";
}
}
Now when we have new JSON data model we can test it. For example we can parse below JSON:
{
"id":1,
"b":{"id":2, "p1":"v1", "p2":"v2"},
"c":{"id":3, "p3":"v3", "p4":"v4", "p5":"v5"},
"d":{"id":4, "p6":"v6"}
}
Deserialization example:
ObjectMapper objectMapper = new ObjectMapper();
DtoA a = objectMapper.readValue(json, DtoA.class);
System.out.println(a);
Above program prints:
A [id=1, b=2, c=3, d=4]
Now, you have to implement toA() method in DtoA class which could look like this:
public A toA() {
A a = new A(getId());
a.setB(new B(getB().getId()));
a.setC(new C(getC().getId()));
a.setD(new D(getD().getId()));
return a;
}
Let me know whether it works for you.