Design patterns for converting objects with nested lists - java

I have a service where the flow is basically the following:
Receive an input object. This is just a POJO object and I don't have much say in the design of it.
Convert to a normalized object for my service.
Perform some business logic on the normalized object, and gather some extra data about it.
Convert to an output object for another service that the data gets passed to. (Another POJO.)
Pass the converted data to another service.
What this means, though, is that a good portion of my service is converting from type InputFoo to type NormalizedFoo to type OutputFoo.
This would be a pretty easy task. I'm using the Google Collections library and can have a class like this:
public class InputFooToNormalizedFooConverter implements Function<InputFoo, NormalizedFoo> {
public NormalizedFoo apply(InputFoo input) {
NormalizedFoo output = new NormalizedFoo();
output.setProperty(input.getProperty());
}
}
and another class like this:
public class NormalizedFooFooToOutputFooConverter implements Function<NormalizedFoo, OutputFoo> {
public NormalizedFoo apply(InputFoo input) {
NormalizedFoo output = new NormalizedFoo();
output.setProperty(input.getProperty());
}
}
But each type of Foo essentially has a hierarchy like so:
public class Foo {
List<Bar> barItems;
// .. other properties
}
public class Bar {
List<Baz> bazItems;
List<Quux> quuxItems;
// .. other properties
}
public class Baz {
// .. other properties
}
public class Quux {
// .. other properties
}
This means that I have NormalizedFooToOutputFooConverter that has a NormalizedBarToOutputBarConverter implements Function<NormalizedBar, OutputBar> type and so on and so forth.
Even worse, the input doesn't quite match up exactly to the normalized model. It's more like
public class InputFoo {
public List<InputBar> bars;
public List<InputBaz> bazs;
public List<InputQuux> quuxs;
// .. other properties
}
public class InputBar {
private String barId;
// .. other properties
}
public class InputBaz {
private String barId;
private String bazId;
// .. other properties
}
public class InputQuux {
private String barId;
private String quuxId;
// .. other properties
}
In these models, I can figure out which Baz and Quux belongs to which Bar based on the barId that each one has.
At this point, I have about 20 different converters for going from Input to Normalized and Normalized to Output. And worse still, some of them have name like ReallyLongInputTypeToReallyLongNormalizedTypeConverter creating extremely long class names. I feel like I'm doing something wrong here, with all the converters. Is there a better way to organize my converters?

Related

Create Generic class/method to map one object to another

Since I'm a newbie, I would like to know if there is a better way to code this.
Let say we have batch (spring) where we have downloader/processor/mapper/writer for every type of file we receive since we have customized logic for each file type. X number of Mapper , X number of processor for X number of file types.
Currently looking into templatize the code so not much changes may be required when new type is introduced. Below is my idea. so let say mapper, we have different objects for different file types and all of them will be converted to object of Class CustomObject as below. mapper bean in sample spring context
bean id = "file1Mapper" class = "com.filemapper.file1Mapper"
and it invokes file1Mapper class which has mapping logic. Same for other files.
This is what I'm coming up with to avoid all those file1mapper, file2mapper...... instead one generic mapper which does all together, but looking for better solutions,
public class GMapper{
public <T> CustomObject map(T item){
CustomObject customObject = new CustomObject()
.WithABCDetails(getABCDetails(item));
}
private <T> XYZDetails getABCDetails(T item) {
ABCDetails details = new ABCDetails();
if( item instanceof A){
A a = (A)item;
// read a and map it to ABCDetails object
}
if( item instanceof B){
B b = (B)item;
// read b and map it to ABCDetails object
}
...
...
// repeat this if loop for mapping all file types.
return details;
}
}
Sample jsons
class ABCDetails{
// JsonProperty
Object1 ob1;
Object2 ob2;
Integer d;
}
class Object1{
// JsonProperty
Object3 ob3;
String abc;
String def;
}
class Object2{
// JsonProperty
String ab;
Integer e;
}
class A{
// JsonProperty
String e;
String d; // ex, this is mapped to Object 2 String "ab"
}
This does't look so professional and I believe there might be better ways to do it. Can someone please share an example or explanation on how can this code be made better. I also reading Functional interface to see if that could help.
Thanks in advance.
It is impossible to understand what you need. So I will give some common advice.
Format your code - use tabs/spaces to indent.
Do not put capital letters together - replace ABCDetails with AbcDetails. No one cares how real world name looks like.
Do not write meaningless comments - say no to // JsonProperty
Name variables so that someone can understand what they are supposed to store - avoid {Object1 ob1; Object2 ob2; Integer d;}
Do not write if ... else if ... else if ... or case when ... since this scales badly. Use Map. Examples below.
And a general solution to your problem: use plugin architecture - the best thing (and maybe the only thing) that OOP can offer. Just make all your processors implement common interface. And to work with plugins use dispatcher pattern.
First create all processors.
public interface FileProcessor {
String extension();
void process(String filename);
}
#Component
public final class CsvFileProcessor implements FileProcessor {
public String extension() {
return "csv";
}
public void process(String filename) {
/* do what you need with csv */
}
}
#Component
public final class JsonFileProcessor implements FileProcessor {
public String extension() {
return "json";
}
public void process(String filename) {
/* do what you need with json */
}
}
Then inject them into your dispatcher. Do not forget to process errors, for example, some files may not have suffix, for some files you will not have processor, etc.
#Component
public final class FileDispatcher {
private final Map<String, FileProcessor> processorByExtension;
#Autowired
public FileDispatcher(List<FileProcessor> processors) {
processorByExtension = processors.stream().collect(Collectors.toMap(p -> p.extension(), p -> p));
}
public void dispatch(String filename) {
String extension = filename.split("//.")[1];
processorByExtension.get(extension).process(filename);
}
}
Now if you need to support new file format you have to add only one class - implementation of FileProcessor. You do not have to change any of already created classes.

