Java bean testing framework - java

Is there a framework or library available that, when given a JavaBean, will "put it through its paces," i.e., test all the getters and setters, validate that a property matches the getters and setters, etc.?

Personally, I don't think that's the hardest part of testing. It'd be possible to do via reflection, but that's not what makes testing worthwhile.
The hard part is figuring out all the possible inputs, for "happy path" and erroneous situations, making sure that exceptions are thrown when they should be, etc.
Your Java Bean should be implementing equals and hashCode. I'd worry more about tests to check the equals contract: null equals, reflexive, symmetric, transitive, and not equals. Those aren't trivial.
Getters and setters are the least of your problems. When people talk about code coverage standards of 70% or better they often say that getters and setters can be left out.

While I agree that there are bigger problems to solve, there are cases for testing Java bean methods. Large teams teams working on large codebases can run into problems. I've seen several cases of copy/paste error leading to getters or setters working on the wrong property. Forgetfulness can lead to hashCode and equals methods becoming inconsistent. Finding bugs in this simple code can be very frustrating.
Bean Matchers is a library that can help in this regard. It provides a series of Hamcrest matchers for reflectively testing Java beans. For example:
#Test
public void testBean() {
assertThat(MyBean.class, allOf(
hasValidBeanConstructor(),
hasValidGettersAndSetters(),
hasValidBeanHashCode(),
hasValidBeanEquals(),
hasValidBeanToString()
));
}

Take a look at Reflection Test Utilities:
http://code.google.com/p/rtu/
Although if you're testing generated methods (based on fields in a class) it may not be worth it.

If you're not looking like something more fancy like http://commons.apache.org/validator/ I would recommend to write your own. Personally I don't like pure data holding objects without any behaviour - it's not very good design. So if I'm not forced to work with such objects (by working with j2ee f. e.), I try to get rid of them.

You could try http://oval.sourceforge.net/ Oval it allows you to use annotations on your beans and then execute a validate method. It's not fully JSR303 compliant. If you want to use something fully compliant you should check out the Hibernate Validator.
Like the post above states definitely check out apache commons validator.

