I am struggling with the following:
The class is constructed through Spring
It implements the interface that consist of two methods (process, shutdown)
It also implements Callable
The problem:
process() returns a Type and it is called inside the call(), the problem is that process has input parameters which call() signature doesn’t allow. So I referred to this question: Is there a way to take an argument in a callable method?, unfortunately that wouldn't work for me as my object constructed through Spring, process() gets called from the JSP and the input parameters are variable, depending on the user action.
Will include some code for clarification, bellow:
public class MyClass implements MyClassInterface, Callable<Results> {
private String fileLocation;
private final SMTPMailer smtpMalier;
public MyClass(String fileLocation, SMTPMailer smtpMalier) {
this.fileLocation = fileLocation;
this.smtpMalier = smtpMalier;
}
public Results call() {
// to return process(arg1, arg2) here, need to cater for input parameters
}
public Results process(String arg1, String arg2) {
// does some proceeding, returns Results
}
public void shutdown() {
// shut down implementation
}
}
How can I go around this?
Short answer is, you can't.
The contract of Callable is that it can perform an action without any input.
If it needs parameters, it isn't Callable.
You need to consider how the code is called. I assume you have code like this:
AsyncTaskExecutor executor = ...;
MyClass theService = ...;
String foo = "apple", bar = "banana";
Future<Results> result = executor.submit(theService); // Needs foo and bar :(
The simple solution is, don't implement Callable in MyClass. It isn't callable, it needs some input parameters! Implement Callable where it makes sense instead, such as where you have all parameters:
AsyncTaskExecutor executor = ...;
MyClass theService = ...;
String foo = "apple", bar = "banana";
Future<Results> result = executor.submit(new Callable<Results>(){
#Override public Results call(){
return theService.process(foo, bar);
}
});
// Or if you're on Java 8:
Future<Results> result = executor.submit(() -> theService.process(foo, bar);
If this is something that happens a lot and you really really want the class to provide you with Callables, you could give it a factory method:
public class MyClass implements MyClassInterface {
public Results process(String arg1, String arg2) {
// does some proceeding, returns Results
}
public Callable<Results> bind(String arg1, String arg2) {
return () -> process(arg1, arg2);
}
// Other methods omitted
}
Related
the usage of method references as listeners in an observer pattern does not work.
Example:
public class ObserverWithMethodReferenceAsListenerTest {
class ListenerCurator {
private final Set<Consumer<String>> listeners = new HashSet<>();
public boolean register(final Consumer<String> consumer) {
return this.listeners.add(consumer);
}
public boolean unregister(final Consumer<String> consumer) {
return this.listeners.remove(consumer);
}
public int getListenersCount() {
return this.listeners.size();
}
}
class MyListenerLeaks {
public void theListener(final String someString) {
// the listener
}
}
class MyListenerWorks {
public Consumer<String> consumer = str -> {
theListener(str);
};
public void theListener(final String someString) {
// the listener
}
}
#Test
public void testListenerLeak() {
ListenerCurator lc = new ListenerCurator();
MyListenerLeaks ml = new MyListenerLeaks();
lc.register(ml::theListener);
Assert.assertEquals(1, lc.getListenersCount());
lc.register(ml::theListener);
// expected 1 but there are 2 listeners
lc.unregister(ml::theListener);
// there are 2 listeners registered here
}
#Test
public void testListenerWorks() {
ListenerCurator lc = new ListenerCurator();
MyListenerWorks ml = new MyListenerWorks();
lc.register(ml.consumer);
Assert.assertEquals(1, lc.getListenersCount());
lc.register(ml.consumer);
Assert.assertEquals(1, lc.getListenersCount());
lc.unregister(ml.consumer);
Assert.assertEquals(0, lc.getListenersCount());
}
}
Conclusion: each referencing of the listener method with ml::theListener generates a new object id for the reference? Right? Therefore there a multiple listeners registered and cannot be removed individually?
The MyListenerWorks class uses a member with a "constant" object id and works. Is there another workaround for this? Are my assumptions correct?
After I added some breakpoints to the HashSet#add and remove function.
I got some results for your questions in the images below:
1. each referencing of the listener method with ml::theListener generates a new object id for the reference? Right?
Ans: No. It would generate a new memory address into the HashSet. There would not be an object id. So in the test function:testListenerLeak, you cannot remove the listener correspondingly. Since you didn't get the listeners from the set before you remove it.
2. The MyListenerWorks class uses a member with a "constant" object id and works. Is there another workaround for this? Are my assumptions correct?
You could take a look of the Observer pattern in Spring, Vue, or some other famous project. they have something similar to what you want. But mostly I have ever read about this pattern is in the Event-driven model. They use the "instanceOf" to check the subclasses and their superclass.
From the Oracle documentation on Method References:
Method references enable you to do this; they are compact, easy-to-read lambda expressions for methods that already have a name.
A method reference is not a constant.
I wanted to do overloaded method dispatching and Visitor pattern looked too much convoluted.
My stupid mind came up with something like below, and it works. Is it fine to follow something like this ?
An interface
public interface Value {
default public Integer getValue(){
return 1;
}
}
One can have multiple types of Value interface, for example like two Value interface implementations below.
class ConcreteValueA implements Value {
#Override
public Integer getValue() {
return 2;
}
}
class ConcreteValueB implements Value {
#Override
public Integer getValue() {
return 3;
}
}
and a service implementation with overloaded methods like below which perform operations based on input type.
public class ImplA implements Interface{
private final Function<ConcreteValueA, Optional<String>> handleConcreteA = this::handle;
private final Function<ConcreteValueB, Optional<String>> handleConcreteB = this::handle;
private final Map<Class<? extends Value>, Function> functions;
public ImplA(){
functions = new HashMap<>();
functions.put(ConcreteValueA.class, handleConcreteA);
functions.put(ConcreteValueB.class, handleConcreteB);
}
/**
* Overridden method
*/
#Override
public Optional<String> handle(Value input) {
Function function = functions.get(input.getClass());
return (Optional<String>)function.apply(input);
}
/**
* Overloaded method A
*/
public Optional<String> handle(ConcreteValueA input) {
return Optional.of(input.getValue()+":A");
}
/**
* Overloaded method B
*/
public Optional<String> handle(ConcreteValueB input) {
return Optional.of(input.getValue()+":B");
}
/**
* Test method
*/
public static void main(String [] args){
Interface service = new ImplA();
Value input = new ConcreteValueB();
Optional<String> optional = service.handle(input);
System.out.println(optional.orElse("Default"));
}
}
Prints 3:B, which what I wanted.
Yes, Double Dispatch via reflection is a common replacement of the Visitor pattern in Java (and other languages that support introspection).
However, the Visitor pattern is still useful to let users to extend closed hierarchies, ie add a new virtual function to all classes of a hierarchy without changing them.
With the introduction of generics, I am reluctant to perform instanceof or casting as much as possible. But I don't see a way around it in this scenario:
for (CacheableObject<ICacheable> cacheableObject : cacheableObjects) {
ICacheable iCacheable = cacheableObject.getObject();
if (iCacheable instanceof MyObject) {
MyObject myObject = (MyObject) iCacheable;
myObjects.put(myObject.getKey(), myObject);
} else if (iCacheable instanceof OtherObject) {
OtherObject otherObject = (OtherObject) iCacheable;
otherObjects.put(otherObject.getKey(), otherObject);
}
}
In the above code, I know that my ICacheables should only ever be instances of MyObject, or OtherObject, and depending on this I want to put them into 2 separate maps and then perform some processing further down.
I'd be interested if there is another way to do this without my instanceof check.
Thanks
You could use double invocation. No promises it's a better solution, but it's an alternative.
Code Example
import java.util.HashMap;
public class Example {
public static void main(String[] argv) {
Example ex = new Example();
ICacheable[] cacheableObjects = new ICacheable[]{new MyObject(), new OtherObject()};
for (ICacheable iCacheable : cacheableObjects) {
// depending on whether the object is a MyObject or an OtherObject,
// the .put(Example) method will double dispatch to either
// the put(MyObject) or put(OtherObject) method, below
iCacheable.put(ex);
}
System.out.println("myObjects: "+ex.myObjects.size());
System.out.println("otherObjects: "+ex.otherObjects.size());
}
private HashMap<String, MyObject> myObjects = new HashMap<String, MyObject>();
private HashMap<String, OtherObject> otherObjects = new HashMap<String, OtherObject>();
public Example() {
}
public void put(MyObject myObject) {
myObjects.put(myObject.getKey(), myObject);
}
public void put(OtherObject otherObject) {
otherObjects.put(otherObject.getKey(), otherObject);
}
}
interface ICacheable {
public String getKey();
public void put(Example ex);
}
class MyObject implements ICacheable {
public String getKey() {
return "MyObject"+this.hashCode();
}
public void put(Example ex) {
ex.put(this);
}
}
class OtherObject implements ICacheable {
public String getKey() {
return "OtherObject"+this.hashCode();
}
public void put(Example ex) {
ex.put(this);
}
}
The idea here is that - instead of casting or using instanceof - you call the iCacheable object's .put(...) method which passes itself back to the Example object's overloaded methods. Which method is called depends on the type of that object.
See also the Visitor pattern. My code example smells because the ICacheable.put(...) method is incohesive - but using the interfaces defined in the Visitor pattern can clean up that smell.
Why can't I just call this.put(iCacheable) from the Example class?
In Java, overriding is always bound at runtime, but overloading is a little more complicated: dynamic dispatching means that the implementation of a method will be chosen at runtime, but the method's signature is nonetheless determined at compile time. (Check out the Java Language Specification, Chapter 8.4.9 for more info, and also check out the puzzler "Making a Hash of It" on page 137 of the book Java Puzzlers.)
Is there no way to combine the cached objects in each map into one map? Their keys could keep them separated so you could store them in one map. If you can't do that then you could have a
Map<Class,Map<Key,ICacheable>>
then do this:
Map<Class,Map<Key,ICacheable>> cache = ...;
public void cache( ICacheable cacheable ) {
if( cache.containsKey( cacheable.getClass() ) {
cache.put( cacheable.getClass(), new Map<Key,ICacheable>() );
}
cache.get(cacheable.getClass()).put( cacheable.getKey(), cacheable );
}
You can do the following:
Add a method to your ICachableInterface interface that will handle placing the object into one of two Maps, given as arguments to the method.
Implement this method in each of your two implementing classes, having each class decide which Map to put itself in.
Remove the instanceof checks in your for loop, and replace the put method with a call to the new method defined in step 1.
This is not a good design, however, because if you ever have another class that implements this interface, and a third map, then you'll need to pass another Map to your new method.
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;
}