Java Replace / Improve null check - java

I have a pseudo Java method where everything can be nullable:
private String prepareMessage(Scope scope) {
if (scope != null) {
if (scope.getPermission != null) {
if (scope.getInfo != null) {
return "Successful";
} else {
return "Missing field Info";
}
} else if (scope.getInfo() != null) {
return "Permission field not provided";
}
}
return "Permission and Info fields not provided";
}
How can I simplify this code to remove terrible looking null checks? Thanks !

You can create a helper method that suits you, an example:
public String notNullOrElse(Object o, String notNull, String isNull) {
return null != o ? notNull : isNull;
}
Then you can change:
if (scope.getInfo != null) {
return "Successful";
} else {
return "Missing field Info";
}
to:
return notNullOrElse(scope.getInfo(), "Successfull", "Missing field Info");
However, sometimes those horrible null checks are unfortunately necessary.

Tried refactoring the code. In most cases you can simplify If - else by re ordering the code flow. This makes getting code coverage easy.
private String prepareMessage(Scope scope) {
if (scope == null) {
return "Permission and Info fields not provided";
}
if (scope.getPermission != null && scope.getInfo != null) {
return "Successful";
} else {
return scope.getPermission == null ? "Permission field not provided" : "Missing field Info";
}
}
This doc beautifully explains code smells in if-else ->
https://dzone.com/articles/code-smells-if-statements

Java 1.7 introduces the class java.util.Objects (this link is from the Java 11 JavaDoc, but that should not matter here).
That class provides the methods Objects.isNull() and Objects.nonNull() that can be used as follows in your code:
import static java.util.Objects.*;
…
private String prepareMessage(Scope scope) {
if (nonNull (scope)) {
if (nonNull (scope.getPermission())) {
if (nonNull (scope.getInfo())) {
return "Successful";
} else {
return "Missing field Info";
}
} else if (nonNull (scope.getInfo()) {
return "Permission field not provided";
}
}
return "Permission and Info fields not provided";
}
Whether this looks better or not is a matter of taste, of course.
Alternative logic may look like this (for Java 11):
import static java.util.Objects.*;
…
private String prepareMessage( Scope scope )
{
var messages = { "Successful", "Missing field Info", "Permission field not provided", "Permission and Info field not provided" };
var index = 0;
var retValue = messages [3]; // No scope at all
if( nonNull( scope ) )
{
if( isNull( scope.getPermission() ) ) index += 2;
if( isNull( scope.getInfo() ) ) index += 1;
retValue = messages [index];
}
return retValue;
}
I do not want to say that this is really better in any way, it is just different. And it spares one null check …

Related

void can not converted to Unit when use kotlin in java code - android

I am working with kotlin and java together in my project, I have a class kotlin like bellow:
class AuthenticationPresenter #Inject constructor(
private val navigator: AuthenticationNavigator,
private val getCurrentServerInteractor: GetCurrentServerInteractor,
private val getAccountInteractor: GetAccountInteractor,
private val settingsRepository: SettingsRepository,
private val localRepository: LocalRepository,
private val tokenRepository: TokenRepository
) {
suspend fun loadCredentials(newServer: Boolean, callback: (authenticated: Boolean) -> Unit) {
val currentServer = getCurrentServerInteractor.get()
val serverToken = currentServer?.let { tokenRepository.get(currentServer) }
val settings = currentServer?.let { settingsRepository.get(currentServer) }
val account = currentServer?.let { getAccountInteractor.get(currentServer) }
account?.let {
localRepository.save(LocalRepository.CURRENT_USERNAME_KEY, account.userName)
}
if (newServer || currentServer == null || serverToken == null || settings == null || account?.userName == null) {
callback(false)
} else {
callback(true)
navigator.toChatList()
}
}
}
I am converting bellow code (kotlin) to java:
presenter.loadCredentials(newServer || deepLinkInfo != null) { authenticated ->
if (!authenticated) {
showServerInput(deepLinkInfo)
}
}
And this is my convert code to java but get me error:
presenter.loadCredentials((newServer || deepLinkInfo != null), authenticated ->{
if (!authenticated) {
showServerInput(deepLinkInfo);
}
});
But say me: Missing return statement
What can I use from this loadCredentials in java code?
Code of showServerInput:
fun showServerInput(deepLinkInfo: LoginDeepLinkInfo?) {
addFragment(TAG_SERVER_FRAGMENT, R.id.fragment_container, allowStateLoss = true) {
ServerFragment.newInstance(deepLinkInfo)
}
}
All the previous answers fail to include the part where you need to return an instance of Unit, once I did that I was able to get a similar issue fixed.
There is a slight issue with the original question in that "AA" cannot be returned and so would throw an error and instead you'd need to call a method.
Here's how to do it in the context of this question.
presenter.loadCredentials((newServer || deepLinkInfo != null), authenticated ->{
if (!authenticated) {
showServerInput(deepLinkInfo); // Here!
} else {
myOtherMethod();
}
return Unit.INSTANCE;
});
You need to return the result of showServerInput:
presenter.loadCredentials((newServer || deepLinkInfo != null), authenticated ->{
if (!authenticated) {
return showServerInput(deepLinkInfo); // Here!
} else {
return "AA";
}
});
Try this
presenter.loadCredentials((newServer || deepLinkInfo != null), authenticated ->{
if (!authenticated) {
showServerInput(deepLinkInfo);
}
});