Answering this in 2021 because sadly, this problem still exists.
Beans add up to the code base and have a very negative impact if your DevOps pipelines are imposing coverage restrictions on repos. There are two ways to overcome it.
Exclude the beans ( which I would say should not be done).
Write test cases for beans ( which is the most pathetic thing that we as a developer can do to waste our time :( ).
And in most cases, you will end up writing test cases for beans.
I have written this simple Utility/test case that uses reflection and can allow you to increase the Junit code coverage and save your time.
Bean under test: City
package com.test.beans;
import java.util.List;
/**
* #author ameena
*
*/
public class City {
private int postOffices;
private int jurdictaionAreas;
private double areaInSqMeter;
private long population;
private List<City> neighbourCities;
private boolean metro;
public int getJurdictaionAreas() {
return jurdictaionAreas;
}
public void setJurdictaionAreas(int jurdictaionAreas) {
this.jurdictaionAreas = jurdictaionAreas;
}
public double getAreaInSqMeter() {
return areaInSqMeter;
}
public void setAreaInSqMeter(double areaInSqMeter) {
this.areaInSqMeter = areaInSqMeter;
}
public long getPopulation() {
return population;
}
public void setPopulation(long population) {
this.population = population;
}
public int getPostOffices() {
return postOffices;
}
public void setPostOffices(int postOffices) {
this.postOffices = postOffices;
}
public List<City> getNeighbourCities() {
return neighbourCities;
}
public void setNeighbourCities(List<City> neighbourCities) {
this.neighbourCities = neighbourCities;
}
public boolean isMetro() {
return metro;
}
public void setMetro(boolean metro) {
this.metro = metro;
}
}
The class to automate the bean testing
package com.test.beans;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.jupiter.api.Assertions.fail;
import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import org.junit.jupiter.api.Test;
/**
* #author ameena
*
*/
class BeanTest {
public void invokeSetter(Object obj, String propertyName, Object variableValue)
{
PropertyDescriptor propDescriptor;
try {
propDescriptor = new PropertyDescriptor(propertyName, obj.getClass());
Method setter = propDescriptor.getWriteMethod();
try {
setter.invoke(obj,variableValue);
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
e.printStackTrace();
fail(e.getMessage());
}
} catch (IntrospectionException e) {
e.printStackTrace();
fail(e.getMessage());
}
}
public Object invokeGetter(Object obj, String variableName)
{
Object returnValue = null;
try {
PropertyDescriptor pd = new PropertyDescriptor(variableName, obj.getClass());
Method getter = pd.getReadMethod();
returnValue = getter.invoke(obj);
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | IntrospectionException e) {
e.printStackTrace();
fail(e.getMessage());
}
return returnValue;
}
private <T extends Object> void validateGettersSetters(List<T> objects) {
for (T t : objects) {
Class<?> aClass = t.getClass();
for (java.lang.reflect.Field field : aClass.getDeclaredFields()) {
System.out.println(field);
Class<?> c = field.getType();
if (c == String.class) {
invokeSetter(t, field.getName(), "dummy");
assertEquals("dummy", (invokeGetter(t, field.getName())));
} else if (c == Integer.class || c == int.class) {
invokeSetter(t, field.getName(), 1);
assertEquals(1, (invokeGetter(t, field.getName())));
}else if (c == Double.class || c == double.class) {
invokeSetter(t, field.getName(), 1d);
assertEquals(1d, (invokeGetter(t, field.getName())));
}else if (c == Long.class || c == long.class) {
invokeSetter(t, field.getName(), 1l);
assertEquals(1l, (invokeGetter(t, field.getName())));
}else if (c == Boolean.class || c == boolean.class) {
invokeSetter(t, field.getName(), true);
assertEquals(true, (invokeGetter(t, field.getName())));
}else if (c == List.class){
//Now based on your bean and filed name
switch(field.getName()) {
case "neighbourCities" :
invokeSetter(t, field.getName(), new ArrayList<City>());
assertNotNull(invokeGetter(t, field.getName()));
break;
}
}
}
}
}
#Test
void testBean() {
List<Object> objects = new ArrayList<>();
objects.add(new City());
validateGettersSetters(objects);
}
}
Nothing fancy, but it saved me for writing test cases for 23 beans :)
Regards
Amit Meena

I guess this library is the answer to your question:
http://outsidemybox.github.com/testUtils/
it tests all the bean's initial values, the setters, the getters, hashCode(), equals() and toString().
All you have to do is define a map of default and non default property/value.
It can also test objects that are beans with additional non default constructors.

Related

Argument(s) are different! Wanted:

I am writing a unit test for my below code
public class Class1 {
protected void execute(String a, String b) {
try{
process(a,b);
}
catch(Exception E){
Class2.write(e,Class1.class.getSimpleName())
}
}
private void process(String a, String b) {
validate(a,b);
// Doing some processing on a and b values
}
private void validate (String a, String b) {
if(a==null || a.isEmpty() || b==null || b.isEmpty())
throw new IllegalArgumentException("Input value cannot be null or empty");
}
}
For the above code, I am trying to write a UT which covers the exception use case. Below is my UT code,
#Test
public void test1(){
try {
PowerMockito.mockStatic(Class2.class);
PowerMockito.when(Class2.class, "write", Mockito.anyObject(), Mockito.anyString())
.thenCallRealMethod();
Class1 class1 = new Class1();
Class2.write(new IllegalArgumentException("Input value cannot be null or empty"),Class1.class.getSimpleClassName());
PowerMockito.verifyStatic(Class2.class, VerificationModeFactory.times(1));
class1.execute(Mockito.anyString(),Mockito.anyString());
} catch (Exception e) {
e.printStackTrace();
Assert.fail(e.getMessage());
}
}
I am getting the below exception when I execute the above test
Argument(s) are different! Wanted:
Class2.write{
java.lang.IllegalArgumentException:Input value cannot be null or empty,
Class1
}
Actual invocation has different arguments:
Class2.write{
java.lang.IllegalArgumentException:Input value cannot be null or empty,
Class1
}
Can someone please help me on resolving this issue?
I really appreciate your help and time
Thanks in Advance
Your Problem:
IllegalArgumentException does not use the string message for equality. It would be safer to test the string message or the class type. I would prefer that the test detect the type rather than the message, as the string message should not be used for control flow, it is an implementation detail.
System.out.println(Objects.equals(
new IllegalArgumentException(),
new IllegalArgumentException()));
// false
System.out.println(Objects.equals(
new IllegalArgumentException().getClass(),
new IllegalArgumentException().getClass()));
// true
So to mock this I would use matchers:
any(IllegalArgumentException.class), eq(Class1.class.getSimpleName())
Issues with your design:
I'm going to end with an argument against how this code is structured, being that it is not built around dependency injection. Rather than calling the static method Class2::write, you could be calling an instance method.
For example, create the interface:
public interface Writer {
void write(Exception e, String source);
}
You can now refactor the class to provide two ctors, one that accepts any writer, and one that defaults to Class2.
public class Class1 {
private final Writer writer;
public Class1() {
this(Class2::write);
}
public Class1(Writer writer) {
this.writer = writer;
}
protected void execute(String a, String b) {
try {
process(a,b);
}
catch (Exception E) {
writer.write(e, Class1.class.getSimpleName());
}
}
...
}
Using this strategy you can now simply create an instance mock of Writer. This avoids having to mock as static method which changes the bytecode of your application, and also make your class more flexible as it can support many different writer implementations now. Anything that is modifying the bytecode of the application should be used very sparingly, such as replacing static method calls, does not truly validate the runtime execution of your code.
In my opinion, the majority of the PowerMockito/PowerMock only help verify code which was not built with testability / flexibility in mind. You shouldn't need to use anything outside of the Mockito/EasyMock tool-set for well structured code. There are some exceptions but the tool-set should be used very sparingly.

How to iterate over all the declared fields of an object of a class [duplicate]

