I have a Spring Application which is built on top of DynamoDB. I am trying to write a saveFoo() Repository method that will save an object of type Foo to the database. This method will be called from the application layer.
What I'm struggling with is that the Foo class has fields within it that are Dynamo specific. I don't want clients of the saveFoo() class to think they need to create an object of type Foo with these fields. Nor do I want them to attempt to ever set these values themselves.
These database-specific fields need public getters and setters in order to work with the DynamoDB SDK.
The database model class looks like the following:
#DynamoDBTable(tableName = "foo")
public class Foo {
// Fields the client should be setting
private String bar;
private String baz;
// Fields the client should not access and should not care about. They are internal fields used for DynamoDB purposes.
private Long version;
private String gsiIndexKey;
// Empty constructor needed for deserialization of data from dynamodb
public Foo() {
}
// Getters and setters for all of the above fields.
}
And the repository method to save the object to the DB:
public class FooRepositoryImpl {
public Foo saveFoo(WhatClassShouldThisBe foo) {
// Code that saves a new Foo item to the database and returns it.
}
}
My current idea is to create a FooWrapper interface that the saveFoo() method can take as a parameter. The wrapper will allow the client to set the fields that they should have control over, but does not expose fields related to the database internals. Something like the below:
/**
* Allows us restrict visibility of the Foo fields to the Application by hiding database internal fields.
**/
public interface FooWrapper {
Foo getFoo()
}
public class FooWrapperImpl implements FooWrapper {
private final Foo foo;
public FooWrapperImpl(String bar, String baz) {
foo = new Foo();
foo.setBar(bar);
foo.setBaz(baz);
}
#Override
public Foo getFoo() {
return foo;
}
}
public class FooRepositoryImpl {
public Foo saveFoo(FooWrapper fooWrapper) {
Foo foo = fooWrapper.getFoo(); // Save this item to db
// Code that saves a new Foo item to the database and returns it.
}
}
What are your thoughts on this approach? Does anyone know of some better techniques I could try? I can't help but feel that I am over-engineering things here.
Expose only an interface to clients that has the methods you want. Internally you can call the other public methods of the implementation, but the client code won't know them.
If you are using modern Java, don't export your implementation classes outside of your module. Only export the public interface.
You could also keep an interface for internal use that has more methods than the public API.
public interface Foo {
public void setBar(String bar);
public void setBaz(String baz);
}
#DynamoDBTable(tableName = "foo")
public class FooImpl implements Foo {
// Fields the client should be setting
private String bar;
private String baz;
// Fields the client should not access and should not care about. They are internal fields used for DynamoDB purposes.
private Long version;
private String gsiIndexKey;
// Empty constructor needed for deserialization of data from dynamodb
public FooImpl() {
}
// Getters and setters for all of the above fields.
#Override
public void setBar(String bar) {
this.bar = bar;
}
#Override
public void setBaz(String baz) {
this.baz = bar;
}
// Not part of the Foo interface
public void setVersion(Long version) {
this.version = version;
}
public void setGsiIndexKey(String indexKey) {
this.gsiIndexKey = indexKey;
}
}
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.
Suppose I have a file like this:
import javax.swing.JPanel;
import java.awt.event.MouseAdapter;
public class Foo extends JPanel
{
private int m;
private int n;
private int o;
public Foo()
{
this.addMouseListener(new Bar());
}
class Bar extends MouseAdapter
{
// ...
// methods here access and modify values of the private
// instance variables.
// ...
}
}
Obviously I can add simple accessors and mutators to Foo but that gets tedious fast and completely breaks encapsulation. How can I refactor this inner class while keeping damage to encapsulation to a minimum?
If these classes seem too big, then you should split them. The first step in splitting them would be to stop relying on private instance variables of the outer class. You could, as you say, add public getters and setters, but better would be to have Foo implement a public interface of Bar, and have Bar simply talk to that interface. And initialize each Bar with self.
public class Bar extends MouseAdapter {
public interface Caller {
void thingClicked();
...
}
}
public class Foo extends JPanel implements Bar.Caller {
...
}
So where now in Bar you have something like:
public void mouseUp() {
m = m + 1;
n = 0
}
you would now have
public void mouseUp() {
caller.thingClicked();
}
and, in Foo:
public void thingClicked() {
m = m + 1;
n = 0
}
It's hard to make this clear without more specifics, but basically your outer class is responding to messages, and the mouse listener is only responsible for delivering those messages, not for what happens in response to them. In the examples above it looks like this is more code than what you already have, but I suspect you'll find that slicing it out in this way ultimately leads to less code - and certainly code which is easier to test and reuse.
One approach is to put the class bar in a new file and inject everything you need there into the constructor. You'd need to change your primitive types like int into objects like Integer. Then you can create a Builder class that steers the construction of Foo and Bar. Let's assume for simplicity you need the same instance of Baz in all of your Foo and Bar instances:
class Builder {
// objects that both classes need are stored as member variables
// if you need multiple instances of baz you can also store a BazBuilder here
private Baz baz;
public Builder(Baz baz) {
this.baz=baz;
}
public Foo buildFoo() {
Foo foo = new Foo(baz);
return foo;
}
public Bar buildBar() {
Bar bar = new Bar(baz);
return bar;
}
}
This is only a minimalistic example but it's easy to extend. Builder#buildFoo() could take arguments that are needed in the constructor of Foo and likewise for Bar.
EDIT
Small example of what it might look like with a BazBuilder:
class BazBuilder {
Baz build(int value) {
return new Baz(value);
}
}
And in Builder you can use it like so:
class Builder {
private BazBuilder bazBuilder;
public Build(BazBuilder bazBuilder) {
this.bazBuilder = bazBuilder;
}
public Foo buildFoo() {
Baz baz = bazBuilder.build(5);
Bar bar = new Bar(baz);
Foo foo = new Foo(baz);
foo.add(bar);
return foo;
}
}
I have an abstract POJO class which is named Person and two entities which are named Developer and Manager. These entities inherits Person abstract class. There is no problem to save them to the same collection but when I try to find, for instance, only developers in the collection, Morphia's find method gets me all records in the collection and I get java.lang.ClassCastException.
Morphia morphia = new Morphia();
Datastore ds = morphia.createDatastore("test");
for (Developer savedDeveloper : ds.find(Developer.class).asList()) {
System.out.println(savedDeveloper.getFoo());
}
Exception
Sep 27, 2013 11:56:18 AM com.google.code.morphia.logging.MorphiaLoggerFactory chooseLoggerFactory
INFO: LoggerImplFactory set to com.google.code.morphia.logging.jdk.JDKLoggerFactory
Developer1
Developer2
Exception in thread "main" java.lang.ClassCastException: test.model.Manager cannot be cast to test.model.Developer
at test.Test.main(Test.java:39)
Java Result: 1
So my questions is that how can I get only one specific entity list in a collection which has more than one entities?
My POJOs
Person.java
public abstract class Person {
#Id
private ObjectId objectid;
private String username;
public Person() {
}
/* ......Getters and Setters*/ }
People.java
#Entity("people")
public class Developer extends Person {
private String foo;
public Developer() {
}
public String getFoo() {
return foo;
}
public void setFoo(String foo) {
this.foo = foo;
}
}
Manager.java
#Entity("people")
public class Manager extends Person {
private String bar;
public Developer() {
}
public String getBar() {
return bar;
}
public void setBar(String bar) {
this.bar = bar;
}
}
There's actually an open issue on this: https://github.com/mongodb/morphia/issues/22
Polymorphic queries can actually get quite complicated to do correctly generically. They make me a bit nervous to contemplate, actually. That said, I was talking to the C# team and they have an approach that seems to work for them without too much heartburn so there's likely some inspiration there to borrow. For now, though, you'll have to manually include the className field as suggested above.
I resolved this problem with Morphia's BasicDAO. I created a DeveloperDAO class that inherits Morphia's BasicDAO class then I used DAO methods in order to make queries and it works.
public class DeveloperDAO extends BasicDAO<Developer, String> {
public DeveloperDAO(String dbName) throws UnknownHostException {
super(MongoSingleton.getInstance(), MorphiaSingleton.getInstance(), dbName);
} }
Test
public class Test {
public static void main(String[] args) throws UnknownHostException {
DeveloperDAO developerDAO = new DeveloperDAO("test");
for(Developer developer : developerDAO.find().asList())
System.out.println(developer.getFoo());
}}
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?
I'm working on some classes that get part of their configuration from global variables, e.g.
class MyClass {
public void MyClass(Hashtable<String, String> params) {
this.foo = GlobalClass.GLOBALVAR.get("foo");
this.bar = GlobalClass.GLOBALVAR.get("bar");
this.params = params;
}
}
This is bad for a couple of reasons, GLOBALVAR talks to a database to get some of the variables and this makes it really hard to make unit tests. The other problem is that I have many (dozens) of classes that inherit from MyClass, so I can't easily change the constructor signature.
My current solution is to create an additional default constructor and setter methods for params, foo and bar.
class MyClass {
// Other code still here for backwards compatibility.
public void MyClass() {
// Do nothing much.
}
public void setParams(Hashtable<String, String> params) {
this.params = params;
}
public void setFoo(Foo foo) {
this.foo = foo;
}
public void setBar(Bar bar) {
this.bar = bar;
}
}
Any ideas on a good way to refactor this, besides the way I did it? My other thought would be to use a factory method, but I'm afraid I'll run into polymorphic substitution problems.
I think I would start by doing the following. It let's your existing code work without modification, and allows you to add new constructors to the subclasses as you can. Once all of the subclasses have the new constructor, and all of the calls to the old constructors are gone, you can get rid of the GlobalClass and the constructors that use it. You can also then, hopefully, work on cleaning up the GLOBALVAR (the Car class in my code).
import java.util.Hashtable;
class MyClass
{
private final Foo foo;
private final Bar bar;
private final Hashtable<String, String> params;
public MyClass(final Hashtable<String, String> params)
{
this(params, GlobalClass.GLOBALVAR);
}
// added constructor
public MyClass(final Hashtable<String, String> params,
final FooBar fooBar)
{
this.foo = fooBar.getFoo();
this.bar = fooBar.getBar();
this.params = params;
}
}
class MySubClass
extends MyClass
{
public MySubClass(final Hashtable<String, String> params)
{
super(params);
}
// added constructor
public MySubClass(final Hashtable<String, String> params,
final FooBar fooBar)
{
super(params, fooBar);
}
}
// unchanged
class GlobalClass
{
public static Car GLOBALVAR;
}
// added interface
interface FooBar
{
Foo getFoo();
Bar getBar();
}
class Car
// added implements
implements FooBar
{
private Foo foo = new Foo();
private Bar bar = new Bar();
public Object get(final String name)
{
if(name.equals("foo"))
{
return (foo);
}
if(name.equals("bar"))
{
return (bar);
}
throw new Error();
}
// added method
public Foo getFoo()
{
return ((Foo)get("foo"));
}
// added method
public Bar getBar()
{
return ((Bar)get("bar"));
}
}
// unchanged
class Foo
{
}
// unchanged
class Bar
{
}
I think you should introduce an interface to put a layer of abstraction between the global variable collection and its consumers.
interface GlobalVars {
String get(String key);
}
You should introduce a constructor with limited scope, probably package-private
MyClass(GlobalVars globals, Map<String, String> params) {
// create the object
}
And then provide public static factory methods to use this constructor.
public static MyClass newMyClass(Map<String, String> params) {
return new MyClass(GlobalClass.GLOBAL_VAR, params);
}
With this design you can pass in a mock implementation of GlobalVars in a unit test from within the same package by explicitly invoking the constructor.
Addendum: Since params seems to be a required field, I would definitely make it final and avoid the approach where you add mutators to overwrite them.
private final Map<String, String> params;
Also, make a defensive copy to prevent l33t h4x.
this.params = Collections.unmodifiableMap(params);
Your class should take all of its dependencies in the constructor. It's a good idea to make it impossible to create an invalid or uninitialized instance of classes. Make foo and bar private and final, and set them in the constructor.
A slight variation on your approach would be to have an object of type GLOBALVAR in the class and use that instead of the actual global (that refactoring should be a simple search/replace). You can default the new variable to the actual global variable and provide an override for testing.
This GlobalClass.GLOBALVAR should be chopped up up into logical units. That way it would be easier to make mock objects for the unit tests. For example in my CAD/CAM metal cutting application I have a MaterialList, a SheetSizeList, PartNestingParameters, etc.
I don't have a huge list of variables stuff into one giant AppParameter class. They all hang off a ShopStandards object. For Unit Test involving a specific PartNestingParmeters I will just go ShopStandards.PartNestingParmeters = new MockPartNestingParameterTest114(). The test will run not realizing that the Part Nesting Parameters are a mockup. Plus this save me from having to doing dozens of assignments just to get the ShopStandard setup correctly for the test.
We have even more automated where many of the Mock load from files saved during the test run during initial development.
Since you mention that you have the freedom to modify the class hierarchy.
Change the base MyClass ctor to take in 3 parameters params, foo and bar. Comment out the GlobalVar references and simply cache passed in values
Compile.. this should throw up a bunch of compile errors - no ctor which takes 1 parameter.
Fix each one to pass in GlobalVar.get("foo") and GlobalVar.get("bar"). Get it to build.
Refine: Now minimize hits to the DB by lazy load and caching the foo and bar values. Expose via some property on GlobalVar.