Builder for existing classes - java

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.

Related

How can i create constructor with autowired and non autowired fields simultaniosly?

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;

How do I use method from super of super class

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

Creating JSON by combining fields from two classes

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(); }
}

Java Builder Pattern - deep object copy

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
}

Jackson: Printing Values as Keys in the JSON

Normally what we do in Jackson to print a class as JSON object is to define getter and setter like
public class MyClass
{
private Integer a;
private Integer b;
public myClass(Integer a, Integer b)
{
this.a = a;
this.b = b;
}
#JsonProperty
public Integer getA()
{
return a;
}
#JsonProperty
public Integer getB()
{
return b;
}
public void setA(Integer a)
{
this.a = a;
}
public void setB(Integer b)
{
this.b = b;
}
}
and this will return {"a":1,"b":2}
But can I get output as {1:2} instead of what I am getting before?
In order to achieve that, you need to write own code and pass accordingly. But output you showed is standard json format which you cannot change, but definitely you can change it with code.
If you do not care that output JSON is not valid you can write custom serializer for your POJO class. It could look like this:
class MyClassJsonSerializer extends JsonSerializer<MyClass> {
#Override
public void serialize(MyClass myClass, JsonGenerator generator, SerializerProvider serializerProvider) throws IOException, JsonProcessingException {
generator.writeStartObject();
generator.writeRaw(myClass.getA() + ":" + myClass.getB());
generator.writeEndObject();
}
}
Using:
#JsonSerialize(using = MyClassJsonSerializer.class)
class MyClass {
....
}
Since now, your POJO should be serialized to desired output.

Categories