I need to make sure that no object attribute is null and add default value in case if it is null. Is there any easy way to do this, or do I have to do it manually by checking every attribute by its getters and setters?
You can use reflection to iterate over the object's field, and set them. You'd obviously need some sort of mapping between types or even field names and required default values but this can be done quite easily in a loop. For example:
for (Field f : obj.getClass().getFields()) {
f.setAccessible(true);
if (f.get(obj) == null) {
f.set(obj, getDefaultValueForType(f.getType()));
}
}
[Update]
With modern Java, you can use annotations to set the default values for fields on a per class basis. A complete implementation might look like this:
// DefaultString.java:
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
#Retention(RetentionPolicy.RUNTIME)
public #interface DefaultString {
String value();
}
// DefaultInteger.java:
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
#Retention(RetentionPolicy.RUNTIME)
public #interface DefaultInteger {
int value();
}
// DefaultPojo.java:
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
public class DefaultPojo {
public void setDefaults() {
for (Field f : getClass().getFields()) {
f.setAccessible(true);
try {
if (f.get(this) == null) {
f.set(this, getDefaultValueFromAnnotation(f.getAnnotations()));
}
} catch (IllegalAccessException e) { // shouldn't happen because I used setAccessible
}
}
}
private Object getDefaultValueFromAnnotation(Annotation[] annotations) {
for (Annotation a : annotations) {
if (a instanceof DefaultString)
return ((DefaultString)a).value();
if (a instanceof DefaultInteger)
return ((DefaultInteger)a).value();
}
return null;
}
}
// Test Pojo
public class TestPojo extends DefaultPojo {
#DefaultString("Hello world!")
public String stringValue;
#DefaultInteger(42);
public int integerValue;
}
Then default values for a TestPojo can be set just by running test.setDetaults()
You need to manually filter input to constructors and setters. Well... you could use reflection but I wouldn't advise it. Part of the job of constructors and setters is to validate input. That can include things like:
public void setPrice(double price) {
if (price < 0.0d) {
throw new IllegalArgumentException("price cannot be negative " + price);
}
this.price = price;
}
and
public void setName(String name) {
if (name == null) {
throw new NullPointerException("name cannot be null");
}
this.name = name;
}
You could use wrapper functions for the actual check and throwing the exception.
Non-reflective solution for Java 8, without using a series of if's, would be to stream all fields and check for nullness:
return Stream.of(id, name).allMatch(Objects::isNull);
This remains quite easy to maintain while avoiding the reflection hammer.
This will return true for null attributes.
Maybe check Hibernate Validator 4.0, the Reference Implementation of the JSR 303: Bean Validation.
This is an example of an annotated class:
public class Address {
#NotNull
private String line1;
private String line2;
private String zip;
private String state;
#Length(max = 20)
#NotNull
private String country;
#Range(min = -2, max = 50, message = "Floor out of range")
public int floor;
...
}
For an introduction, see Getting started with JSR 303 (Bean Validation) – part 1 and part 2 or the "Getting started" section of the reference guide which is part of the Hibernate Validator distribution.
You can create a function that returns a boolean value and checks every attribute. You can call that function to do the job for you.
Alternatively, you can initialize the object with default values. That way there is no need for you to do any checking.
I don't have enough context to give you a correct answer, but I'll suggest you to make you code immutable as much as possible. Use public final fields. No more getters or setters : every field has to be defined by the constructor. Your code is shorter, more readable and prevents you from writing code with side effects.
It doesn't prevent you from passing null arguments to your constructor though... You can still check every argument as suggested by #cletus, but I'll suggest you to throw IllegalArgumentException instead of NullPointerException that doesn't give no new hint about what you've done.
Anyway, that's what I do as much as I can and it improved my code (readability, stability) to a great extend. Everyone in my team does so and we are very happy with that. We learned that when we try to write some erlang code where everything is immutable.
Hope this helps.
I tried this and it works without any issues to validate if the field is empty.
I have answered your question partially as I haven't personally tried to add default values to attributes
if(field.getText()!= null && !field.getText().isEmpty())
Hope it helps
This is not to check for null, instead this will be helpful in converting an existing object to an empty object(fresh object). I dont know whether this is relevant or not, but I had such a requirement.
#SuppressWarnings({ "unchecked" })
static void emptyObject(Object obj)
{
Class c1 = obj.getClass();
Field[] fields = c1.getDeclaredFields();
for(Field field : fields)
{
try
{
if(field.getType().getCanonicalName() == "boolean")
{
field.set(obj, false);
}
else if(field.getType().getCanonicalName() == "char")
{
field.set(obj, '\u0000');
}
else if((field.getType().isPrimitive()))
{
field.set(obj, 0);
}
else
{
field.set(obj, null);
}
}
catch(Exception ex)
{
}
}
}

Alternate method of BeanInfo creation?

