I need to get a Field (or a list of Fields) without knowing it's name.
I.e: for a custom entitymanager i'd like to be able to do Method Calls like this:
cem.getEntities(MyEntity.class, ParamMap) where the ParamMap should be of the Type Map<Field, Object>.
What i can do at the moment is something like this:
Map<Field, Object> params = new HashMap<Field, Object>();
params.put(MyEntity.class.getDeclaredField("someFieldName"), 20);
List<MyEntity> entitysWithSomeFieldNameEquals20 = cem.getEntities(MyEntity.class, params);
Im trying to avoid the usage of querys, because it should work "generic" in the first place, but also be independent from Strings. (They are error-prone). The Entity Manager therefore uses reflection to determine the table and column names, he needs to use.
However, I STILL need to use
MyEntity.class.getDeclaredField("someFieldName")
which will simple move the error-prone string "out" of the entity manager...
What i'm trying to achieve would be something like this:
MyEntity.class.getDeclaredField(MyEntity.class.fields.someFieldName.toString())
So, no matter what the actual field is named, it can be referenced in a save way and refactoring will refactor all the field-access calls, too.
I'm not sure if this is possible. I could go with a (encapsuled) enum for ALL entities, but I hope, that theres a more generic way to achieve this.
Edit:
One good solution seems to be the usage of constants:
public class MyEntity{
private static string SOME_FIELD = "some_field_name_in_database";
#Column(name = SOME_FIELD);
private String someField;
}
...
Map<String, Object> params = new HashMap<String, Object>();
params.put(MyEntity.SOME_FIELD, matchValue);
List<MyEntity> result = eem.getEntities(MyEntity.class, params);
This at least reduces the usage of the string to exactly one location, where it can be maintained and changed without affecting any other file. But im still searching for a solution without constants, so the contants don't need to be synchronized with the available fields :-)
Ok, this is just an idea, which is not easy to implement, but it could work.
Suppose MyEntity looks like this:
public class MyEntity {
private String foo;
private String bar;
public String getFoo() { return this.foo; }
public void setFoo(String foo) { this.foo = foo; }
public String getBar() { return this.bar; }
public void setBar(String bar) { this.bar = bar; }
}
and there is an interface:
public interface Pattern {
public Class<?> getEntityClass();
public Map<Field, Object> getFields();
}
and there is a method, which takes a class and generates a pattern object, which is an instance of the given class:
public class PatternFactory {
public <T> T createPattern(Class<T> klass) {
// magic happens here
}
}
The requirement for the emitted instance would be that it should implement the Pattern interface, such that the method getFields returns only the fields which were explicitly set. GetEntityClass should return the entity class. Then the custom entity manager could be implemented like this:
public class EntityManager {
public <T> Collection<T> getEntities(T pattern) {
if (!(pattern instanceof Pattern))
throw new IllegalArgumentException();
Class<?> klass = ((Pattern) pattern).getEntityClass();
Map<Field, Object> fields = ((Pattern) pattern).getFields();
// fetch objects here
}
}
Then you could use it like this:
PatternFactory pf = // obtain somehow
EntityManager em = // obtain somehow
MyEntity pattern = pf.createPattern(MyEntity.class);
pattern.setFoo("XYZ");
pattern.setBar(null);
Collection<MyEntity> result = em.getEntities(pattern);
In this case pattern.getFields would return a map with two entries.
The difficulty here lies, of course, in the implementation of the createPattern method, where you will have to emit bytecode at run-time. However, this is possible and can be done.
Related
I want to define a DAO over a DynamoDB that has 20+ fields. In Java, I can use Lombok and do something like this to avoid a bunch of boilerplate code.
#Setter
#Getter
#DynamoDBTable("MyTable")
public class MyDAO {
//FIELD_1, FIELD_2, FIELD_3 defined as static final String elsewhere
#DynamoDBAttribute(attribute = FIELD_1)
private final String field1;
#DynamoDBAttribute(attribute = FIELD_2)
private final Long field2;
#DynamoDBAttribute(attribute = FIELD_3)
private final int field3;
...
}
The problem is if I had methods that did something for each field like the following, I would end up duplicating the code over and over again, because the setters in step 2 would be different and the field names in step 3 would be different (i.e. setField1 for the first and setField2 for the second).
public void addField1(String key, String field1Value) {
//Wrap some retry logic and error handling around the following
// 1. get DAO for key
// 2. set FIELD_1 to field1Value in DAO if not set
// 3. put DAO in DynamoDB using attribute name FIELD_1
}
public void addField2(String key, Long field2Value) {
//Wrap some retry logic and error handling around the following
// 1. get DAO for key
// 2. set FIELD_2 to field2Value in DAO if not set
// 3. put DAO in DynamoDB using attribute name FIELD_2
}
Ideally, I would like to have something like the addField method below, with all the retry logic so I don't have to duplicate everything for every field.
private void addField(String fieldName, String key, Object value);
public void addField1(String key, String field1Value) {
addField(FIELD_1, key, (Object) field1Value);
}
I've tried a map between field names and BiConsumers as such
Map<String, BiConsumer<MyDAO, Object>> setterMap =
new HashMap<String, BiConsumer<MyDAO, Object>>(){{
put(FIELD_1, MyDAO::setField1);
put(FIELD_2, MyDAO::setField2);
}};
private void addField(String fieldName, String key, Object value) {
...
// 2. Use setterMap.get(fieldName).accept(value);
...
}
The problem is I get an error saying that I cannot cast BiConsumer<MyDAO, String> to BiConsumer<MyDAO, Object>.
Is it the only way to do it - to create a separate map and method for each type? Or is there a more elegant way to do this?
Well, I don't think it's possible to do it using a Map if you want to preserve type safety. Instead, here's what I would do:
1) I'd create a special class like that:
#AllArgsConstructor
#Getter
final class FieldDefinition<T> {
private final String name;
private final BiConsumer<MyDAO, T> setter;
}
2) Then, I'd create constants in MyDAO (or, even better, in some helper object near MyDAO) like that:
static final FieldDefinition<String> FIELD_1_DEF = new FieldDefinition<>(FIELD_1, MyDAO::setField1);
3) Finally, I'd create the following type-safe addField method:
private <T> void addField(FieldDefinition<T> fieldDefinition, String key, T value) {
// ...
fieldDefinition.getSetter().accept(this, value);
// ...
}
which whould be called like that:
myDao.addField(FIELD_1_DEF, key, value);
Dynamic selection of methods is really not a good fit for functional interfaces. Parameterizing your code around method selection is better done with reflection, rather than with functional interfaces.
The main reason making it difficult to implement your logic using the BiConsumer interface is that you would technically still have to provide static implementations for it, for each field (whether using lambdas, method references, or classes...).
Here's an example reflection-based implementation:
private void addField(String fieldName, String key, Object value) {
MyDAO.class.getDeclaredField(fieldName).set(value, key);
}
So I'd just make setterMap a map of key to field name mapping, and use it like so:
private void addField(String key, Object value) {
String field = setterMap.get(key);
MyDAO.class.getDeclaredField(field).set(value, key);
}
I wonder what is the best practice of having some global mapping in a Java application?
Say I have a text file with the mapping:
key1:value1
key2:value2
...
keyN:valueN
The file is huge, and both keys and values are arbitrary, so I can't really use Enum.
In the Java application I'm going to instantiate a bunch of classes with keys as the input (note that the code is more adequate in reality, just trying to put it abstract and simple):
for(int i = 0; i < 10000; i++) {
String key = magicallyGetArbitaryKey();
SomeClass someClass = new SomeClass(key);
//do stuff
}
and assign a property in the constructor based on the map lookup.
public class SomeClass {
private String value;
public void SomeClass(String key) {
this.value = getValue(key);
}
private String getValue() {
// what is the best way to implement this?
}
}
I want my code to be simple and, what is important, testable. And avoid using frameworks such as Spring.
This is what I came up with so far: create a Holder class, which is simply a wrapper around the HashMap with the additional methods for initialization:
class MappingHolder {
private Map<String, String> keyValueMap = new HashMap();
public MappingHolder(String filePath){
keyValueMap = ...; //init from the file
}
public MappingHolder(Map initMap) { //constructor useful for testing
keyValueMap = initMap;
}
public String get(String key) {
return keyValueMap.get(key);
}
It seems to be obvious that I want to have only one instance of the mapping.
As far as I can see the options are:
Have the MappingHolder#getValue as a static method
public class SomeClass {
...
private String getValue() {
return MappingHolder.getValue()
}
Have the MappingHolder#getValue as an instance method, but make
field of the type MappingHolder static in the SomeClass
public class SomeClass {
...
private static MappingHolder mappingHolder = new MappingHolder();
private String getValue() {
return mappingHolder.getValue();
}
Make the MapppingHolder a singleton.
public class SomeClass {
...
private MappingHolder mappingHolder = MappingHolder.getInstance();
private String getValue() {
return mappingHolder.getValue();
}
Neither of this seems to me testable, having just JUnit and Mockito and not leveraging some more powerful mocking frameworks. Though I sucks in testing and maybe I am wrong.
So it would be great if one could recommend the approach, either how to develop further my own, or better one which I may be missing. Thanks!
Ive been searching for a robust way to compare my objects, I came across the ObjectUtils , and had the immidiate doubt that would it be able to compare it efficiently or not as I do not know how it works internally and documentation on apache org site about this is scarce.
Can someone please help me with this??
EDIT:
When I say compare , all I really need to to compare for equality of MYOBJ, where MYOBJ is a custom object I have defined , which has various variables in it(all these vars are primitive data types like int,long,float String which can be compares in a straightforward manner if they are not null), but this might change in the future.
I was not sure would BeanUtils.areEqual method be able to handle such a case and what if I include my own datatypes(non -primitives) inside this MYOBJ.
Thanks
Your Question is very vague, I don't really know what you are talking about, so I'll go in several Directions.
"compare my Objects" can mean several things. In Java, this usually means comparing them for sorting, i.e. through the Comparable / Comparator interfaces. While ObjectUtils does provide a null-safe compare method, it won't help you beyond that. What you need is either a custom Comparator or for your objects to implement Comparable. CompareToBuilder can help you with both, to a certain extent:
public class SomeBean implements Comparable<SomeBean>{
private String foo;
private int bar;
private List<String> baz;
public int compareTo(SomeBean other) {
return new CompareToBuilder()
.append(foo, other.foo)
.append(bar, other.bar)
.append(baz, other.baz)
.toComparison();
}
}
If, on the other hand, you want to compare the properties of different object types, then you are looking in the totally wrong direction. Have a look at Commons / BeanUtils instead. Sample code:
public class BeanUtilsTester {
public static class Foo{
private String foo="foo";
public String getFoo() {return foo;}
public void setFoo(String foo) {this.foo = foo;}
private Integer bar=123;
public Integer getBar() {return bar;}
public void setBar(Integer bar) {this.bar = bar;}
private List<String> squoggle=Arrays.asList("abc","def");
public List<String> getSquoggle() {return squoggle;}
public void setSquoggle(List<String> squoggle) {this.squoggle = squoggle;}
}
public static class Bar{
private String foo="bar";
public String getFoo() {return foo;}
public void setFoo(String foo) {this.foo = foo;}
private Integer bar=456;
public Integer getBar() {return bar;}
public void setBar(Integer bar) {this.bar = bar;}
private String[] fiddle=new String[]{"abc","def"};
public String[] getFiddle() {return fiddle;}
public void setFiddle(String[] fiddle) {this.fiddle = fiddle;}
}
public static void main(String[] args) throws Exception{
Foo foo = new Foo();
Bar bar = new Bar();
Map<String,Object> fooProps = BeanUtils.describe(foo);
Map<String,Object> barProps = BeanUtils.describe(bar);
fooProps.keySet().retainAll(barProps.keySet());
BeanUtils.populate(bar, fooProps);
assertEquals(foo.getFoo(),bar.getFoo());
assertEquals(foo.getBar(), bar.getBar());
}
}
And if you just want to implement equals() correctly, look at EqualsBuilder:
#Override
public boolean equals(Object obj) {
if (obj instanceof SomeBean) {
SomeBean other = (SomeBean) obj;
return new EqualsBuilder()
.append(foo, other.foo)
.append(bar, other.bar)
.append(baz, other.baz)
.isEquals();
}
return false;
}
ObjectUtils will work just fine with comparing user defined objects. Of course you'll need to implement the Comparable interface in any object that you'd like to compare using the library functions.
Just made a simple test
User user1 = new User();
User user2 = new User();
Assert.assertEquals(true,ObjectUtils.equals(user1, user2));
The test here displays false. It's not equal.
User user1 = new User();
User user2 = user1;
Assert.assertEquals(true,ObjectUtils.equals(user1, user2));
The previous test displays true.
I believe you want to test similarly like the first test without changing the user defined class. If I am right, you can't use this library to do comparison.
However if you implement the compare() method in the every bean that you want to compare, I believe you are able to use this.
I have a public class, which needs 7 parameters to be passed down. At the moment, I am able to make 3 of them being passed to constructor and another 4 to a public method in the class . Like this:
Public Class AClass{
private XClass axClass;
private String par4;
private String par5;
private String par6;
private String par7;
public AClass(String par1, String par2, String par3){
aXClass = new XClass(par1,par2,par3);
}
public execute(String par4,String par5, String par6, String par7){
//this is needed because they are used in other private methods in this class
this.par4 = par4;
this.par5 = par5;
this.par6 = par6;
this.par7 = par7;
//call other private methods within this class.
//about 7 lines here
}
}
My question is, is this the right way to ask client of the class to passing in paramters?
There shouldn't be anything stopping you from passing 7 parameters to a constructor, if that's what you want. I don't know if there's a maximum number of parameters that can be passed to a method in Java, but it's certainly higher than 7 if there is a max.
When you create a class and its public methods, you're creating an interface on how to use and access that class. So technically what you've done so far is correct. Is it the "right way" to ask the client of a class to pass in arguments? That's up to you, the designer of the interface.
My first instinct when I saw 7 parameters being passed was to silently ask "Is there some relationship between some or all of these parameters that might mean they'd go together well in a class of their own?" That might be something you address as you look at your code. But that's a question of design, not one of correctness.
I'd go for the Builder Pattern instead of many constructor parameters as suggested by
Effective Java Item 2: Consider a builder when faced with many constructor parameters
Here's a simple class to illustrate:
public class Dummy {
private final String foo;
private final String bar;
private final boolean baz;
private final int phleem;
protected Dummy(final Builder builder) {
this.foo = builder.foo;
this.bar = builder.bar;
this.baz = builder.baz;
this.phleem = builder.phleem;
}
public String getBar() {
return this.bar;
}
public String getFoo() {
return this.foo;
}
public int getPhleem() {
return this.phleem;
}
public boolean isBaz() {
return this.baz;
}
public static class Builder {
private String foo;
private String bar;
private boolean baz;
private int phleem;
public Dummy build() {
return new Dummy(this);
}
public Builder withBar(final String bar) {
this.bar = bar;
return this;
}
public Builder withBaz(final boolean baz) {
this.baz = baz;
return this;
}
public Builder withFoo(final String foo) {
this.foo = foo;
return this;
}
public Builder withPhleem(final int phleem) {
this.phleem = phleem;
return this;
}
}
}
You would instantiate it like this:
Dummy dummy = new Dummy.Builder()
.withFoo("abc")
.withBar("def")
.withBaz(true)
.withPhleem(123)
.build();
The nice part: you get all the benefits of constructor parameters (e.g. immutability if you want it), but you get readable code too.
Can't you just make a class/hashmap that stores these parameters and pass this to the function?
public excute(Storageclass storageClass){
//this is needed because they are used in other private methods in this class
this.par4 = storageClass.getPar4();
this.par5 = storageClass.getPar5();
this.par6 = storageClass.getPar6();
this.par7 = storageClass.getPar7();
//or
this.storageClass = storageClass;
}
I don't really see the problem with that.
In any case you could create a "Request" object or something like this:
class SomeClass {
private String a;
private String b;
....
public SomeClass( Request r ) {
this.a = r.get("a");
this.b = r.get("b");
...
}
public void execute( Request other ) {
this.d = other.get("d");
this.e = other.get("d");
...
}
}
See also: http://c2.com/cgi/wiki?TooManyParameters
Without knowing the use of the child class, I can say that there is nothing inherently wrong with what you have done.
Note though that you have to declare
private XClass axClass;
in the variables of your AClass.
However, you say 'I am able to make....' Does this mean there is some problem with declaring this another way?
I don't care for it much, because an object should be 100% ready to be used after its constructor is called. It's not as written in your example.
If the parameters passed into the execute method can simply be consumed, and that's the method of interest for clients, I see no reason for them to be data members in the class.
Without knowing more about your ultimate aims it's hard to tell. But I would re-think this implementation.
If you're planning on introducing an AClass.someMethod() that needs to know par4-7 without requiring you to have called AClass.excute(), then clearly you should be passing the parameters in the constructor.
On the other hand: if you can construct an instance of this object with only par1-3 and do something meaningful with it besides call excute() then it makes sense to allow the object to be constructed with fewer than the full seven parameters.
Yet my own aesthetic is to try and limit the number of "modes" that an object can be in which make certain methods work and others fail. So ideally, a fully-constructed object is ready to run any method the programmer might call. I'd worry about the design issue more than be too concerned about the sheer number of parameters to the constructor.
But as others have pointed out, sometimes there is a natural grouping of these parameters which can deserve objects of their own. For instance: in many APIs instead of passing (x, y, width, height) all over the place they use rectangle objects.
As others already wrote, it is technically correct to pass 7 parameters, although not very 'user-friendly', if you can say so.
Since you didn't write much about this class, I can suggest one small thing: in constructor you're just creating XClass object, so it would be sane to create this object before and pass it as a single parameter.
Something like this:
...
XClass aXClass = new XClass(par1, par2, par3);
AClass aClass = new AClass(aXClass);
...
And this is the constructor:
public AClass(XClass aXClass) {
this.aXClass = aXClass;
}
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.