how to toggle the right class for checkbox listener?

I have a GUI with a start button and a checkbox that creates multiple instances of Class A (A blueprint of my web service) based on given text input. The checkbox if checked writes some additional elements to the XML file (which is the main output of the entire application). Now I want to add an additional checkbox which will provide the GUI to create instances of Class B which extends Class A but provides some additional fields and logic.
My question is that how can I implement this required functionality?
Given there is a createMyXML() method in class C which is doing the same for hardcoded arguments as Class A or Class B for its methods, should I extend it to take one of the class as a parameter and create instances for required elements in the XML?
P.S. It is probable that this question may be too subjective but I wonder what could be the approach or the 'right way' to do it.
Class A Anatomy
public class A {
private String id;
private Vector<String> inputs;
private Vector<String> outputs;
//***Getters and Setters for above.***
}
Class C Anatomy
public class C {
void createMyXML(){
for (A a : this.parser.getAttributes()){
createFirstElement(A a);
createSecondElement(A a);
// Or (This behavior should be triggered by the checkbox)
createFirstElement(B b);
createSecondElement(B b);}
}
If I understand your question right, you want a way of creating different instances that would create XML files based on some logic that differs from class to class, preferably easily extendable later on.
In this case the Factory Design Pattern seems like a reasonable solution. You define an interface with the craeteMyXML() method:
public interface I {
public void createMyXML();
}
Add a class for each XML creation logic. In this example I've added two classes: A and B, which implement the I interface.
Class A:
import java.util.Vector;
public class A implements I {
private String id;
private Vector<String> inputs;
private Vector<String> outputs;
#Override
public void createMyXML() {
System.out.println("Create XML by the rules of A.");
}
/* Getters and setters and other methods needed*/
}
Class B:
public class B implements I {
#Override
public void createMyXML() {
System.out.println("Create XML by the rules of B.");
}
}
You can use an enum as a parameter for the factory based on which it creates instances. You can use other options as well, for example a String value or int, it depends on your solution. Here, I define the available instances as an enum:
public enum Instance {
A, B
}
The Factory class creates instance of A or B using the super-type I.
public class Factory {
public static I createInstance(Instance i) {
if (i == Instance.A) {
return new A();
} else if (i == Instance.B) {
return new B();
} else {
return null;
}
}
}
I'm adding a Test class to quickly test this solution, you can incorporate it in your project.
public class Test {
public static void main(String[] args) {
I a = Factory.createInstance(Instance.A);
I b = Factory.createInstance(Instance.B);
a.createMyXML();
b.createMyXML();
}
}
When you execute this, it will produce the output:
Create XML by the rules of A.
Create XML by the rules of B.

Java SAXException: No deserializer for

I'm trying to write a web service method that has a an object as one of it's parameters and that object has a property that is another object type. There seems to be no problem with passing in a object as long as all of the objects properties are primitive types. As soon as one of the properties is another object it has issues even if that embedded object is made of all primitives.
I'm using SoapUI to test it and the error I get is org.xml.sax.SAXException: No deserializer for {http://WebService}MyEmbeddedObject
I'm thinking there must be an easy way to tell it to deserialize the embedded object too but can't for the life of me figure out how. At this point I'll take the hard way too I just need a solution, I can always try to improve it later.
The method in the web service I'm writing looks like this:
public boolean MethodName(MyObject object, String sessionID) throws Exception
{
//do Stuff
}
The MyObject Class looks like this:
public class MyObject implements java.io.Serializable
{
public String Description;
public MyEmbeddedObject Thing1;
public MyEmbeddedObject Thing2;
public MyEmbeddedObject[] Things;
}
The MyEmbeddedObject Class looks like this:
public class MyEmbeddedObject implements java.io.Serializable
{
public String SubThing1;
public String SubThing2;
public String SubThing3;
}
In my case this problem had nothing to do with implementing java.io.Serializable. In fact you could remove that and it will work just fine as long as you fix the actual problem.
The actual problem being that you can't use an object as an argument unless all of it's properties are primitive types UNLESS you also use that embeded object in the method itself. It seems to be some sort of compiler voodoo if you ask me but here's the solution in code. Hopefully this makes sense. I'll even take it one level deeper just for illustration purposes.
One thing you'll notice that I've changed in the solution is that the "MyEmbeddedObject" class is much more complicated looking. This is because I didn't know how to properly define arrays in java at the time I asked this question. I assumed it was the same as C# and unfortunately for me that compounded my problem but I eventually figured it out by banging my head long enough and reviewing sample code from the vendor this project is for.
Program
public boolean MethodName(MyObject object, String sessionID)
{
//do Stuff
}
public MyEmbeddedObject unusedMyEmbeddedObject()
{
return null;
}
public MyDoubleEmbeddedObject unusedMyDoubleEmbeddedObject()
{
return null;
}
In a separate class file
public class MyObject
{
public String description;
public MyEmbeddedObject thing1;
public MyEmbeddedObject thing2;
}
In a separate class file
public class MyEmbeddedObject
{
public MyDoubleEmbeddedObject subThing1;
private MyDoubleEmbeddedObject[] subThings;
public MyDoubleEmbeddedObject[] getSubThings()
{
return this.subThings;
}
public void setSubThings(final MyDoubleEmbeddedObject[] value)
{
this.subThings = value;
}
}
In a separate class file
public class MyDoubleEmbeddedObject
{
public String subSubString1;
public String subSubString2;
public String subSubString3;
}

Extending enum fields Java

I know that it isn't possible to extend enum in Java, but I am trying to find an elegant solution for the below
I am trying to model enums (or classes) which will contain http end points of various web services across regions, say I have service A and B, each will have 4 region specific end points in US, EU, JP or CN. (This is basically for some seperate debug code that I am writing, in production the end points will be picked from configuration)
I was hoping to do something like this (not compliant java code).
public enum IEndPoint {
NA_END_POINT,
EU_END_POINT,
JP_END_POINT,
CN_END_POINT,
}
public enum ServiceAEndPoint extends IEndPoint {
NA_END_POINT("http://A.com/");
EU_END_POINT("http://A-eu.com/");
JP_END_POINT("http://A-jp.com/");
CN_END_POINT("http://A-cn.com/");
}
I could do this using interfaces where I have a method for each region, but in my opinion the enum way is more expressive, is there any better way I could model this ? What I am looking for is if there is any better way to model the inheritence relation and also having the expressive power of enumerations.
ServiceAEndPoint.NA_END_POINT
vs
serviceAEndPoint.getNAEndPoint()
I'm assuming that you will also want a ServiceBEndPoint enum (and similar). In which case I don't think your model really makes that much sense.
IEndPoint is really an enumeration of the kind of environments/regions where a service might be running. It is not an enumeration of the services themselves. Each individual service (A, B or whatever) will have different addresses for each of the regions.
Therefore I would stick with just the IEndPoint enum, and then in some service-specific code have a lookup map that will give you the address for a given end-point. Something like this:
public enum IEndPoint {
NA_END_POINT,
EU_END_POINT,
JP_END_POINT,
CN_END_POINT,
}
public class ServiceABroker {
private static final Map<IEndPoint, String> addressesByEndPoint;
static {
addressesByEndPoint = new EnumMap<>();
addressesByEndPoint.put(NA_END_POINT, "http://A.com/");
addressesByEndPoint.put(EU_END_POINT, "http://A-eu.com/");
addressesByEndPoint.put(JP_END_POINT, "http://A-jp.com/");
addressesByEndPoint.put(CN_END_POINT, "http://A-cn.com/");
}
public String getAddressForEndPoint(IEndPoint ep) {
return addressesByEndPoint.get(ep);
}
}
If these are static final constants, then just put them in an interface. Name the interface something like IServiceAEndPointKeys, where the keys part is a convention.
Here's where I consider enums to be more appropriate and useful:
Example 1: File type. An enum containing jpg, pdf etc.
Example 2: Column definitions. If I have a table with 3 columns, I would write an enum declaring ID, Name, Description (for example), each one having parameters like column header name, column width and column ID.
Im not sure I understand you question, but you can add methods to an enum for example you could do something like the following:
public enum ServiceAEndPoint{
NA_END_POINT("http://A.com/");
EU_END_POINT("http://A-eu.com/");
JP_END_POINT("http://A-jp.com/");
CN_END_POINT("http://A-cn.com/");
private final String url;
private EndPoint(String url){
this.url=url;
}
public String getURL(){
return url;
}
}
Enums cannot be extended in such a manner, mostly because enums cannot be sub-classed or the constraints they must adhere to will not be possible to impose.
Instead leverage interfaces, like so
public interface IEndPoint;
public enum DefaultEndPoints implements IEndPoint {
NA_END_POINT,
EU_END_POINT,
JP_END_POINT,
CN_END_POINT,
}
public enum DefaultServiceEndPoints implements IEndPoint {
NA_END_POINT("http://A.com/");
EU_END_POINT("http://A-eu.com/");
JP_END_POINT("http://A-jp.com/");
CN_END_POINT("http://A-cn.com/");
}
public void doSomething(IEndPoint endpoint) {
...
}
The reason why one can't subclass in the manner you wish is related to the contract that enums will be both equal via .equals(object) and via ==. If you could subclass, would this make sense?
if ( (DefaultEndPoints)JP_END_POINT == (DefaultServiceEndPoints)JP_END_POINT) {
}
if you say "yes" then I would expect to be able to do this
DefaultEndPoint someEndpoint = DefaultServiceEndPoints.JP_END_POINT;
which would leave a door open for error, as there is no guarantee that a enum entry in one enum declaration is in the other enum declaration.
Could it be different? Perhaps, but it isn't, and changing it would definately introduce a lot of complications that would have to be thoroughly thought out (or it would open avenues to work around Java's strong static-type checking).
You may want to consider something like this:
public abstract class EndpointFactory {
public abstract String getNAEndPoint();
public abstract String getEUEndPoint();
}
public class ServiceAEndpointFactory extends EndpointFactory {
public static final String NA_END_POINT = "http://A.com/";
public static final String EU_END_POINT = "http://A-eu.com/";
public String getNAEndPoint() {
return ServiceAEndpointFactory.NA_END_POINT;
}
public String getEUEndPoint() {
return ServiceAEndpointFactory.EU_END_POINT;
}
}
public class ServiceBEndpointFactory extends EndpointFactory {
public static final String NA_END_POINT = "http://B.com/";
public static final String EU_END_POINT = "http://B-eu.com/";
public String getNAEndPoint() {
return ServiceAEndpointFactory.NA_END_POINT;
}
public String getEUEndPoint() {
return ServiceAEndpointFactory.EU_END_POINT;
}
}
Then you can refer to your strings directly like this:
ServiceAEndpointFactory.NA_END_POINT;
Or, you can use the base object if the type of service is not known until execution:
EndpointFactory ef1 = new ServiceAEndpointFactory();
String ep = ef1.getNAEndPoint();
The drawback of this is the redefinition of the get*Endpoint() functions in each sub-class. You could eliminate that by moving the static final variables to be not static in the base class and putting the getter/setter in the base class only one time. However, the drawback of that is you are not able to reference the values without instantiating an object (which essentially emulates what I find valuable with ENUMs).
How does a pattern like this appeal to you? I let the enum implement an interface and implement the interface in a Debug set and a Release set. The release set can then derive the property name from the enum name - which is neat.
public interface HasURL {
public String getURL();
}
public enum DebugEndPoints implements HasURL {
NA,
EU,
JP,
CN;
#Override
public String getURL() {
// Force debug to go to the same one always.
return "http://Debug.com/";
}
}
public enum NormalEndPoints implements HasURL {
NA,
EU,
JP,
CN;
final String url;
NormalEndPoints () {
// Grab the configured property connected to my name.
this.url = getProperty(this.name());
}
#Override
public String getURL() {
return url;
}
}