How to update the Hibernate Entity Record when only few fields of entity obj are modified and remaining fields should not be null

is there any other different solution for this code.
for every pojo class we have to check that modified data coming from browser and we will store only modified data into the database.
see below billingTax obj is coming from browser which is updated data
and billingtaxDbObject obj is retrieved from database and we will check with if condition whether updated data is changed or not
if pojo class has 20 fields, we have to write 20 if conditions
if pojo class has 5 fields, we have to write 5 if conditions
instead of writing if conditions for checking wheter data is modified or nor is there any other simplest way?
#Override
public BillingTax update(BillingTax billingTax) throws DataInsufficientException, RecordNotFoundException {
log.debug("BillingTaxServiceImpl.update()....................");
try {
if (billingTax == null)
throw new DataInsufficientException("billingTax object is null");
BillingTax billingtaxDbObject = get(billingTax.getId());
if (billingtaxDbObject == null)
throw new RecordNotFoundException("billingTax object is not found in database");
if (billingTax.getTaxApplyType() != null
&& !billingTax.getTaxApplyType().equals(billingtaxDbObject.getTaxApplyType()))
billingtaxDbObject.setTaxApplyType(billingTax.getTaxApplyType());
if (billingTax.getCode() != null && !billingTax.getCode().trim().equalsIgnoreCase("null")
&& !billingTax.getCode().equalsIgnoreCase(billingtaxDbObject.getCode()))
billingtaxDbObject.setCode(billingTax.getCode());
if (billingTax.getName() != null && !billingTax.getName().trim().equalsIgnoreCase("null")
&& !billingTax.getName().equalsIgnoreCase(billingtaxDbObject.getName()))
billingtaxDbObject.setName(billingTax.getName());
if (billingTax.getDescription() != null && !billingTax.getDescription().trim().equalsIgnoreCase("null")
&& !billingTax.getDescription().equalsIgnoreCase(billingtaxDbObject.getDescription()))
billingtaxDbObject.setDescription(billingTax.getDescription());
if (billingTax.getServiceTypeForTax() != null
&& !billingTax.getServiceTypeForTax().equals(billingtaxDbObject.getServiceTypeForTax()))
billingtaxDbObject.setServiceTypeForTax(billingTax.getServiceTypeForTax());
if (billingTax.getTaxValue() != null && !billingTax.getTaxValue().equals("null")
&& !billingTax.getTaxValue().equals(billingtaxDbObject.getTaxValue()))
billingtaxDbObject.setTaxValue(billingTax.getTaxValue());
if (billingTax.getStatus() != null && !billingTax.getStatus().equals(billingtaxDbObject.getStatus()))
billingtaxDbObject.setStatus(billingTax.getStatus());
if (billingTax.getOrderNo() != null && !billingTax.getOrderNo().equals("null")
&& !billingTax.getOrderNo().equals(billingtaxDbObject.getOrderNo()))
billingtaxDbObject.setOrderNo(billingTax.getOrderNo());
if (billingTax.getId() != null && !billingTax.getId().trim().equalsIgnoreCase(billingtaxDbObject.getId())
&& !billingTax.getId().equalsIgnoreCase(billingtaxDbObject.getId()))
billingtaxDbObject.setId(billingTax.getId());
if (billingTax.getStartDate()!= null && !billingTax.getStartDate().equals(billingtaxDbObject.getStartDate()))
billingtaxDbObject.setStartDate(billingTax.getStartDate());
if (billingTax.getEndDate()!= null && !billingTax.getEndDate().equals(billingtaxDbObject.getEndDate()))
billingtaxDbObject.setEndDate(billingTax.getEndDate());
billingtaxDbObject.setUpdatedDate(new Date());
return billingTaxDAO.update(billingtaxDbObject);
} catch (Exception e) {
log.error("BillingTaxServiceImpl.update()....................exception:" + e.getMessage());
throw e;
}
}
You can do it with Dynamic updates for hibernate if you can avoid check changes among dto and entity and update all fields that come from web. If you need check dto from web and entity you can use apache bean util to find all changed values (or use spring util if you have or reflection from java...) and update it with dynamic updates.
see : BeanUtils
BeanUtils.copyProperties() // there are 3 methods.
check how it works in source code .
Create your own util method , similar to BeanUtils.copyProperties() , but with logic that you need (not null and not equal with source-entity value ).
Also use method from BeanUtils , to get PropertyDescriptor :
public static PropertyDescriptor[] getPropertyDescriptors(Class clazz)
throws BeansException
iterate over array of PropertyDescriptor and do check that you need (set value into source with ReflectionUtils).
with this approach you populate only properties that are not null and changed( if you need it) into billingtaxDbObject and update it.
You can put your copy / merge method into some util class and reuse it for all place where you need copy from dto into entity with some checks.
this is developed by getting all the fields/properties from the pojo class and checking with wheter null data or modified data.
below is the code:
copyProperties(billingTax, billingtaxDbObject);
public void copyProperties(BillingTax source, BillingTax dest) throws Exception{
if (source == null)
throw new DataInsufficientException("billingTax object is null");
if (dest == null)
throw new RecordNotFoundException("billingtaxDbObject object is not found in database");
try{
for (Field field : source.getClass().getDeclaredFields()) {
field.setAccessible(true);
Object sourceValue = field.get(source);
Object destValue=field.get(dest);
if(sourceValue!=null && sourceValue!="" && sourceValue!="null"){
if(sourceValue instanceof String){
if(!sourceValue.toString().trim().equalsIgnoreCase("null")){
if(!sourceValue.toString().equalsIgnoreCase(destValue.toString())){
field.set(dest, sourceValue);
System.err.println(field.getName()+" is modified:"+field.get(dest));
}
}
}
else{
if(!sourceValue.equals("null") && !sourceValue.equals(destValue)){
field.set(dest, sourceValue);
System.err.println(field.getName()+" is modified:"+field.get(dest));
}
}
}
}
System.out.println();
}catch (Exception e) {
throw e;
}
}
public class CopyConverter<T> {
private List<String> errorMessages = new ArrayList<>();
private int countSuccess = 0;
public CopyConverter<T> convert(T source, T target, Set<String> ignoreFields){
copyProperties(source,target,ignoreFields);
return this;
}
public boolean hasError(){
return errorMessages.isEmpty();
}
public List<String> getErrorMessages(){
return errorMessages;
}
private boolean copyProperties(T source ,T target , Set<String> ignoreFields) {
Objects.requireNonNull(source , "..error message...");
Objects.requireNonNull(target , "..error message...");
try {
Map<String, Field> fieldNameMapping = buildFiledMap(target.getClass().
getDeclaredFields());
ignoreFields = (ignoreFields == null ? new HashSet<>() : ignoreFields);
for (Map.Entry<String, Field> fieldEntry : fieldNameMapping.entrySet()) {
if (ignoreFields.contains(fieldEntry.getKey())) {
continue;
}
Field field = fieldEntry.getValue();
field.setAccessible(true);
Object sourceValue = field.get(source);
Object targetValue = field.get(source);
if (isChangedAsString(sourceValue, targetValue)) {
field.set(target, sourceValue);
continue;
}
if (isChangedAsObject(sourceValue, targetValue)) {
field.set(target, sourceValue);
}
countSuccess++;
}
} catch (Exception e) {
errorMessages.add(".......");
log.info(....);
}
return countSuccess == 0;
}
private Map<String, Field> buildFiledMap(Field[] fields) {
Map<String, Field> fieldMap = new HashMap<>(fields.length);
//Stream.of(fields).collect(Collectors.toMap())
for (Field field : fields) {
fieldMap.put(field.getName(), field);
}
return fieldMap;
}
private boolean isChangedAsObject(Object obj1, Object obj2) {
return (obj1 == null && obj2 != null) || (obj1 != null && !obj1.equals(obj1));
}
private boolean isChangedAsString(Object obj1, Object obj2) {
if (obj1 instanceof String && obj2 instanceof String) {
String value1 = (String) obj1;
String value2 = (String) obj2;
return value1 != null &&
!value1.trim().equalsIgnoreCase("null") &&//strange check
!value1.equalsIgnoreCase(value2);
}
return false;
}
}

