Setting Default Value Strategy with Multiple Source Object in MapStruct - java

I want to generate null checks on mapped properties of my source objects and set to a default value if indeed the source property is null.
I have tried to use NullValuePropertyMappingStrategy.SET_TO_DEFAULT on #Mapper as well as on #Mapping targets but the generated code did not include the default setters..
So basically what I am trying to achieve is:
#Mapper(componentModel = "spring")
public interface OperationDataMapper {
OperationDTO from(Object 1 o1, Object2 o2);
}
So that my generated code becomes:
#Component
public class OperationDataMapperImpl implements OperationDataMapper {
#Override
public OperationDTO from(Object 1 o1, Object2 o2) {
if ( o1 == null && o2 == null ) {
return null;
}
OperationDTO operationDTO = new OperationDTO();
if ( o1 != null ) {
if(o1.getProp1() != null) {
operationDTO.setProp1( o1.getProp1() )
} else {
operationDTO.setProp1( "" ) // if property is a string for example
}
.
.
}
if ( o2 != null ) {
if(o2.getProp2() != null) {
operationDTO.setProp2( o2.getProp2() )
} else {
operationDTO.setProp2( "" ) // if property is a string for example
}
.
.
}
return operationDTO;
}
}
I didn't write my example with the default value strategy like the documentation points out because I it did not work on my attempts to map the nested properties with null values.. Interesting enough, the NullValueCheckStrategy works without any problems but the NullValuePropertyMappingStrategy does not.
I have also tried setting them using a #BeanMapping with no avail.
If someone could please point me in the right direction I would appreciate it!

The NullValuePropertyMappingStrategy is meant to be used for update mappings. If you want that to be applied you'll have to provide the OperationDTO through #MappingTarget.
The only way to achieve what you are looking for is to use Mapping#defaultValue or Mapping#defaultExpression

Related

Introduce a new variable instead of reusing the parameter "entity"