I recently moved my spring application from java 1.6 to java 1.8. This has caused the spring bootstrapping to take an order of magnitude longer (20s before, 4mins now). Tracing the cause has led me to the CachedIntrospectionResults class, which is created for every bean. When created it calls,
beanInfo = (shouldIntrospectorIgnoreBeaninfoClasses ?
Introspector.getBeanInfo(beanClass, Introspector.IGNORE_ALL_BEANINFO) :
Introspector.getBeanInfo(beanClass));
Introspector then creates the bean info, in java 1.6, it calls
private BeanDescriptor getTargetBeanDescriptor() {
// Use explicit info, if available,
if (explicitBeanInfo != null) {
BeanDescriptor bd = explicitBeanInfo.getBeanDescriptor();
if (bd != null) {
return (bd);
}
}
// OK, fabricate a default BeanDescriptor.
return new BeanDescriptor(this.beanClass);
}
However in java 1.8 it now calls,
private BeanDescriptor getTargetBeanDescriptor() {
// Use explicit info, if available,
if (explicitBeanInfo != null) {
BeanDescriptor bd = explicitBeanInfo.getBeanDescriptor();
if (bd != null) {
return (bd);
}
}
// OK, fabricate a default BeanDescriptor.
return new BeanDescriptor(this.beanClass, findCustomizerClass(this.beanClass));
}
private static Class<?> findCustomizerClass(Class<?> type) {
String name = type.getName() + "Customizer";
try {
type = ClassFinder.findClass(name, type.getClassLoader());
// Each customizer should inherit java.awt.Component and implement java.beans.Customizer
// according to the section 9.3 of JavaBeans™ specification
if (Component.class.isAssignableFrom(type) && Customizer.class.isAssignableFrom(type)) {
return type;
}
}
catch (Exception exception) {
// ignore any exceptions
}
return null;
}
This method as far as I can see was added with java 1.7, and since I don't define any customizer classes, it searches my full classpath then throws an exception which ends up taking a few hundred ms. The result being that each bean takes ~500ms to init. A huge hit to startup time.
I am now trying to find a way to work around this problem,
The spring documentation says to implement a BeanInfoFactory in order to customize the beanInfo creation. But I can't find anywhere that says how to actaually create BeanInfo for a provided class.
How would I actually do that? Introspector uses a bunch of private constructors to build it up so I can't really follow it, and simply returning an empty BeanInfo blows spring up. What does spring actually want with the beaninfo?
Any ideas?
Normally, when you provide an explicit BeanInfo, the Introspector will gather information automatically whenever the explicit BeanInfo returns null. So there should be no problem providing an empty BeanInfo that only returns a non-null BeanDescriptor to prohibit the automatic Customizer search.
For example:
import java.beans.*;
import java.util.stream.Stream;
public class BeanInfoTest {
public static void main(String... arg) throws IntrospectionException {
BeanInfo bi=Introspector.getBeanInfo(TheComponent.class, Object.class);
System.out.println("properties: ");
Stream.of(bi.getPropertyDescriptors())
.map(p->p.getPropertyType().getSimpleName()+' '+p.getName())
.forEach(System.out::println);
}
public static class TheComponent {
String foo;
int bar;
public String getFoo() {
return foo;
}
public void setFoo(String foo) {
this.foo = foo;
}
public int getBar() {
return bar;
}
public void setBar(int bar) {
this.bar = bar;
}
}
public static class TheComponentBeanInfo extends SimpleBeanInfo {
/** Overridden to prevent the automated search for a Customizer */
#Override
public BeanDescriptor getBeanDescriptor() {
System.out.println("Providing my explicit BeanDescriptor");
return new BeanDescriptor(TheComponent.class);
}
}
}
will print
Providing my explicit BeanDescriptor
properties:
int bar
String foo
So it found the properties using automated search while using the explicit BeanDescriptor.

Letting the code try different things until it succeeds, neatly