Multiple Null checks handling in java8

Instead of multiple null checks in below case, I am planning to add something readable code instead. May be with the help of java 8 streams/maps. Can somebody help me with this
private String getRailsServiceClass(IRailsComponent railsComponent) {
String serviceClass = "";
if (railsComponent != null && railsComponent.getRailOffer() != null && railsComponent.getRailOffer().getRailProducts().get(0).getRailProduct() != null && railsComponent.getRailOffer().getRailProducts().get(0).getRailProduct().getFareBreakdownList() != null &&
railsComponent.getRailOffer().getRailProducts().get(0).getRailProduct().getFareBreakdownList().get(0).getPassengerFareList() != null && railsComponent.getRailOffer().getRailProducts().get(0).getRailProduct().getFareBreakdownList().get(0).getPassengerFareList().get(0).getPassengerSegmentFareList() != null &&
railsComponent.getRailOffer().getRailProducts().get(0).getRailProduct().getFareBreakdownList().get(0).getPassengerFareList().get(0).getPassengerSegmentFareList().get(0).getCarrierServiceClassDisplayName() != null) {
return railsComponent.getRailOffer().getRailProducts().get(0).getRailProduct().getFareBreakdownList().get(0).getPassengerFareList().get(0).getPassengerSegmentFareList().get(0).getCarrierServiceClassDisplayName();
}
return serviceClass;
}
You can use Optional for your purpose.
String serviceClass = Optional.ofNullable(railsComponent)
.map(IRailsComponent::getRailOffer)
.map(RailOffer::getRailProducts)
...
.orElse("");
Your code is bad because on each check you had to get the items in the lists again and again. That's a lot of I/O to do.
Without using any API (so pre-Java 8 solution) You can clean you code by checking each item one after all (depends on the accessiblity of each class but here is a fully developped condition
RailComponent rc = getRailComponent();
if (rc != null) {
RailOffer ro = rc.getRailOffer()
if (ro != null) {
RailProduct rp = ro.getRailProducts().get(0).getRailProduct();
if (rp != null) {
List<FareBreakDown> fbList = rp.getFareBreakdownList();
if (fbList != null) {
List<PassengerFare> pfList = fb.get(0).getPassengerFareList();
if (pfList != null) {
List<PassengerSegmentFare> psfList = pfList.get(0).getPassengerSegmentFareList();
if (psfList != null) {
String carrierServiceClassDisplayName = psfList.get(0).getCarrierServiceClassDisplayName();
if (carrierServiceClassDisplayName != null) {
return carrierServiceClassDisplayName;
}
}
}
}
}
}
}
You see that's not THAT much of check once you reduce the verbosity of your code
inspired by kotlin safe call operator ?. & elivs opreator ?:, you can chain a custom SafeCallable. for example:
String serviceClass = SafeCallable.of(railsComponent)
.then(IRailsComponent::getRailOffer)
.then(RailOffer::getRailProducts)
.then(products -> products.get(0))
.then(...)
.orElse("");
SafeCallable
interface SafeCallable<T> {
T call();
static <T> SafeCallable<T> of(T value) {
return () -> value;
}
// ?. operator
default <R> SafeCallable<R> then(Function<T, R> step) {
return then(step, () -> null);
}
// ?: operator
default T orElse(T value) {
return then(identity(), () -> value).call();
}
default <R> SafeCallable<R> then(Function<T, R> step, Supplier<R> otherwise) {
T value = call();
return value == null ? otherwise::get : () -> step.apply(value);
}
}
If any of those nulls are rare, i would use a try catch block:
private String getRailsServiceClass(IRailsComponent railsComponent) {
try {
return railsComponent.getRailOffer().getRailProducts().get(0)
.getRailProduct().getFareBreakdownList().get(0).getPassengerFareList().get(0)
.getPassengerSegmentFareList().get(0).getCarrierServiceClassDisplayName();
} catch (NullPointerException e) {
return "";
}
}

Code Refactoring Extract To a Method

Friends
I have below two overloaded methods which throw same ServiceException
private ModResponse updateNDelTerms(GlobalTermDeleteType item, boolean isGlobal)
{
StdTerm stdTerm = getTerm(item.getstdTermId());
if (stdTerm == null || !getBuilder().getOwnerId().equals(stdTerm.getOwnerId()))
{
throw new ServiceException(GLOBAL_TERM_TO_DELETE_DOES_NOT_EXIST_MSG,
CANNOT_DELETE_GLOBAL_TERM, GLOBAL_TERM_DOES_NOT_EXIST);
}
if (stdTerm.isGlobal() && !isGlobal)
{
throw new ServiceException(
"Global Term can not be updated: incorrect URL.",
CANNOT_UPDATE_GLOBAL_TERM, INCORRECT_URL);
}
if (stdTerm.isLocked() != null && stdTerm.isLocked())
{
throw new ServiceException("Global Term can not be updated: stdTerm is locked.",
CANNOT_UPDATE_GLOBAL_TERM, TERM_LOCKED);
}
return updateNDel(item, stdTerm);
}
Second method is
public ItemResponse<List<stdTermItemType>> copyTerm(
BigInteger stdTermId, boolean isGlobal,
boolean isFalse)
{
StdTerm stdTerm = getTerm(stdTermId);
if (stdTerm == null || !getBuilder().getOwnerId().equals(stdTerm.getOwnerId()))
{
throw new ServiceException(GLOBAL_TERM_TO_DELETE_DOES_NOT_EXIST_MSG,
CANNOT_DELETE_GLOBAL_TERM, GLOBAL_TERM_DOES_NOT_EXIST);
}
if (stdTerm.isGlobal() && !isGlobal)
{
throw new ServiceException(
"Global Term can not be updated: incorrect URL.",
CANNOT_COPY_GLOBAL_TERM, INCORRECT_URL);
}
if (stdTerm.isLocked() != null && stdTerm.isLocked())
{
throw new ServiceException("Rate sheet term can not be updated: stdTerm is locked.",
CANNOT_COPY_GLOBAL_TERM, TERM_LOCKED);
}
return copyGlobleTerm(stdTerm, pasteTermObj, isFalse);
}
I am thinking of refactoring these two methods and use Extract common code to a method ,
However due to difference in CANNOT_COPY_GLOBAL_TERM and CANNOT_UPDATE_GLOBAL_TERM which are unique to both the methods hence
Im not able to achieve Extract to a Method refactoring .
Please suggest .
private StdTerm retrieveStdTerm(BigInteger stdTermId, boolean isGlobal, String errorTerm)
{
StdTerm stdTerm = getTerm(BigInteger stdTermId);
if (stdTerm == null || !getBuilder().getOwnerId().equals(stdTerm.getOwnerId()))
{
throw new ServiceException(GLOBAL_TERM_TO_DELETE_DOES_NOT_EXIST_MSG,
CANNOT_DELETE_GLOBAL_TERM, GLOBAL_TERM_DOES_NOT_EXIST);
}
if (stdTerm.isGlobal() && !isGlobal)
{
throw new ServiceException(
"Global Term can not be updated: incorrect URL.",
errorTerm, INCORRECT_URL);
}
if (stdTerm.isLocked() != null && stdTerm.isLocked())
{
throw new ServiceException("Global Term can not be updated: stdTerm is locked.",
errorTerm, TERM_LOCKED);
}
return stdTerm;
}
private ModResponse updateNDelTerms(GlobalTermDeleteType item, boolean isGlobal)
{
StdTerm stdTerm = retrieveStdTerm(item.getstdTermId(), isGlobal,
CANNOT_DELETE_GLOBAL_TERM);
return updateNDel(item, stdTerm);
}
public ItemResponse<List<stdTermItemType>> copyTerm(BigInteger stdTermId, boolean isGlobal,
boolean isFalse)
{
StdTerm stdTerm = retrieveStdTerm(stdTermId, isGlobal, CANNOT_COPY_GLOBAL_TERM);
return copyGlobleTerm(stdTerm, pasteTermObj, isFalse);
}
Pass in the things that are different into the extracted method.
You could also turn those methods into lambdas and pass them in as well if you're running on JDK 8. Use a more functional style.

New user held with searching array

I am trying to search an array and if the two Strings are matched then it will return true otherwise false, firstly i want to search to see if the account is already there if so then search Code if the two exsis then return true
public boolean searchArray(String account, String code) {
for (Accounts a : bAccounts) {
if (a.getAccount().equals(account)) {
for (Accounts c : bAccounts) {
if (c.getCode().equals(Code))
return true;
}
}
}
return false;
}
Think I've got a little lost within this search method, can anyone please help me on this, thanks. This all compiles fine but doesn't seem to return anything. I have get methods in my Accounts class which has get and set methods for Account and Sort.
public boolean searchArray(String account, String code) {
for (Accounts a : bAccounts) {
if (a.getAccount().equals(account)
&& a.getCode().equals(code)) {
return true;
}
}
return false;
}
Inner for should be removed.
You didn't mention if you'll accept nulls for account and code parameters.
If null values are possible/desirable to compare, this is what I suggest:
public boolean searchArray(String account, String code) {
for (Account a : accounts) {
if (account == null) {
if (code == null) {
if ((a.getAccount() == null) && (a.getCode() == null)) {
return true;
}
} else {
if ((a.getAccount() == null) && code.equals(a.getCode())) {
return true;
}
}
} else {
if (code == null) {
if (account.equals(a.getAccount()) && (a.getCode() == null)) {
return true;
}
} else {
if (account.equals(a.getAccount()) && code.equals(a.getCode())) {
return true;
}
}
}
}
return false;
}
If you won't consider nulls for account and code parameters, I suggest this:
public boolean searchArray(String account, String code) {
// if you won't consider nulls then there's no need to search
// when at least one of them is null
if ((account == null) || (code == null)) {
return false;
}
for (Account a : accounts) {
if (account.equals(a.getAccount()) && code.equals(a.getCode())) {
return true;
}
}
return false;
}
Hope it helps you

Categories