I am solving SonarQube issues , in that issues I face an below warning any one please tell me how can i fix it,
Here is my class
public static Agency updateEntity(AgencyModel model, Agency entity) {
if (model == null || entity == null) {
return null;
}
if (entity.getAgencyId() != model.getAgencyId()) {
entity = new Agency()
// for the above variable 'entity' i get the warning, "Introduce a new
variable instead of reusing the parameter "entity".
}
entity.setAgencyId(model.getAgencyId());
if (entity.getAgencyLogoLarge() == null) {
entity.setAgencyLogoLarge(new File());
}
entity.setAgencyLogoLarge(FileModel.updateEntity(model.getAgencyLogoLarge(), entity.getAgencyLogoLarge()));
if (entity.getAgencyLogoSmall() == null) {
entity.setAgencyLogoSmall(new File());
}
entity.setAgencyLogoSmall(FileModel.updateEntity(model.getAgencyLogoSmall(), entity.getAgencyLogoSmall()));
entity.setAgencyName(model.getAgencyName());
entity.setContactPersons(
AgencyContactPersonModel.updateEntities(model.getContactPersons(), entity.getContactPersons()));
entity.setOtherDetails(model.getOtherDetails());
entity.setClassification(ClassificationModel.updateEntity(model.getClassification(), entity.getClassification()));
entity.setStatus(entity.getStatus());
entity.setCreatedBy((model.getCreatedBy() != null && model.getCreatedBy() != 0) ? model.getCreatedBy()
: entity.getCreatedBy());
entity.setUpdatedBy((model.getUpdatedBy() != null && model.getUpdatedBy() != 0) ? model.getUpdatedBy()
: entity.getUpdatedBy());
entity.setUpdatedDate(new Date());
entity.setStatus(Constant.ACTIVE);
return entity;
}
In above method i get that warning , will any one please tell me that what is the best approach to solve the above problem.
Assigning a value to a method argument often indicates a bug (even though this is not the case in your example), which is probably why SonarQube gives that warning.
Assuming you have no way of disabling that warning (or you don't want to), you can eliminate it by introducing a new local variable:
public static Agency updateEntity(AgencyModel model, Agency entity) {
Entity result;
if (model == null || entity == null) {
return null;
}
if (entity.getAgencyId() != model.getAgencyId()) {
result = new Agency();
} else {
result = entity;
}
... use result variable instead of entity variable ...
return result;
}

A more elegant approach to multiple checks performed in java class?

I have the below conditions to check which I will be checking based on the value that I will be recieving on parameter incomingProduct, So, I have below multiple conditions but they look odd as every time multiple checks wil be performed please advise how can i customise the below checks with else if I can acheive the same thing.
String incomingProduct = wokerchoice.getProduct();
if (incomingProduct!= null && incomingProduct.equalsIgnoreCase("CD") ) {
wokerchoice.setFourceSystem
((String)configuration.getConfiguration().get("CD"));
}
if (incomingProduct!= null && incomingProduct.equalsIgnoreCase("MODITY") ) {
wokerchoice.setFourceSystem((String)configuration.getConfiguration().get("MODITY"));
}
if (incomingProduct!= null && incomingProduct.equalsIgnoreCase("WQEQD") ) {
wokerchoice.setFourceSystem((String)configuration.getConfiguration().get("WEREQD"));
}
if (incomingProduct!= null && incomingProduct.equalsIgnoreCase("QRTFI") ) {
wokerchoice.setFourceSystem((String)configuration.getConfiguration().get("WERFI"));
}
if (incomingProduct!= null && incomingProduct.equalsIgnoreCase("URES") ) {
wokerchoice.setFourceSystem((String)configuration.getConfiguration().get("V"));
}
if (incomingProduct!= null && incomingProduct.equalsIgnoreCase("FXQWNM") ) {
wokerchoice.setFourceSystem((String)configuration.getConfiguration().get("FXQWNM"));
}
if (incomingProduct!= null && incomingProduct.equalsIgnoreCase("IERTRD") ) {
wokerchoice.setFourceSystem((String)configuration.getConfiguration().get("IERTRD"));
}
if (incomingProduct!= null && incomingProduct.equalsIgnoreCase("UHVMM") ) {
wokerchoice.setFourceSystem((String)configuration.getConfiguration().get(UHV"MM"));
}
if (incomingProduct!= null && incomingProduct.equalsIgnoreCase("OPT") ) {
wokerchoice.setFourceSystem((String)configuration.getConfiguration().get("OPT"));
}
if (incomingProduct!= null && incomingProduct.equalsIgnoreCase("RECE") ) {
wokerchoice.setFourceSystem((String)configuration.getConfiguration().get("RECS"));
}
Since yours aren't the same, the usual thing to do is to put the incoming and outgoing mappings on a map:
Map<String, String> ht = new HashMap<String, String>(){ { put("ONE","ONE");
put("OTHER","TWO");} };
String cfg = ht.get(incomingProduct.toUpperCase());
if (cfg != null)
wokerchoice.setFourceSystem((String)configuration
.getConfiguration().get(cfg));
Sadly java doesn't yet give us the ability to declare literal maps so I used the ugly anonymous class hack you see above to get a one liner.
If you could get the incoming and outgoing mappings the same (which I recommend, though it might not be possible), you could use a list or array of strings instead.
String[] mapping = {"ONE", "TWO"};
String incoming = incomingProduct.toUpperCase();
if(Arrays.asList(mapping).contains(incoming)){
wokerchoice.setFourceSystem((String)configuration
.getConfiguration().get(incoming));
}
But really; assuming getConfiguration().get() returns a null if there is no value (and you can get rid if the mapping step), the best answer looks something like so:
String incoming = incomingProduct.toUpperCase();
Object cfg= configuration.getConfiguration().get(incoming);
If (cfg != null)
wokerchoice.setFourceSystem((String)cfg);

How can I reduce duplicate code in Hibernate classes?

At this point we have several Hibernate object classes in our project, like the following:
package org.carl.recordkeeper.entity;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Id;
public class BstRecordPK implements Serializable
{
// ------------------------------ FIELDS ------------------------------
private String bst;
private Integer instbit;
// --------------------- GETTER / SETTER METHODS ---------------------
#Id
#Column( name = "BST", nullable = false, length = 1 )
public String getBst()
{
return bst;
}
public void setBst( String bst )
{
this.bst = bst;
}
#Id
#Column( name = "INSTBIT", nullable = false )
public Integer getInstbit()
{
return instbit;
}
public void setInstbit( Integer instbit )
{
this.instbit = instbit;
}
// ------------------------ CANONICAL METHODS ------------------------
#Override
public boolean equals( Object o )
{
if ( this == o )
{
return true;
}
if ( o == null || getClass() != o.getClass() )
{
return false;
}
BstRecordPK that = (BstRecordPK)o;
if ( bst != null ? !bst.equals( that.bst ) : that.bst != null )
{
return false;
}
if ( instbit != null ? !instbit.equals( that.instbit ) : that.instbit != null )
{
return false;
}
return true;
}
#Override
public int hashCode()
{
int result = instbit != null ? instbit.hashCode() : 0;
result = 31 * result + ( bst != null ? bst.hashCode() : 0 );
return result;
}
}
We also have a duplicate code checker, which keeps going off when we create a new Hibernate class because one of the get/set pairs matches what's in another class (database tables with foreign keys). Is there a way to reduce duplicate code and still keep Hibernate happy? I've thought about using a base class, but it's not like there is a single column used in all the database tables.
Code duplication warning a meant to show copied sections of code normally produced with copy & paste. Copying code will reduce maintainability and may result in security issues.
If sonarqube shows me duplication warnings, I have a closer look on the section of fode and decide, if this is a false positive in sense that many pojos will share some code like getId() { return id; } even if the retrn type differs or I some programmer just re-implemented or copied a section.
I would strongly recommend to not reduce you entities. This will only lead to objuscation.
However, you can try to use #MappedSuperClass if you really bother about code dublication detection limitations.

How to convert from String to a primitive type or standard java Wrapper types

I have a java.lang.reflect.InvocationHandler and I need to implement the method invoke()
I have a value of type java.lang.String from my elaboration and I need to convert this value to the appropriate returnType expected by the method (it can be a primitive like int, boolean, double or wrapper classes like Boolean, Integer, Double, Float, etc).
Example:
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
String computedValue = compute(...);
return convert(method.getReturnType(), computedValue);
}
private Object convert(Class<?> returnType, String stringValue) {
return ...; // what's the simplest way?
}
I am not expecting to simply implement an automatic conversion between complex objects, but I expect a simple way to convert from String to the standard java types.
I've seen (too) many times stuff like this, but it doesn't seem appropriate to me:
public static Object toObject( Class clazz, String value ) {
if( Boolean.class.isAssignableFrom( clazz ) ) return Boolean.parseBoolean( value );
if( Byte.class.isAssignableFrom( clazz ) ) return Byte.parseByte( value );
if( Short.class.isAssignableFrom( clazz ) ) return Short.parseShort( value );
if( Integer.class.isAssignableFrom( clazz ) ) return Integer.parseInteger( value );
if( Long.class.isAssignableFrom( clazz ) ) return Long.parseLong( value );
if( Float.class.isAssignableFrom( clazz ) ) return Float.parseFloat( value );
if( Double.class.isAssignableFrom( clazz ) ) return Double.parseDouble( value );
return value;
}
and the above is not even the worse one I saw, so far :)
Does anybody have a secret trick here?
As far as I'm aware, there is no real alternative to the version you presented. You can simplify it a bit (since the wrapper types are all final), but you essentially need to use if or switch or hashing to switch on the class.
My advice is to code it like the above. Ugly code is only a problem per se if you have to look at it. So put it inside a utility method and don't look at it again.
FWIW - this is how I'd simplify the method:
public static Object toObject( Class clazz, String value ) {
if( Boolean.class == clazz ) return Boolean.parseBoolean( value );
if( Byte.class == clazz ) return Byte.parseByte( value );
if( Short.class == clazz ) return Short.parseShort( value );
if( Integer.class == clazz ) return Integer.parseInt( value );
if( Long.class == clazz ) return Long.parseLong( value );
if( Float.class == clazz ) return Float.parseFloat( value );
if( Double.class == clazz ) return Double.parseDouble( value );
return value;
}
This is simpler and more efficient. And it is equivalent to the original version because the classes are all final and because the specs state that equality for Class objects is object identity.
Arguably, we should be using the <wrapper>.valueOf(String) methods which return the wrapper objects directly.
I make no claim that this is less ugly ... but "beauty" is not a useful measure of code quality, because it is subjective and because it doesn't tell you whether the code is easy to understand and / or maintain.
UPDATE
To support primitive types as well, add the corresponding classes to the if conditions; e.g.
if (Boolean.class == clazz || Boolean.TYPE == clazz) {
return Boolean.parseBoolean(value);
}
It may now be getting to the point where doing a String switch on the type's name is more efficient, though there are some slightly knotty issues of type identity that need to be thought through. (In theory, you can have multiple types with the same full name that have been loaded by different classloaders. I think you'd need to "play fast and loose" in a classloader to do that with the primitive wrapper classes ... but I think it might still be possible.)
I think I found something
import java.beans.PropertyEditor;
import java.beans.PropertyEditorManager;
#Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String returnValue = ...
return convert(method.getReturnType(), returnValue);
}
private Object convert(Class<?> targetType, String text) {
PropertyEditor editor = PropertyEditorManager.findEditor(targetType);
editor.setAsText(text);
return editor.getValue();
}
I think that those 3 lines of code are better than the multiple ifs, and I avoided to add external library dependencies, since java.beans package is inside the Java standard libraries (javadocs: PropertyEditorManager).
I find it quite acceptable; my only perplexity is that PropertyEditor is contained in java.beans package and I would have preferred something available in java.util or java.lang.reflect package, since this code has nothing to do with java.beans actually.
The code above has also the advantage that you can register additional PropertyEditor instances to translate complex objects, btw. That's not a bad thing to have though.
I think it's better than a list of ifs, in beauty, but also in quality.
Probably org.apache.commons.beanutils.ConvertUtils can help?
import org.apache.commons.beanutils.ConvertUtils;
// ...
final Object v = ConvertUtils.convert("42", Integer.class);
I propose this:
List<Class<?>> clsList = new ArrayList<Class<?>>();
clsList.add(Boolean.class);
clsList.add(Integer.class);
//etc.
for (Class<?> cls : clsList) {
if (cls.isAssignableFrom(clazz)) {
return cls.getMethod("valueOf", new Class[] { String.class }).invoke(null, new Object[] { value });
//Missing in this example: Handle a few exceptions
}
}
I'll leave it to you whether this looks cleaner or uglier.
There is a lightweight library that parses strings to java types which does what you want. It's called type-parser and you can find it on github here.
Your above code could then look something like this:
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
TypeParser parser = TypeParser.newBuilder().build();
String computedValue = compute(...);
return parser.parseType(computedValue, method.getGenericReturnType());
}
in jdk8, you could now do something like so O(1) lookup time with no if statements...
A better version now that handles nulls correct is here
https://github.com/deanhiller/webpieces/blob/master/webserver/http-router/src/main/java/org/webpieces/router/impl/params/ObjectTranslator.java
private Map<Class<?>, Function<String, Object>> classToUnmarshaller = new HashMap<>();
private Map<Class<?>, Function<Object, String>> classToMarshaller = new HashMap<>();
public ObjectTranslator() {
classToUnmarshaller.put(Boolean.class, s -> s == null ? null : Boolean.parseBoolean(s));
classToUnmarshaller.put(Boolean.TYPE, s -> Boolean.parseBoolean(s));
classToUnmarshaller.put(Byte.class, s -> s == null ? null : Byte.parseByte(s));
classToUnmarshaller.put(Byte.TYPE, s -> Byte.parseByte(s));
classToUnmarshaller.put(Short.class, s -> s == null ? null : Short.parseShort(s));
classToUnmarshaller.put(Short.TYPE, s -> Short.parseShort(s));
classToUnmarshaller.put(Integer.class, s -> s == null ? null : Integer.parseInt(s));
classToUnmarshaller.put(Integer.TYPE, s -> Integer.parseInt(s));
classToUnmarshaller.put(Long.class, s -> s == null ? null : Long.parseLong(s));
classToUnmarshaller.put(Long.TYPE, s -> Long.parseLong(s));
classToUnmarshaller.put(Float.class, s -> s == null ? null : Float.parseFloat(s));
classToUnmarshaller.put(Float.TYPE, s -> Float.parseFloat(s));
classToUnmarshaller.put(Double.class, s -> s == null ? null : Double.parseDouble(s));
classToUnmarshaller.put(Double.TYPE, s -> Double.parseDouble(s));
classToUnmarshaller.put(String.class, s -> s);
classToMarshaller.put(Boolean.class, s -> s == null ? null : s.toString());
classToMarshaller.put(Boolean.TYPE, s -> s.toString());
classToMarshaller.put(Byte.class, s -> s == null ? null : s.toString());
classToMarshaller.put(Byte.TYPE, s -> s.toString());
classToMarshaller.put(Short.class, s -> s == null ? null : s.toString());
classToMarshaller.put(Short.TYPE, s -> s.toString());
classToMarshaller.put(Integer.class, s -> s == null ? null : s.toString());
classToMarshaller.put(Integer.TYPE, s -> s.toString());
classToMarshaller.put(Long.class, s -> s == null ? null : s.toString());
classToMarshaller.put(Long.TYPE, s -> s.toString());
classToMarshaller.put(Float.class, s -> s == null ? null : s.toString());
classToMarshaller.put(Float.TYPE, s -> s.toString());
classToMarshaller.put(Double.class, s -> s == null ? null : s.toString());
classToMarshaller.put(Double.TYPE, s -> s.toString());
classToMarshaller.put(String.class, s -> s == null ? null : s.toString());
}
public Function<String, Object> getUnmarshaller(Class<?> paramTypeToCreate) {
return classToUnmarshaller.get(paramTypeToCreate);
}
public Function<Object, String> getMarshaller(Class<?> type) {
return classToMarshaller.get(type);
}
such that you can then call
primitiveTranslator.getConverter(Integer.TYPE).apply(stringToConvert);