This is the second time I found myself writing this kind of code, and decided that there must be a more readable way to accomplish this:
My code tries to figure something out, that's not exactly well defined, or there are many ways to accomplish it. I want my code to try out several ways to figure it out, until it succeeds, or it runs out of strategies. But I haven't found a way to make this neat and readable.
My particular case: I need to find a particular type of method from an interface. It can be annotated for explicitness, but it can also be the only suitable method around (per its arguments).
So, my code currently reads like so:
Method candidateMethod = getMethodByAnnotation(clazz);
if (candidateMethod == null) {
candidateMethod = getMethodByBeingOnlyMethod(clazz);
}
if (candidateMethod == null) {
candidateMethod = getMethodByBeingOnlySuitableMethod(clazz);
}
if (candidateMethod == null) {
throw new NoSuitableMethodFoundException(clazz);
}
There must be a better way…
Edit: The methods return a method if found, null otherwise. I could switch that to try/catch logic, but that hardly makes it more readable.
Edit2: Unfortunately, I can accept only one answer :(
To me it is readable and understandable. I'd simply extract the ugly part of the code to a separate method (following some basic principles from "Robert C.Martin: Clean Code") and add some javadoc (and apologies, if necessary) like that:
//...
try {
Method method = MethodFinder.findMethodIn(clazz);
catch (NoSuitableMethodException oops) {
// handle exception
}
and later on in MethodFinder.java
/**
* Will find the most suitable method in the given class or throw an exception if
* no such method exists (...)
*/
public static Method findMethodIn(Class<?> clazz) throws NoSuitableMethodException {
// all your effort to get a method is hidden here,
// protected with unit tests and no need for anyone to read it
// in order to understand the 'main' part of the algorithm.
}
I think for a small set of methods what you're doing is fine.
For a larger set, I might be inclined to build a Chain of Responsibility, which captures the base concept of trying a sequence of things until one works.
I don't think that this is such a bad way of doing it. It is a bit verbose, but it clearly conveys what you are doing, and is easy to change.
Still, if you want to make it more concise, you can wrap the methods getMethod* into a class which implements an interface ("IMethodFinder") or similar:
public interface IMethodFinder{
public Method findMethod(...);
}
Then you can create instances of you class, put them into a collection and loop over it:
...
Method candidateMethod;
findLoop:
for (IMethodFinder mf: myMethodFinders){
candidateMethod = mf.findMethod(clazz);
if (candidateMethod!=null){
break findLoop;
}
}
if (candidateMethod!=null){
// method found
} else {
// not found :-(
}
While arguably somewhat more complicated, this will be easier to handle if you e.g. need to do more work between calling the findMethods* methods (such as more verification that the method is appropriate), or if the list of ways to find methods is configurable at runtime...
Still, your approach is probably OK as well.
I'm sorry to say, but the method you use seems to be the widely accepted one. I see a lot of code like that in the code base of large libraries like Spring, Maven etc.
However, an alternative would be to introduce a helper interface that can convert from a given input to a given output. Something like this:
public interface Converter<I, O> {
boolean canConvert(I input);
O convert(I input);
}
and a helper method
public static <I, O> O getDataFromConverters(
final I input,
final Converter<I, O>... converters
){
O result = null;
for(final Converter<I, O> converter : converters){
if(converter.canConvert(input)){
result = converter.convert(input);
break;
}
}
return result;
}
So then you could write reusable converters that implement your logic. Each of the converters would have to implement the canConvert(input) method to decide whether it's conversion routines will be used.
Actually: what your request reminds me of is the Try.these(a,b,c) method in Prototype (Javascript).
Usage example for your case:
Let's say you have some beans that have validation methods. There are several strategies to find these validation methods. First we'll check whether this annotation is present on the type:
// retention, target etc. stripped
public #interface ValidationMethod {
String value();
}
Then we'll check whether there's a method called "validate". To make things easier I assume, that all methods define a single parameter of type Object. You may choose a different pattern. Anyway, here's sample code:
// converter using the annotation
public static final class ValidationMethodAnnotationConverter implements
Converter<Class<?>, Method>{
#Override
public boolean canConvert(final Class<?> input){
return input.isAnnotationPresent(ValidationMethod.class);
}
#Override
public Method convert(final Class<?> input){
final String methodName =
input.getAnnotation(ValidationMethod.class).value();
try{
return input.getDeclaredMethod(methodName, Object.class);
} catch(final Exception e){
throw new IllegalStateException(e);
}
}
}
// converter using the method name convention
public static class MethodNameConventionConverter implements
Converter<Class<?>, Method>{
private static final String METHOD_NAME = "validate";
#Override
public boolean canConvert(final Class<?> input){
return findMethod(input) != null;
}
private Method findMethod(final Class<?> input){
try{
return input.getDeclaredMethod(METHOD_NAME, Object.class);
} catch(final SecurityException e){
throw new IllegalStateException(e);
} catch(final NoSuchMethodException e){
return null;
}
}
#Override
public Method convert(final Class<?> input){
return findMethod(input);
}
}
// find the validation method on a class using the two above converters
public static Method findValidationMethod(final Class<?> beanClass){
return getDataFromConverters(beanClass,
new ValidationMethodAnnotationConverter(),
new MethodNameConventionConverter()
);
}
// example bean class with validation method found by annotation
#ValidationMethod("doValidate")
public class BeanA{
public void doValidate(final Object input){
}
}
// example bean class with validation method found by convention
public class BeanB{
public void validate(final Object input){
}
}
You may use Decorator Design Pattern to accomplish different ways of finding out how to find something.
public interface FindMethod
{
public Method get(Class clazz);
}
public class FindMethodByAnnotation implements FindMethod
{
private final FindMethod findMethod;
public FindMethodByAnnotation(FindMethod findMethod)
{
this.findMethod = findMethod;
}
private Method findByAnnotation(Class clazz)
{
return getMethodByAnnotation(clazz);
}
public Method get(Class clazz)
{
Method r = null == findMethod ? null : findMethod.get(clazz);
return r == null ? findByAnnotation(clazz) : r;
}
}
public class FindMethodByOnlyMethod implements FindMethod
{
private final FindMethod findMethod;
public FindMethodByOnlyMethod(FindMethod findMethod)
{
this.findMethod = findMethod;
}
private Method findByOnlyMethod(Class clazz)
{
return getMethodOnlyMethod(clazz);
}
public Method get(Class clazz)
{
Method r = null == findMethod ? null : findMethod.get(clazz);
return r == null ? findByOnlyMethod(clazz) : r;
}
}
Usage is quite simple
FindMethod finder = new FindMethodByOnlyMethod(new FindMethodByAnnotation(null));
finder.get(clazz);
... I could switch that to try/catch logic, but that hardly makes it more readable.
Changing the signature of the get... methods so you can use try / catch would be a really bad idea. Exceptions are expensive and should only be used for "exceptional" conditions. And as you say, the code would be less readable.
What is bothering you is the repeating pattern used for flow control--and it should bother you--but there isn't too much to be done about it in Java.
I get really annoyed at repeated code & patterns like this, so for me it would probably be worth it to extract the repeated copy & paste control code and put it in it's own method:
public Method findMethod(Class clazz)
int i=0;
Method candidateMethod = null;
while(candidateMethod == null) {
switch(i++) {
case 0:
candidateMethod = getMethodByAnnotation(clazz);
break;
case 1:
candidateMethod = getMethodByBeingOnlyMethod(clazz);
break;
case 2:
candidateMethod = getMethodByBeingOnlySuitableMethod(clazz);
break;
default:
throw new NoSuitableMethodFoundException(clazz);
}
return clazz;
}
Which has the disadvantage of being unconventional and possibly more verbose, but the advantage of not having as much repeated code (less typos) and reads easier because of there being a little less clutter in the "Meat".
Besides, once the logic has been extracted into it's own class, verbose doesn't matter at all, it's clarity for reading/editing and for me this gives that (once you understand what the while loop is doing)
I do have this nasty desire to do this:
case 0: candidateMethod = getMethodByAnnotation(clazz); break;
case 1: candidateMethod = getMethodByBeingOnlyMethod(clazz); break;
case 2: candidateMethod = getMethodByBeingOnlySuitableMethod(clazz); break;
default: throw new NoSuitableMethodFoundException(clazz);
To highlight what's actually being done (in order), but in Java this is completely unacceptable--you'd actually find it common or preferred in some other languages.
PS. This would be downright elegant (damn I hate that word) in groovy:
actualMethod = getMethodByAnnotation(clazz) ?:
getMethodByBeingOnlyMethod(clazz) ?:
getMethodByBeingOnlySuitableMethod(clazz) ?:
throw new NoSuitableMethodFoundException(clazz) ;
The elvis operator rules. Note, the last line may not actually work, but it would be a trivial patch if it doesn't.

Is it possible in Java to check if objects fields are null and then add default value to all those attributes?

I need to make sure that no object attribute is null and add default value in case if it is null. Is there any easy way to do this, or do I have to do it manually by checking every attribute by its getters and setters?
You can use reflection to iterate over the object's field, and set them. You'd obviously need some sort of mapping between types or even field names and required default values but this can be done quite easily in a loop. For example:
for (Field f : obj.getClass().getFields()) {
f.setAccessible(true);
if (f.get(obj) == null) {
f.set(obj, getDefaultValueForType(f.getType()));
}
}
[Update]
With modern Java, you can use annotations to set the default values for fields on a per class basis. A complete implementation might look like this:
// DefaultString.java:
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
#Retention(RetentionPolicy.RUNTIME)
public #interface DefaultString {
String value();
}
// DefaultInteger.java:
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
#Retention(RetentionPolicy.RUNTIME)
public #interface DefaultInteger {
int value();
}
// DefaultPojo.java:
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
public class DefaultPojo {
public void setDefaults() {
for (Field f : getClass().getFields()) {
f.setAccessible(true);
try {
if (f.get(this) == null) {
f.set(this, getDefaultValueFromAnnotation(f.getAnnotations()));
}
} catch (IllegalAccessException e) { // shouldn't happen because I used setAccessible
}
}
}
private Object getDefaultValueFromAnnotation(Annotation[] annotations) {
for (Annotation a : annotations) {
if (a instanceof DefaultString)
return ((DefaultString)a).value();
if (a instanceof DefaultInteger)
return ((DefaultInteger)a).value();
}
return null;
}
}
// Test Pojo
public class TestPojo extends DefaultPojo {
#DefaultString("Hello world!")
public String stringValue;
#DefaultInteger(42);
public int integerValue;
}
Then default values for a TestPojo can be set just by running test.setDetaults()
You need to manually filter input to constructors and setters. Well... you could use reflection but I wouldn't advise it. Part of the job of constructors and setters is to validate input. That can include things like:
public void setPrice(double price) {
if (price < 0.0d) {
throw new IllegalArgumentException("price cannot be negative " + price);
}
this.price = price;
}
and
public void setName(String name) {
if (name == null) {
throw new NullPointerException("name cannot be null");
}
this.name = name;
}
You could use wrapper functions for the actual check and throwing the exception.
Non-reflective solution for Java 8, without using a series of if's, would be to stream all fields and check for nullness:
return Stream.of(id, name).allMatch(Objects::isNull);
This remains quite easy to maintain while avoiding the reflection hammer.
This will return true for null attributes.
Maybe check Hibernate Validator 4.0, the Reference Implementation of the JSR 303: Bean Validation.
This is an example of an annotated class:
public class Address {
#NotNull
private String line1;
private String line2;
private String zip;
private String state;
#Length(max = 20)
#NotNull
private String country;
#Range(min = -2, max = 50, message = "Floor out of range")
public int floor;
...
}
For an introduction, see Getting started with JSR 303 (Bean Validation) – part 1 and part 2 or the "Getting started" section of the reference guide which is part of the Hibernate Validator distribution.
You can create a function that returns a boolean value and checks every attribute. You can call that function to do the job for you.
Alternatively, you can initialize the object with default values. That way there is no need for you to do any checking.
I don't have enough context to give you a correct answer, but I'll suggest you to make you code immutable as much as possible. Use public final fields. No more getters or setters : every field has to be defined by the constructor. Your code is shorter, more readable and prevents you from writing code with side effects.
It doesn't prevent you from passing null arguments to your constructor though... You can still check every argument as suggested by #cletus, but I'll suggest you to throw IllegalArgumentException instead of NullPointerException that doesn't give no new hint about what you've done.
Anyway, that's what I do as much as I can and it improved my code (readability, stability) to a great extend. Everyone in my team does so and we are very happy with that. We learned that when we try to write some erlang code where everything is immutable.
Hope this helps.
I tried this and it works without any issues to validate if the field is empty.
I have answered your question partially as I haven't personally tried to add default values to attributes
if(field.getText()!= null && !field.getText().isEmpty())
Hope it helps
This is not to check for null, instead this will be helpful in converting an existing object to an empty object(fresh object). I dont know whether this is relevant or not, but I had such a requirement.
#SuppressWarnings({ "unchecked" })
static void emptyObject(Object obj)
{
Class c1 = obj.getClass();
Field[] fields = c1.getDeclaredFields();
for(Field field : fields)
{
try
{
if(field.getType().getCanonicalName() == "boolean")
{
field.set(obj, false);
}
else if(field.getType().getCanonicalName() == "char")
{
field.set(obj, '\u0000');
}
else if((field.getType().isPrimitive()))
{
field.set(obj, 0);
}
else
{
field.set(obj, null);
}
}
catch(Exception ex)
{
}
}
}

Categories