I have some BaseX pojo class ex:
public class Base1 {
private String base1Field1;
private String base1Field2;
// getter & setter
}
public class Base2 {
private String base2Field1;
private String base2Field2;
// getter & setter
}
And some DomainVo pojo class, it has some field & method from BaseX class ex:
//from base1
public class Domain1Vo {
private String domain1Field1;
private String base1Field1;
private String base1Field2;
// getter & setter
}
//from base1 & base 2
public class Domain2Vo {
private String domain2Field1;
private String base1Field1;
private String base1Field2;
private String base2Field1;
private String base2Field2;
// getter & setter
}
I don't want copy paste those fields from BaseX class to my domain object, but I can't use extends Base1, Base2 because java don't allow it.
I don't actually use BaseX in my code, I define them just want a single place to maintain those field.
update:
I can't change my domain object structure, because it's come from/to other service as json. Also I need use it to generate a swagger doc(I use springfox). This why I need both field & method.
======== some research I did
I found a lib called lombok, it has a feature name #Delegate
https://projectlombok.org/features/experimental/Delegate
//from base1
public class Domain1Vo {
private String domain1Field1;
#Delegate
private Base1 base1;
// getter & setter
}
It can generate method from BaseX class, but not field.
Composition is what you want. Inheritance is wildly overused (also getters and, especially, setters).
The base classes become components. (Use better names! Even "base" isn't a useful word to use in a class name.)
public final class Component1 {
private String component1Field1;
private String component1Field2;
// domain methods
}
public final class Component2 {
private String component2Field1;
private String component2Field2;
}
public final class Domain1Vo {
private String domain1Field1;
private final Component1 component1;
public Domain1Vo(
Component1 component1
) {
// Or construct.
this.component1 =
Objects.requireNonNull(component1);
}
// domain methods
}
//from base1 & base 2
public final class Domain2Vo {
private String domain2Field1;
private final Component1 component1;
private final Component2 component2;
public Domain2Vo(
Component1 component1,
Component2 component2,
) {
// Or construct.
this.component1 =
Objects.requireNonNull(component1);
this.component2 =
Objects.requireNonNull(component2);
}
// domain methods
}
Related
I am working with a technology called Verastream Host Integrator. Essentially VHI is a no-code/low-code GUI tool for working with mainframe data that that compiles into Java bindings.
One of the issues with VHI is that it can only output flat data. Here is an example:
public class VhiProcedureRecord {
private String foo1;
private String foo2;
private String bar1;
private String bar2;
// constructors, getters, and setters
}
I am piping this output through a Spring Boot middleware layer and I want to remap this object into something that would look like this:
public class Foo {
private String foo1;
private String foo2;
// constructors, getters, and setters
}
public class Bar {
private String bar1;
private String bar2;
// constructors, getters, and setters
}
public class MyRecord {
private Foo foo;
private Bar bar;
// constructors, getters, and setters
}
As you can see this requires splitting the fields in VhiProcedureRecord between Foo and Bar.
Doing this manually quickly becomes a huge pain.
The other problem with the output being flat is when the VHI output contains a list of data, it returns multiple records with duplicate fields, akin to what a SQL join would look like e.g.
public class VhiPetOwnershipRecord {
private String ownerName;
private String petName;
// constructors, getters, and setters
}
The result of this procedure returns something akin to:
[
{"ownerName": "JHuang", "petName": "Fido"},
{"ownerName": "JHuang", "petName": "Spot"}
]
And I want to remap this into:
public class MyPetOwnershipRecord {
private String ownerName;
private List<String> petName;
}
Is there a way to use Jackson or something similar to do this sort of remapping automatically?
Keep in mind that VhiProcedureRecord is compiled by VHI, so that class can't be changed.
I have the following legacy code as shown below. I'm wondering is there a way to set BikeName and BikeModel when BikeGroup is being set? Basically, as the user is setting BikeGroup, how can we automatically set Foo's version of BikeName and BikeModel? Without using a constructor to set values. I'm setting the BikeGroup using a Validator (spring framework)... so I cannot use a constructor or setter to set the values.
Class Foo{
private BikeGroup; // 1. when this is set
private String bikeName; // 2. set this with value in BikeGroup
private String bikeModel; // 3. and set this with value in BikeGroup
//getters/setters
}
Class BikeGroup{
private String bikeName;
private String bikeModel;
//getters/setters
}
Yes. But, the constructor for Foo must be named Foo (and you want to pass a BikeGroup to that constructor, so it needs a parameter). And you don't put () at class declaration. Something like,
class Foo {
public Foo(BikeGroup bg) {
this.bikeName = bg.getBikeName();
this.bikeModel = bg.getBikeModel();
}
private String bikeName;
private String bikeModel;
}
Or, using a setter...
class Foo {
public void setBikeGroup(BikeGroup bg) {
this.bikeName = bg.getBikeName();
this.bikeModel = bg.getBikeModel();
}
private String bikeName;
private String bikeModel;
}
I have a class in Java named Course. In that class I have some private fields (ID, name, list of teachers and enum type (that can be Compulsory, Elective or Modular)). If the type of the course is Modular, there should be another field Module. How can that be done, in a different way (not to have 3 different classes CompulsoryCourse, ElectiveCourse and ModularCourse)?
Well you can have an extra field Module which is optional. So it would be null, and its getter returns Optional<Module> (that way you avoid null pointer exceptions).
This seems a case for the Factory or Strategy pattern. However that requires polymorphism.
Dynamically adding a field to a class is not possible, or better it is, but that's a bytecode manipulation topic.
You can emulate the optionality of the Module type field, by encapsulating it and exposing it via an Optional<Module> getter method, or by applying a sort of no-op implementation to it.
Other than using null or similar...
Instead of using an enum for type, use a type.
abstract class CourseType {
...
}
class Modular extends CourseType {
private Module module;
...
}
class Compulsory extends CourseType {
...
class Course {
private CourseType type;
public class Course {
private UUID ID;
private String name;
private List<String> teachers;
private Type type;
private String module;
public void typeCompulsory() {
type(Type.COMPULSORY, null);
}
public void typeElective() {
type(Type.ELECTIVE, null);
}
public void typeModular(String module) {
Objects.requireNonNull(module);
type(Type.MODULAR, module);
}
private void type(Type type, String module) {
this.type = type;
this.module = module;
}
public enum Type {
COMPULSORY,
ELECTIVE,
MODULAR
}
}
use the fact that enums are objects. Add a private field 'module' and a method 'getModule' that will return the module value for Modular course, and null for Compulsory and Elective courses.
enum courseType{
Modular("module x"), Compulsory, Elective;
private String module = null;
private courseType(){}
private courseType(String module){this.module = module;}
public String getModule() {return this.module;}
}
you can also throw an exception instead:
enum courseType{
Modular("module x"),
Compulsory {public String getModule() { throw new AssertionError("not applicable");}},
Elective {public String getModule() { throw new AssertionError("not applicable");}};
private final String module;
private courseType(){ this.module = null;}
private courseType(String module){this.module = module;}
public String getModule() { return this.module;}
}
I am creating a simple GUI game (number guessing) in Java.
Apparently, I have a button called Give Up.
When I click the Give Up button, I want to display the answer on a textarea.
However, the targetNumber variable is declared as private:
public class GameUtility {
private String targetNumber = "2543";
//rest of the code
}
class GiveUpButton implements ActionListener { //Inner class
public void actionPerformed(ActionEvent gEvent) {
GameUtility utility = new GameUtility();
textArea.append(utility.targetNumber); //How to access the value of targetNumber?
}
}
How can I access a value of a private variable?
To make the state of the managed bean accessible, you need to add setter and getter methods for that state.
Once the setter and getter (accessor) methods have been added, you can update and access the value of the private instance. The code should look like the following example:
public class AccessorExample {
private String attribute;
public String getAttribute() {
return attribute;
}
public void setAttribute(String attribute) {
this.attribute = attribute;
}
}
Letting access the information inside the private instance from outside of the class, only if they ask through a provided mechanism we will call method. The mechanisms for asking an object to reveal information about itself we can call the getter method (e.g. accessorExample.getAttribute();).
The private modifier implies that you don't have access to the property directly. But perhaps more importantly, private implies that you shouldn't have access to the property directly. Create a getter for providing access to external classes:
public class GameUtility {
private String targetNumber = "2543";
public String getTargetNumber() {
return targetNumber;
}
//rest of the code
}
class GiveUpButton implements ActionListener {
public void actionPerformed(ActionEvent gEvent) {
GameUtility utility = new GameUtility();
textArea.append(utility.getTargetNumber());
}
}
See also: Java Documentation on Access Control
The recommended way is to create appropriate Getters and Setters.
See this post to get more insights as how do getters and setters work?
public class AccessorExample {
private String attribute;
public String getAttribute() {
return attribute;
}
public void setAttribute(String attribute) {
this.attribute = attribute;
}
}
Most of the IDEs provide support to directly generate getters and setters.
Generate Getters and setters in Netbeans.
Generate Getters and setters in Eclipse.
The following model:
public class SomeType
{
#XmlAttribute
private int att1 = 4;
#XmlElement
private Delegate delegate = new Delegate();
public static class Delegate
{
#XmlAttribute
private String att2 = "hi";
#XmlAttribute
private String att3 = "howdy";
}
}
Produces this output:
<someType att1="4">
<delegate att2="hi" att3="howdy"/>
</someType>
Is there way to have JAXB omit the <delegate> element but include all its attributes (more than one, so #XmlValue won't suffice)? Desired output:
<someType att1="4" att2="hi" att3="howdy"/>
Not Sure if it is possible. But if you don't have to use Delegate in other places and only in this one class you can have below workaround.
Create an intermediate class in desired structure like below which would read fields from original class and you can unmarshal data using this class
Intermdiate class : Populate fields in this class by reading fields in original class
public class IntermediateType
{
#XmlAttribute
private int att1 = 4;
#XmlAttribute
private String att2 = "hi";
#XmlAttribute
private String att3 = "howdy";
#XmlElement
private Delegate delegate = new Delegate();
}
Short answer
I don't know, maybe there really is some annotation combination out there or the ability to define some custom adapter/converter, although highly unlikely. JAXB is supposed to enable representation of the xml content as Java objects, so the object graph must match the 'layout' of the xml it represents.
Also, I assume you considered the inheritance, you can just extend your classes from the delegate (you would probably name it then like BaseSomething or AbstractSomething) and everything would work, but you loose the ability to extend some other class.
Long answer
If you can, you should change the xml to the 'undesired' form:
<someType att1="4">
<delegate att2="hi" att3="howdy"/>
</someType>
Think of the other side which is consuming this xml (or producing it if/when you are the consumer). They would probably appreciate the ability not to repeat themselves as well. All JAXB-like frameworks work in a similar fashion, even in languages other than Java.
However, if you cannot change the actual xml form and would like to use better encapsulation in your code when working with these objects, you could implement SomeType using an approach similar to this:
public class SomeType {
#XmlAttribute
private int att1 = 4;
#XmlAttribute
private String att2 = "hi";
#XmlAttribute
private String att3 = "howdy";
public void setDelegate(Delegate delegate) {
this.att2 = delegate.att2;
this.att3 = delegate.att3;
}
public Delegate getDelegate() {
return new Delegate(att2, att3);
}
public static class Delegate {
private String att2 = "hi";
private String att3 = "howdy";
public Delegate(String att2, String att3) {
this.att2 = att2;
this.att3 = att3;
}
}
}
My point is if you need to accommodate to not-so-well structured xml, then I'm afraid that you will not be able to escape copy-pasting JAXB-annotated code. Defining an xsd schema and generating the classes from it can sometimes make this a less tedious job.