Java: avoid checking for null in nested classes (Deep Null checking)

Imagine I have a class Family. It contains a List of Person. Each (class) Person contains a (class) Address. Each (class) Address contains a (class) PostalCode. Any "intermediate" class can be null.
So, is there a simple way to get to PostalCode without having to check for null in every step? i.e., is there a way to avoid the following daisy chaining code? I know there's not "native" Java solution, but was hoping if anyone knows of a library or something. (checked Commons & Guava and didn't see anything)
if(family != null) {
if(family.getPeople() != null) {
if(family.people.get(0) != null) {
if(people.get(0).getAddress() != null) {
if(people.get(0).getAddress().getPostalCode() != null) {
//FINALLY MADE IT TO DO SOMETHING!!!
}
}
}
}
}
No, can't change the structure. It's from a service I don't have control over.
No, I can't use Groovy and it's handy "Elvis" operator.
No, I'd prefer not to wait for Java 8 :D
I can't believe I'm the first dev ever to get sick 'n tired of writing code like this, but I haven't been able to find a solution.
You can use for:
product.getLatestVersion().getProductData().getTradeItem().getInformationProviderOfTradeItem().getGln();
optional equivalent:
Optional.ofNullable(product).map(
Product::getLatestVersion
).map(
ProductVersion::getProductData
).map(
ProductData::getTradeItem
).map(
TradeItemType::getInformationProviderOfTradeItem
).map(
PartyInRoleType::getGln
).orElse(null);
Your code behaves the same as
if(family != null &&
family.getPeople() != null &&
family.people.get(0) != null &&
family.people.get(0).getAddress() != null &&
family.people.get(0).getAddress().getPostalCode() != null) {
//My Code
}
Thanks to short circuiting evaluation, this is also safe, since the second condition will not be evaluated if the first is false, the 3rd won't be evaluated if the 2nd is false,.... and you will not get NPE because if it.
If, in case, you are using java8 then you may use;
resolve(() -> people.get(0).getAddress().getPostalCode());
.ifPresent(System.out::println);
:
public static <T> Optional<T> resolve(Supplier<T> resolver) {
try {
T result = resolver.get();
return Optional.ofNullable(result);
}
catch (NullPointerException e) {
return Optional.empty();
}
}
REF: avoid null checks
The closest you can get is to take advantage of the short-cut rules in conditionals:
if(family != null && family.getPeople() != null && family.people.get(0) != null && family.people.get(0).getAddress() != null && family.people.get(0).getAddress().getPostalCode() != null) {
//FINALLY MADE IT TO DO SOMETHING!!!
}
By the way, catching an exception instead of testing the condition in advance is a horrible idea.
I personally prefer something similar to:
nullSafeLogic(() -> family.people.get(0).getAddress().getPostalCode(), x -> doSomethingWithX(x))
public static <T, U> void nullSafeLogic(Supplier<T> supplier, Function<T,U> function) {
try {
function.apply(supplier.get());
} catch (NullPointerException n) {
return null;
}
}
or something like
nullSafeGetter(() -> family.people.get(0).getAddress().getPostalCode())
public static <T> T nullSafeGetter(Supplier<T> supplier) {
try {
return supplier.get();
} catch (NullPointerException n) {
return null;
}
}
Best part is the static methods are reusable with any function :)
You can get rid of all those null checks by utilizing the Java 8 Optional type.
The stream method - map() accepts a lambda expression of type Function and automatically wraps each function result into an Optional. That enables us to pipe multiple map operations in a row. Null checks are automatically handled under the neath.
Optional.of(new Outer())
.map(Outer::getNested)
.map(Nested::getInner)
.map(Inner::getFoo)
.ifPresent(System.out::println);
We also have another option to achieve the same behavior is by utilizing a supplier function to resolve the nested path:
public static <T> Optional<T> resolve(Supplier<T> resolver) {
try {
T result = resolver.get();
return Optional.ofNullable(result);
}
catch (NullPointerException e) {
return Optional.empty();
}
}
How to invoke new method? Look below:
Outer obj = new Outer();
obj.setNested(new Nested());
obj.getNested().setInner(new Inner());
resolve(() -> obj.getNested().getInner().getFoo())
.ifPresent(System.out::println);
Instead of using null, you could use some version of the "null object" design pattern. For example:
public class Family {
private final PersonList people;
public Family(PersonList people) {
this.people = people;
}
public PersonList getPeople() {
if (people == null) {
return PersonList.NULL;
}
return people;
}
public boolean isNull() {
return false;
}
public static Family NULL = new Family(PersonList.NULL) {
#Override
public boolean isNull() {
return true;
}
};
}
import java.util.ArrayList;
public class PersonList extends ArrayList<Person> {
#Override
public Person get(int index) {
Person person = null;
try {
person = super.get(index);
} catch (ArrayIndexOutOfBoundsException e) {
return Person.NULL;
}
if (person == null) {
return Person.NULL;
} else {
return person;
}
}
//... more List methods go here ...
public boolean isNull() {
return false;
}
public static PersonList NULL = new PersonList() {
#Override
public boolean isNull() {
return true;
}
};
}
public class Person {
private Address address;
public Person(Address address) {
this.address = address;
}
public Address getAddress() {
if (address == null) {
return Address.NULL;
}
return address;
}
public boolean isNull() {
return false;
}
public static Person NULL = new Person(Address.NULL) {
#Override
public boolean isNull() {
return true;
}
};
}
etc etc etc
Then your if statement can become:
if (!family.getPeople().get(0).getAddress().getPostalCode.isNull()) {...}
It's suboptimal since:
You're stuck making NULL objects for every class,
It's hard to make these objects generic, so you're stuck making a null-object version of each List, Map, etc that you want to use, and
There are potentially some funny issues with subclassing and which NULL to use.
But if you really hate your == nulls, this is a way out.
Although this post is almost five years old, I might have another solution to the age old question of how to handle NullPointerExceptions.
In a nutshell:
end: {
List<People> people = family.getPeople(); if(people == null || people.isEmpty()) break end;
People person = people.get(0); if(person == null) break end;
Address address = person.getAddress(); if(address == null) break end;
PostalCode postalCode = address.getPostalCode(); if(postalCode == null) break end;
System.out.println("Do stuff");
}
Since there is a lot of legacy code still in use, using Java 8 and Optional isn't always an option.
Whenever there are deeply nested classes involved (JAXB, SOAP, JSON, you name it...) and Law of Demeter isn't applied, you basically have to check everything and see if there are possible NPEs lurking around.
My proposed solution strives for readibility and shouldn't be used if there aren't at least 3 or more nested classes involved (when I say nested, I don't mean Nested classes in the formal context). Since code is read more than it is written, a quick glance to the left part of the code will make its meaning more clear than using deeply nested if-else statements.
If you need the else part, you can use this pattern:
boolean prematureEnd = true;
end: {
List<People> people = family.getPeople(); if(people == null || people.isEmpty()) break end;
People person = people.get(0); if(person == null) break end;
Address address = person.getAddress(); if(address == null) break end;
PostalCode postalCode = address.getPostalCode(); if(postalCode == null) break end;
System.out.println("Do stuff");
prematureEnd = false;
}
if(prematureEnd) {
System.out.println("The else part");
}
Certain IDEs will break this formatting, unless you instruct them not to (see this question).
Your conditionals must be inverted - you tell the code when it should break, not when it should continue.
One more thing - your code is still prone to breakage. You must use if(family.getPeople() != null && !family.getPeople().isEmpty()) as the first line in your code, otherwise an empty list will throw a NPE.
If you can use groovy for mapping it will clean up the syntax and codes looks cleaner. As Groovy co-exist with java you can leverage groovy for doing the mapping.
if(family != null) {
if(family.getPeople() != null) {
if(family.people.get(0) != null) {
if(people.get(0).getAddress() != null) {
if(people.get(0).getAddress().getPostalCode() != null) {
//FINALLY MADE IT TO DO SOMETHING!!!
}
}
}
}
}
instead you can do this
if(family?.people?[0]?.address?.postalCode) {
//do something
}
or if you need to map it to other object
somobject.zip = family?.people?[0]?.address?.postalCode
Not such a cool idea, but how about catching the exception:
try
{
PostalCode pc = people.get(0).getAddress().getPostalCode();
}
catch(NullPointerException ex)
{
System.out.println("Gotcha");
}
If it is rare you could ignore the null checks and rely on NullPointerException. "Rare" due to possible performance problem (depends, usually will fill in stack trace which can be expensive).
Other than that 1) a specific helper method that checks for null to clean up that code or 2) Make generic approach using reflection and a string like:
checkNonNull(family, "people[0].address.postalcode")
Implementation left as an exercise.
I was just looking for the same thing (my context: a bunch of automatically created JAXB classes, and somehow I have these long daisy-chains of .getFoo().getBar().... Invariably, once in a while one of the calls in the middle return null, causing NPE.
Something I started fiddling with a while back is based on reflection. I'm sure we can make this prettier and more efficient (caching the reflection, for one thing, and also defining "magic" methods such as ._all to automatically iterate on all the elements of a collection, if some method in the middle returns a collection). Not pretty, but perhaps somebody could tell us if there is already something better out there:
/**
* Using {#link java.lang.reflect.Method}, apply the given methods (in daisy-chain fashion)
* to the array of Objects x.
*
* <p>For example, imagine that you'd like to express:
*
* <pre><code>
* Fubar[] out = new Fubar[x.length];
* for (int i=0; {#code i<x.length}; i++) {
* out[i] = x[i].getFoo().getBar().getFubar();
* }
* </code></pre>
*
* Unfortunately, the correct code that checks for nulls at every level of the
* daisy-chain becomes a bit convoluted.
*
* <p>So instead, this method does it all (checks included) in one call:
* <pre><code>
* Fubar[] out = apply(new Fubar[0], x, "getFoo", "getBar", "getFubar");
* </code></pre>
*
* <p>The cost, of course, is that it uses Reflection, which is slower than
* direct calls to the methods.
* #param type the type of the expected result
* #param x the array of Objects
* #param methods the methods to apply
* #return
*/
#SuppressWarnings("unchecked")
public static <T> T[] apply(T[] type, Object[] x, String...methods) {
int n = x.length;
try {
for (String methodName : methods) {
Object[] out = new Object[n];
for (int i=0; i<n; i++) {
Object o = x[i];
if (o != null) {
Method method = o.getClass().getMethod(methodName);
Object sub = method.invoke(o);
out[i] = sub;
}
}
x = out;
}
T[] result = (T[])Array.newInstance(type.getClass().getComponentType(), n);
for (int i=0; i<n; i++) {
result[i] = (T)x[i];
}
return result;
} catch (NoSuchMethodException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
throw new RuntimeException(e);
}
}
and my favorite, the simple try/catch, to avoid nested null checks...
try {
if(order.getFulfillmentGroups().get(0).getAddress().getPostalCode() != null) {
// your code
}
} catch(NullPointerException|IndexOutOfBoundsException e) {}

Categories

Resources