How can I access a simple java object as a bean?
For example:
class Simple {
private String foo;
String getFoo() {
return foo;
}
private void setFoo( String foo ) {
this.foo = foo;
}
}
Now I want to use this object like this:
Simple simple = new Simple();
simple.setFoo( "hello" );
checkSettings( simple );
So I'm looking for the implementation of the method checkSettings( Object obj ):
public boolean checkSettings( Object obj ) {
// pseudocode here
Bean bean = new Bean( obj );
if( "hello".equals( bean.getAttribute( "foo" ) ) {
return true;
}
return false;
}
The java language contains a package called java.beans which sounds like it could help me. But I don't find a good starting point.
Any hints?
I think the functionality you're looking for resembles the one from the BeanUtils class of apache-commons:
http://commons.apache.org/beanutils/
Take a look at the getProperty() method of BeanUtils.
java.beans.Introspector.getBeanInfo yields an object implementing java.beans.BeanInfo, which in turn can be used to get PropertyDescriptors and MethodDescriptors (via its getPropertyDescriptors- and getMethodDescriptors-methods), which in turn can be used to get the information you actually want.
It is not really less effort than using reflection.
As stated in the question comments above I'm still not sure what you want, but it sort of sounds like you want to wrap an object gets & sets to an interface with a getAttribute. This is not what I think of as a "bean".
So you have an interface:
interface Thingie {
Object getAttribute(String attribute);
}
You would have to write an implementation of that that uses reflection.
class Thingie {
Object wrapped;
public Object getAttribute(String attribute) throws Exception {
Method[] methods = wrapped.getClass().getMethods();
for(Method m : methods) {
if (m.getName().equalsIgnoreCase("get"+attribute)) {
return m.invoke(wrapped);
}
}
}
}
Related
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.
I have a long list of object mapping to do from classes auto generated by JAXB.
customer.setCustomerId(rentalCustomer.getCustomerid().getValue()));
customer.setCustomerName(rentalCustomer.getTradingname().getValue());
customer.setVatNumber(rentalSearchCustomer.getVatNumber().getValue());
....
....
Basically I need to make a null check for ALL fields:
getValue(RentalCustomerIDType idType){
if(idType != null){
return idType.getValue();
}
else {
return "";
}
}
Problem is there are too many of these and they all have different types: RentalCustomerIDType, TradingType, VatNumberType..etc
Is there an elegant way to this by creating a GENERIC method that makes null check and return proper values for ALL maybe using Functional Libraries for Java?
Perhaps use reflection on the class when it's generated and eliminate all nulls by assigning non-null values to the fields?
Check an replace null values in multiple variables java
They say (the guy who answered) that they strongly disagree with using reflection for this purpose... but... meh. I've done it and it works.
You could use a generic method to declare the getValueFromAllObjects method and then use reflection to invoke the getValue method
public static <T> String getValueFromAllObjects(T t) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
if(t != null){
return (String) t.getClass().getDeclaredMethod("getValue").invoke(t);
}
else {
return "";
}
}
Refer to https://stackoverflow.com/a/54883454/442256 for reflection alternatives. I've just inlined an example in your code above
From what I understand, you do not want to be changing existing auto-generated classes. What you can do is create a CustomerWrapper class that wraps Customer and inserts defaults when a null is set to a field. This is the idea in code:
public class CustomerWrapper() {
private final Customer customer;
public CustomerWrapper(Customer customer) {
this.customer = customer;
}
public void setCustomerId(String id) {
this.customer.setCustomerId(id == null ? "" : id);
}
// Insert other methods here.
}
maybe a case for Aspect Oriented Programming, if its use is an option:
using an Advice in AspectJ (see around advice)
or (I have not checked this) Spring AOP How to change the return value by spring aop (closed, but has one answer)
I guess you want to use something like. here I have taken ResponseUserDto as my Pojo Class for null checks of it's properties.
private ResponseUserDto getValidNotNullPropertyObject(Object source) {
final BeanWrapper src = new BeanWrapperImpl(source);
Map < String, Object > result = new HashMap<>();
for (PropertyDescriptor property: src.getPropertyDescriptors()) {
if (src.getPropertyValue(property.getName()) == null) {
/* if(property.getPropertyType() == ?) {
//maybe do somethig here
}*/
result.put(property.getName(), ""); // this is start
} else {
result.put(property.getName(), src.getPropertyValue(property.getName()));
}
}
final ObjectMapper mapper = new ObjectMapper(); // Jackson's ObjectMapper
final ResponseUserDto finalResult = mapper.convertValue(result, ResponseUserDto.class);
return finalResult;
}
and to use this, you can call it like this
return this.getValidNotNullPropertyObject(responseUserDto);
This does what you want. But there is a caveat. Each type must implement the same interface that provides the getValue() method. Otherwise, you will probably need reflection to get the method as you suspected. But here is a solution for posterity.
setType(rentalSearchCustomer::getCustomerid,
customer::setCustomerId);
setType(rentalSearchCustomer::getTradingname,
customer::setCustomerName);
setType(rentalSearchCustomer::getVatNumber,
customer::setVatNumber);
System.out.println(customer);
public static <T extends GetValue> void setType(Supplier<T> sup,
Consumer<String> con) {
if (sup.get() == null) {
con.accept("");
} else {
con.accept(sup.get().getValue());
}
}
interface GetValue {
public String getValue();
}
I have two ArrayLists - ArrayList1 and ArrayList2. Each of them is filled with objects - Object1 and Object2, respectively.
Both of these objects have method 'getText'.
Object1:
public String getText() { return "1";}
Object2:
public String getText() { return "2";}
At certain point I would like to loop through each of these lists using the same method (just with different parameter).
loopThroughList(1)
loopThroughList(2)
What is the syntax if I want to call a method, but I don't know which object it is going to be? This is the code I have so far:
for (Object o : lists.getList(listNumber)) {
System.out.println(o.getText());
}
It says Cannot resolve method getText. I googled around and found another solution:
for (Object o : lists.getList(listNumber)) {
System.out.println(o.getClass().getMethod("getText"));
}
But this gives me NoSuchMethodException error. Even though the 'getText' method is public.
EDIT: To get the correct list, I am calling the method 'getList' of a different object (lists) that returns either ArrayList1 or ArrayList2 (depending on the provided parameter).
class Lists
public getList(list) {
if (list == 1) {
return ArrayList1;
}
else if (list == 2) {
return ArrayList2;
}
}
Define an interface for the getText method
public interface YourInterface {
String getText();
}
Implement the interface on the respective classes
public class Object1 implements YourInterface {
#Override
public String getText() {
return "1";
}
}
public class Object2 implements YourInterface {
#Override
public String getText() {
return "2";
}
}
Modify your getList method to return List<YourInterface>
public static List<YourInterface> getList(int list){
List<YourInterface> result = new ArrayList<>();
if(list == 1){
// your initial type
List<Object1> firstList = new ArrayList<>();
result.addAll(firstList);
} else {
// your initial type
List<Object2> secondList = new ArrayList<>();
result.addAll(secondList);
}
return result;
}
Declaration for loopThroughList
public static void loopThroughList(List<YourInterface> list){
list.forEach(yourInterface -> System.out.println(yourInterface.getText()));
}
Sample usage.
public static void main(String[] args) {
loopThroughList(getList(1));
loopThroughList(getList(2));
}
Interfaces work great here, but there a couple of other options if you're dealing with legacy code and cannot use interfaces.
First would be to cast the list items into their respective types:
for (Object o : lists.getList(listNumber)) {
if(o instanceof Object1) {
Object1 o1 = (Object1)o;
System.out.println(o1.getText());
}
else if(o instanceof Object2) {
Object1 o2 = (Object2)o;
System.out.println(o2.getText());
}
else {
System.out.println("Unknown class");
}
}
You can also use reflection to see if the object has a getText method and then invoke it:
for (Object o : lists.getList(listNumber)) {
try {
System.out.println(o.getClass().getDeclaredMethod("getName").invoke(o));
}
catch(Exception e) {
System.out.println("Object doesn't have getText method");
}
}
This is awful. Can you elaborate on what specifically you are trying to do? Java is strong typed by design, and you are trying to get around it. Why? Instead of Object, use the specific class, or interface as previously suggested. If that's not possible, and you must use lists of Objects, use instanceof and casting eg:
for (Object o : lists.getList(listNumber)) {
if (o instanceof Object1) {
Object1 o1 = (Object1) o;
System.out.println(o1.getText());
} else if (o instanceof Object2) {
Object2 o2 = (Object2) o;
System.out.println(o2.getText());
}
}
This is where interfaces come in.
interface HasText {
public String getText();
}
class Object1 implements HasText {
#Override
public String getText() {
return "1";
}
}
class Object2 implements HasText {
#Override
public String getText() {
return "2";
}
}
private void test() {
List<HasText> list = Arrays.asList(new Object1(), new Object2());
for (HasText ht : list) {
System.out.println(ht);
}
}
If one of your objects is not in your control you can use a Wrapper class.
class Object3DoesNotImplementHasText {
public String getText() {
return "3";
}
}
class Object3Wrapper implements HasText{
final Object3DoesNotImplementHasText it;
public Object3Wrapper(Object3DoesNotImplementHasText it) {
this.it = it;
}
#Override
public String getText() {
return it.getText();
}
}
private void test() {
List<HasText> list = Arrays.asList(new Object1(), new Object2(), new Object3Wrapper(new Object3DoesNotImplementHasText()));
for (HasText ht : list) {
System.out.println(ht);
}
}
Just to add more to this answer and give you some more to think on this (Will try to do it in a simple, non-formal way). Using interfaces is the proper way of doing such operation. However, I want to stand on the "bad idea":
for (Object o : lists.getList(listNumber)) {
System.out.println(o.getClass().getMethod("getText"));
}
What you are doing here, is using a mechanism called Reflection:
Reflection is a feature in the Java programming language. It allows an
executing Java program to examine or "introspect" upon itself, and
manipulate internal properties of the program. For example, it's
possible for a Java class to obtain the names of all its members and
display them.
What you actually attempted, is using that mechanism, to retrieve the method through a Class reflection object instance of your Class (sounds weird, isn't it?).
From that perspective, you need to think that, if you want to invoke your method, you now have, in a sense, a meta-Class instance to manipulate your objects. Think of it like an Object that is one step above your Objects (Similarly to a dream inside a dream, in Inception). In that sense, you need to retrieve the method, and then invoke it in a different (meta-like) way:
java.lang.reflect.Method m = o.getClass().getMethod("getText");
m.invoke(o);
Using that logic, you could possibly iterate through the object list, check if method exists, then invoke your method.
This is though a bad, BAD idea.
Why? Well, the answer relies on reflection itself: reflection is directly associated with runtime - i.e. when the program executes, practically doing all things at runtime, bypassing the compilation world.
In other words, by doing this, you are bypassing the compilation error mechanism of Java, allowing such errors happen in runtime. This can lead to unstable behavior of the program while executing - apart from the performance overhead using Reflection, which will not analyze here.
Side note: While using reflection will require the usage of Checked Exception handling, it still is not a good idea of doing this - as you practically try to duck tape a bad solution.
On the other hand, you can follow the Inheritance mechanism of Java through Classes and Interfaces - define an interface with your method (let's call it Textable), make sure that your classes implement it, and then use it as your base object in your list declaration (#alexrolea has implemented this in his answer, as also #OldCurmudgeon has).
This way, your program will still make the method call decision making at Runtime (via a mechanism called late binding), but you will not bypass the compilation error mechanism of Java. Think about it: what would happen if you define a Textable implementation without providing the class - a compile error! And what if you set a non-Textable object into the list of Textables? Guess what! A compile error again. And the list goes on....
In general, avoid using Reflection when you are able to do so. Reflection is useful in some cases that you need to handle your program in such a meta-way and there is no other way of making such things. This is not the case though.
UPDATE: As suggested by some answers, you can use instanceof to check if you have a specific Class object instance that contains your method, then invoke respectively. While this seems a simple solution, it is bad in terms of scaling: what if you have 1000 different classes that implement the same method you want to call?
your objects have to implement a common interface.
interface GetTextable {
String getText();
}
class One implements GetTextable {
private final String text;
public One(final String text) {
this.text = text;
}
public String getText() {
return this.text;
}
}
class Two implements GetTextable {
private final String text;
public Two(final String text) {
this.text = text;
}
public String getText() {
return this.text;
}
}
#Test
public void shouldIterate() throws Exception {
List<GetTextable> toIterate = Arrays.asList(new One("oneText"), new Two("twoText"));
for(GetTextable obj: toIterate) {
System.out.println(obj.getText());
}
}
I have e.g. object like this:
Original obj = new Original();
And I use from this object e.g. method like(this object has many methods and fields):
obj.getMeYourName();
And I would like to have similar object which is almost same but some methods return something else. I want to solve it by facade.
So, at first I want to create facade and decided if I would return direct object or modified.
What is the best way?
Something like this: ?
Original obj = new Original();
OriginalFacade obj = new OriginalFacade(Original obj, boolean getDirectObject);
OriginalFacade(Original obj, boolean getDirectObject) {
if (getDirectObject) {
return obj //How to convert object into OriginalFacade type?
} else {
obj.setMeYourName("Something else");
return obj; //Howto convert object into OriginalFacade type?
}
}
So, I have 2 problems:
1, is it good solution choose original object or modified original object thru constructor with e.g. boolean getDirectObject?
2, how to easy return original object which must me mapped into OriginalFacade Object
Must I have implement all methods from original object?
Actually, the facade pattern uses a common interface that is used by clients.
For instance:
public interface Facade {
public String getMeYourName();
public void someOtherMethod();
}
public class Original implements Facade {
private String name;
Original(String name) {
this.name = name;
}
public String getMeYourName() {
return name;
}
public void someOtherMethod() {
// a lot of great code
}
}
public class Modified implements Facade {
private Facade original;
private String otherName;
Modified(Facade original, String otherName) {
this.original = original;
this.otherName = otherName;
}
public String getMeYourName() {
return otherName;
}
public void someOtherMethod() {
original.someOtherMethod();
}
}
The clients should only need to see the Facade interface, and shouldn't need to care which actual implementation they are dealing with.
Your code demonstrates you have not understood Facade at all.
In first place Facade should be used to provide a simple interface to complex algorithms.
Second, the facade pattern allows you to access its composed objects, for example:
public class OriginalFacade{
public Original original;
}
Unless you follow the Law of Demeter, this code is perfect valid.
Regardless, if Facade is used, you should not need to access those objects.
The following link explains a little bit of Facade
I recommend you buy and read this book
Facade is not the patter to be used here. It is used to make a complex interface simpler, for example, making out-of-the-box usage patterns.
In your case, why don't you just extend the Original class and overload the methods you want to behave differently?
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.