Double-nested Java generics

I asked a similar question this morning, thought I had it answered, actually implemented the proposed solution, and it failed to do what I need. So here's my full problem:
I have the following classes:
// Objects to process.
public class Apple {
private Color color;
private int numberOfSeeds;
// ...
}
public class Chair {
private Material madeOutOfMaterial;
private double price;
// ...
}
public class CellPhone {
private Manufacturer make;
private String model;
private boolean isSmartPhone;
// ...
}
// Contains the object that will be processed (an Apple, Chair, CellPhone instance, etc.)
// as well as metadata info about the processing itself (timestamp, a UUID for tracking
// purposes, etc.).
public class ProcessingMetadata<PROCESSABLE_OBJECT> {
private PROCESSABLE_OBJECT result;
private Date processedOnDate;
private String uuid;
// ...
}
// Abstract base class for processing PROCESSABLE_OBJECTs.
public abstract class ObjectProcessor<ProcessingMetadata<PROCESSABLE_OBJECT>> {
private String name;
public abstract ProcessingMetadata<PROCESSABLE_OBJECT> process(Data data);
}
// One concrete processor.
public class SimpleObjectProcessor extends ObjectProcessor<ProcessingMetadata<PROCESSABLE_OBJECT>> {
private Fizz fizz;
#Override
public ProcessingMetadata<PROCESSABLE_OBJECT> process(Data data) {
// Processes data one way, and returns a PROCESSABLE_OBJECT.
}
}
// Another concrete processor.
public class ComplexObjectProcessor extends ObjectProcessor<ProcessingMetadata<PROCESSABLE_OBJECT>> {
private Buzz buzz;
#Override
public ProcessingMetadata<PROCESSABLE_OBJECT> process(Data data) {
// Processes data differently, and returns a PROCESSABLE_OBJECT.
}
}
So that the final code, using all of these classes looks like this:
ObjectProcessor<ProcessingMetadata<Apple>> appleProcessor =
new ComplexObjectProcessor<ProcessingMetadata<Apple>>();
Data data = getData();
ProcessingMetadata<PROCESSABLE_OBJECT> meta = appleProcessor.process(data);
Apple apple = meta.getResult();
Date processedOn = meta.getProcessedOnDate();
String uuid = meta.getUUID();
This is the "API" that I want exposed to the developer. Grab some Data, select a typed processor, process the data, and get all the metadata you need.
The problem is that my ObjectProcessor<ProcessingMetadata<PROCESSABLE_OBJECT>> isn't legal. It gives me the following compiler error on the ProcessingMetadata portion of the class definition:
Syntax error on token(s), misplaced construct(s)
I have played with this class (and its concrete subclasses) all morning, and can't seem to get generics set up correctly to give me the API that I want. I'm open to requiring the PROCESSABLE_OBJECTs to actually being an interface, such as Processable, and having Apple, Chair, etc. implement it. But there's no telling what the client is going to want to process, and so I'd prefer not to force them to make their POJOs implement a Processabl interface, if at all possible.
So, is my desired API possible? If so, how? If not, then why, and what is the closest I can get to it? Thanks in advance!
Each of the items in the type parameter list needs to be a type parameter. In the class declaration of ObjectProcessor, ProcessingMetadata<PROCESSABLE_OBJECT> is not a generic type parameter.
You could specify PROCESSABLE_OBJECT as a parameterized type, and then specify a type extending ProcessingMetaData as another parameterized type.
public abstract class ObjectProcessor<
PROCESSING_METADATA extends ProcessingMetadata<PROCESSABLE_OBJECT>,
PROCESSABLE_OBJECT >
{ ... }
EDIT:
Your subclasses are also parameterized types. You need to declare those type parameters on the class itself. Then you can use them to parameterize the superclass.
public class SimpleObjectProcessor<
PROCESSING_METADATA extends ProcessingMetadata<PROCESSABLE_OBJECT>,
PROCESSABLE_OBJECT >
extends ObjectProcessor< PROCESSING_METADATA,PROCESSABLE_OBJECT >
{ ... }
I think in your api, the developer would use this line
ProcessingMetadata<PROCESSABLE_OBJECT> meta = appleProcessor.process(data);
as this
ProcessingMetadata<Apple> meta = appleProcessor.process(data);
The class declaration itself only takes a type parameter declaration, but you try to put ProcessingMetadata there.
public abstract class ObjectProcessor<PROCESSABLE_OBJECT> {
private String name;
public abstract ProcessingMetadata<PROCESSABLE_OBJECT> process(Data data);
}
public class SimpleObjectProcessor<PROCESSABLE_OBJECT>
extends ObjectProcessor<PROCESSABLE_OBJECT> {
private Fizz fizz;
#Override
public ProcessingMetadata<PROCESSABLE_OBJECT> process(Data data) {
// Processes data one way, and returns a PROCESSABLE_OBJECT.
}
}
ObjectProcessor<Apple> appleProcessor = new ComplexObjectProcessor<Apple>();
// Note: there is no PROCESSABLE_OBJECT here. Use the concrete type:
ProcessingMetadata<Apple> meta = appleProcessor.process(data);

Categories

Resources