I have a lot of this kind of code in my project:
if (entityRepository.saveEntity(new RemoteEntityBuilder()
.appId(appId)
.nameSpace(nameSpace)
.entityType(entityType)
.entityId(entityId)
.blobs(Lists.list(new RemoteBlobBuilder()
.blobName(blobName)
.blobStream(new SimpleRemoteInputStream(inputStream))
.build()))
.build()) != null) {
// Meaning entity was saved
} else {
// Meaning entity was not saved
}
The saveEntity method returns either NULL (if operation failed) or the object/entity that was saved if the operation was successful. My question is, is there a better way to represent this code with the use of != null for instance:
if(entityRepository.saveEntity(...)) {
}
Or something else.
UPDATE:
The saveEntity method is this
#Override public RemoteEntity saveEntity(RemoteEntity entity)
throws NotBoundException, RemoteException {
RemoteEntities remoteEntities = saveEntities(new RemoteEntity[] {entity});
return remoteEntities != null ? remoteEntities.entities().stream().findFirst().get() : null;
}
Here's how it looks now thanks to YCF_L:
entityRepository.saveEntity(new RemoteEntityBuilder()
.appId(appId)
.nameSpace(nameSpace)
.entityType(entityType)
.entityId(entityId)
.blobs(Lists.list(new RemoteBlobBuilder()
.blobName(blobName)
.blobStream(new SimpleRemoteInputStream(inputStream))
.build()))
.build()).ifPresentOrElse(remoteEntity -> {
pubSubService.updated(remoteEntity.appId(), remoteEntity.nameSpace(),
remoteEntity.entityType(), remoteEntity.entityId());
setStatus(Status.SUCCESS_CREATED);
}, () -> {
setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
});
Here's how the code looks in the IDE (looks pretty clean to me):
I would use Optional in your case :
public Optional<RemoteEntity> saveEntity(RemoteEntity entity) throws NotBoundException, RemoteException {
RemoteEntities remoteEntities = saveEntities(new RemoteEntity[]{entity});
return remoteEntities.entities().stream()
.findFirst();
}
and then :
if(entityRepository.saveEntity(...).isPresent()) {
...
}
In fact you have many choices with Optional, you can use ifPresent also :
entityRepository.saveEntity(...)
.ifPresent(r -> ..)
Or throw an exception:
entityRepository.saveEntity(...)
.orElseThrow(() -> ..)
What is "better" may be a matter of opinion.
Given your example, the way to achieve that would be to create another method that calls saveEntity() and returns true or false. (I do wonder why saveEntity() doesn't throw an exception if its operations fails -- that would be more normal in my experience.)
If you simply don't like that the comparison is hard to spot, you might reverse the order:
if (null != entityRepository.saveEntity(...))
I would probably move the call outside of the if entirely, as I find side effects in conditionals potentially confusing.
RemoteEntity myEntity = entityRepository.saveEntity(...)
if (myEntity != null) ...
Related
How can I handle null checks in the below code using Java 8 when my counterparty can be null.
I want to set counterParty only if it has a value and not set if it is empty.
public static Iterable<? extends Trade> buildTrade (final List<Trade> trade) {
return () -> trade.stream()
.map(trade -> Trade.newBuilder()
.setType(trade.type())
.setUnit(trade.unit())
.setCounterParty(trade.counterParty())
.build())
.iterator();
}
You can use the following code:
trade.stream()
.map(trade -> {
TradeBuilder tb = Trade.newBuilder()
.setType(trade.type())
.setUnit(trade.unit());
Optional.ofNullable(trade.counterParty())
.ifPresent(tb::setCounterParty);
return tb.build();
})
.iterator();
Or without Optional:
trade.stream()
.map(trade -> {
TradeBuilder tb = Trade.newBuilder()
.setType(trade.type())
.setUnit(trade.unit());
if(trade.counterParty() != null) tb.setCounterParty(trade.counterParty());
return tb.build();
})
.iterator();
The stream aspect of this has no relevance to the question; let's strip it out:
trade -> Trade.newBuilder()
.setType(trade.type())
.setUnit(trade.unit())
.setCounterParty(trade.counterParty())
.build()
You're asking to not set counterParty if it is null.
A really easy way to do this would be to modify builder class's setCounterParty() to do nothing and return, if the parameter is null.
TradeBuilder setCounterParty(CounterParty cp) {
if(cp != null) {
this.counterParty = cp;
}
return this;
}
You do need to ensure that this behaviour is consistent with other callers' needs.
If your builder is being dynamically generated by some framework (Lombok etc), you might not have code in which you can easily make this change -- but most such frameworks have mechanisms that allow you to take control of that kind of thing.
If you can't modify the builder, you can break up the calls to it, and surround
one call with an if:
trade -> {
TradeBuilder b = Trade.newBuilder()
.setType(trade.type())
.setUnit(trade.unit());
if(trade.counterParty() != null) {
b.setCounterParty(trade.counterParty());
}
return b.build()
}
I need specific data for a report, then I gettin all information from a parent object
Object1
It has many attributes, object attributes
Object11, Object12, Object13, attr1, attr2...
The attributes has many attributes too
Object111, Object131, Object132,..
by now I got 5 level data attributes.
When I send information to my report it says, Error: cause:null
object1.getIdObject11().getIdObject111().getDescription;
It trows error because Object111 is null
I tried using
object1.getIdObject11().getIdObject111().getDescription==null?'':object1.getIdObject11().getIdObject111().getDescription;
but it only verify if description is null, and throws the same error
Then I tried to verify Object
if(object1.getIdObject11().getIdObject111() == null) {
var = object1.getIdObject11().getIdObject111().getDescription;
} else {
var = "";
}
But when Object11 is null, it throws same error.
I don't think its a good way doing this for each attribute (have to get like 30 attributes)
if(object1.getIdObject11()!=null) {
if(object1.getIdObject11().getIdObject111()!=null) {
if(object1.getIdObject11().getIdObject111().getIdObject1111()!=null) {
//...
}
}
}
I want to verify if is there a null object and set '' (blank) if it is, with no such a large code(because the gotten params are set inside a report, mixed with letter).
reportline1 = "Area: "+object1.getIdObject11().getIdObject111().getName;
You code breaks Demeter's law. That's why it's better to refactor the design itself.
As a workaround, you can use Optional
var = Optional.ofNullable(object1)
.map(o -> o.getIdObject11())
.map(o -> o.getIdObject111())
.map(o -> o.getDescription())
.orElse("")
The way I would probably do this to extend the functionality of the code easily in the future might take a bit of writing in the beginning but will be easily usable forever.
I would create a new method in your parent class called hasNull that returns a boolean like so:
public boolean hasNull()
{
boolean hasANull = false;
//Call another hasNull() inside of object11 which in turns calls hasNull() in object111 etc.
//If any of the calls return with a true/null value set hasANull to true
return hasANull;
}
This in turn checks to see if the current objects it contains are null. If one of the class variables is another custom class you created you can then add another hasNull into that one and keep going until you get to the lowest level where you can do a specific operation when the value is null such as set it to "".
After implementing this you will be able to just be able to use it like this any time you need it:
if (!object1.hasNull())
{
//Do whatever you want if there are no null values
}
else
{
//Do whatever you want if there is a null value
}
You can also make this a void method if you only want it to toggle the values on the lowest level, and do not need to do anything in either case.
I prefer the solution that gave dehasi.
But you can also do something like that:
getOrElse(() -> object1.getIdObject11().getIdObject111().getDescription(), "")
Where getOrElse is:
public static <T> T getOrElse(Supplier<T> getter, T elseValue) {
try {
return getter.get();
} catch (Exception e) {
// log or do something with it
}
return elseValue;
}
It may be controversial becaouse you use Exception to do this.
You can use this code to check if your object has a null attribute, the object is myclass;
for (Field f : myclass.getClass().getDeclaredFields()) {
f.setAccessible(true);
try {
if (Objects.isNull(f.get(myclass))) {
isLineContainsNull = true;
}
} catch (Exception e) {
log.error(e.getMessage());
}
}
Let's suppose we have an if statement like this:
public A save(A a) {
if (isValid.test(a)) {
return aRepository.save(a);
}
throw new ANotValidException("A is not valid");
}
isValid is a Predicate and it may look like:
private Predicate<A> isValid = (a) -> (a != null);
What do you think? Can I make it cleaner somehow?
I mean, for example using an Optional to reduce it in 1 line with an .orElseThrow();
A more precise version using Optional and throwing a custom Exception shall be :
public A save(A a) throws ANotValidException { // throws the custom exception
return Optional.ofNullable(a) // since your predicate is to check for not null
.map(aRepository::save)
.orElseThrow(() -> new ANotValidException(a + "A is not valid"));
}
An Optional can make the code more readable, particularly around the use of your predicate object:
public A save(A a) {
return Optional.ofNullable(a)
.filter(isValid)
.map(aRepository::save)
.orElseThrow(() -> new ANotValidException("A is not valid"));
}
You can also get rid of the predicate altogether as it's simple enough to use Objects::nonNull (unless your real predicate's test is more complex). And in that case, keeping your current condition checks would probably make more sense (in my opinion).
One could argue that it would be more natural to read it in the opposite order, that is first handle the validation and the result of it and then move on to saving the object.
public A save(A a) {
if (!isValid.test(a)) {
throw new ANotValidException("A is not valid");
}
return aRepository.save(a);
}
I have not doubt that there is a solution posted for this, but I can't find the search term retrieve it, so if it does exist please point me to the duplicate and mark this as such.
I have a chain of methods performing various validation checks on a button click event, I display a message if the validation has failed, currently my solution is to then pass back a boolean so that if the method failed the remaining methods will not run.
I don't like this, when I have several methods all passing back booleans my code starts to smell.
is there a better solution to this? (I'd don't want to use a instance variable)
Example of the code as it currently stands:
private void SUBMIT_BUTTON_CLICK(){
if(validate()){
//Do Stuff
}
}
private boolean validate(){
return checkOne() && checkTow() && checkThree() && checkFour();
}
private boolean checkOne(){
if (someCheckFails) {
print(warning);
return false;
} else {
return true;
}
}
private boolean checkTow(){
if (someCheckFails) {
print(warning);
return false;
} else {
return true;
}
}
private boolean checkThree(){
if (someCheckFails) {
print(warning);
return false;
} else {
return true;
}
}
private boolean checkFour(){
if (someCheckFails) {
print(warning);
return false;
} else {
return true;
}
}
Convenionally you would use exceptions:
void check1(Foo value) {
if(some test on value) {
throw new ValidationException(...);
}
}
try {
check1(value);
check2(value);
} catch (ValidationException e) {
// deal with validation failure
}
A bonus here is that the exception can carry information about the failure. Your boolean false just says "it failed", with no explanation.
Another bonus, of course, is that you're free to pass the exception higher up the call stack, where some other code can deal with it.
Some people worry about the cost of building exceptions (or more accurately, collecting that stack trace contained within). I'd advise not worrying about it unless you get performance problems and profiling points the finger at exceptions.
There are alternatives though. For example your validation could return Optional<ValidationError>:
Optional<ValidationError> check1(Foo value) {
if(some test on value) {
return Optional.of(new ValidationError(...));
} else {
return Optional.empty();
}
}
Then...
Optional<ValidationError> validationResult =
check1(value)
.orElseGet( () -> check2(value))
.orElseGet( () -> check3(value));
You could, of course, loop through a list of validators, rather than hard-code like this.
Some of the functional programming libraries (e.g. vavr) include an Either class, which can be used in a similar way, where instead of being either an error or empty(), it's an error or a success value.
Or you could stick with methods returning boolean, but use them as Predicates:
List<Predicate<Foo>> checks = Arrays.asList(
f -> check1(f),
f -> check2(f),
f -> check3(f)
);
(Or the equivalent with method references e.g. this::check1)
checks.stream().allMatch(check -> check.test(value));
As you can see, there are tons of possibilities. But think about whether you're over-complicating. There's mostly nothing inherently wrong with the simple approach you already have -- although it is better, and more testable, to return a failure reason, rather than print it as a side-effect.
Chaining like you are currently doing is generally the best solution. It is easy to understand, efficient and (relatively) concise.
A couple of other ideas would be:
build an array of predicates and then iterate and call them, or
use exceptions and exception handling
but both of these have performance implications, and they will only give "cleaner" code if you have a vast number of predicates to evaluate.
Sometimes an inelegant solution is more elegant than looking for a clever solution.
Consider this: if I use exceptions, I can rewrite the validate() method
private boolean validate(){
return checkOne() && checkTow() && checkThree() && checkFour();
}
as
private void validate() throws ValidationException {
checkOne(); checkTow(); checkThree(); checkFour();
}
But how much have I actually gained here? It is still two lines of code. And if I were to follow Java's style rules it would be:
private void validate() throws ValidationException {
checkOne();
checkTow();
checkThree();
checkFour();
}
which is more lines than we started with. And we haven't considered the predicates themselves or the code that handles the validation exception.
Based on my comment: you're probably after exceptions.
Example (pseudo code):
void checkOne() {
if( check_fails ) {
throw new CheckOneException();
}
}
void checkTwo() {
if( check_fails ) {
throw new CheckTwoException();
}
}
void validate() {
checkOne();
checkTwo();
}
void SUBMIT_BUTTON_CLICK() {
try {
validate();
//Do Stuff
} catch( CheckOneException | CheckTwoException ) {
//handle the exceptions
}
}
Note that you might have to either declare the exceptions to be thrown or make them runtime exceptions.
Additionally you might want to use multiple catch-blocks if the handling depends on the type of exception. Alternatively you could also throw the same type of exception if that fits your needs.
I have an assignment in which I need to convert the following pre-Java 8 code to Java 8 code. Below is just one method which is giving me hard time to finish up:
public static List<VehicleMake> loadMatching(Region region, String nameStartsWith, VehicleLoader loader) {
if ((nameStartsWith == null) || (region == null) || (loader == null)) {
throw new IllegalArgumentException("The VehicleLoader and both region and nameStartsWith are required when loading VehicleMake matches");
}
List<VehicleMake> regionMakes = loader.getVehicleMakesByRegion(region.name());
if (regionMakes == null) {
return null;
}
List<VehicleMake> matches = new ArrayList<>(regionMakes.size());
for (VehicleMake make : regionMakes) {
if ((make.getName() == null) || !make.getName().startsWith(nameStartsWith)) {
continue;
}
matches.add(make);
}
return matches;
}
I want to remove the null checks by using Optional<T> without modifying previously created classes and interfaces.
I tried to begin by changing the method return type and doing the following but compiler is throwing this error:
Bad return type in method reference since the VehicleMake class doesn't have optional instance fields.
Following is my code attempt:
public static Optional<List<VehicleMake>> loadMatchingJava8(Region region, String nameStartsWith, VehicleLoader loader) {
Optional<List<VehicleMake>> regionMakes = Optional.ofNullable(loader).ifPresent(loader.getVehicleMakesByRegion(Optional.ofNullable(region).ifPresent(region.name())));
/*
TODO rest of the conversion
*/
}
EDIT: Removed the flatMap and corrected code by not passing argument to method reference. But now it is not letting me pass region.name() to getVehicleMakesByRegion()
EDIT: Pass in consumer to ifPresent():
Optional<List<VehicleMake>> regionMakes = Optional.ofNullable(loader).ifPresent(()-> loader.getVehicleMakesByRegion(Optional.ofNullable(region).ifPresent(()->region.name()));
You may replace your initial null checks with
Optional.ofNullable(nameStartsWith)
.flatMap(x -> Optional.ofNullable(region))
.flatMap(x -> Optional.ofNullable(loader))
.orElseThrow(() -> new IllegalArgumentException(
"The VehicleLoader and both region and nameStartsWith"
+ " are required when loading VehicleMake matches"));
but it’s an abuse of that API. Even worse, it wastes resource for the questionable goal of providing a rather meaningless exception in the error case.
Compare with
Objects.requireNonNull(region, "region is null");
Objects.requireNonNull(nameStartsWith, "nameStartsWith is null");
Objects.requireNonNull(loader, "loader is null");
which is concise and will throw an exception with a precise message in the error case. It will be a NullPointerException rather than an IllegalArgumentException, but even that’s a change that will lead to a more precise description of the actual problem.
Regarding the rest of the method, I strongly advice to never let Collections be null in the first place. Then, you don’t have to test the result of getVehicleMakesByRegion for null and won’t return null by yourself.
However, if you have to stay with the original logic, you may achieve it using
return Optional.ofNullable(loader.getVehicleMakesByRegion(region.name()))
.map(regionMakes -> regionMakes.stream()
.filter(make -> Optional.ofNullable(make.getName())
.filter(name->name.startsWith(nameStartsWith))
.isPresent())
.collect(Collectors.toList()))
.orElse(null);
The initial code, which is intended to reject null references, should not get mixed with the actual operation which is intended to handle null references.
I have updated your code with Optional:
public static List<VehicleMake> loadMatchingJava8(Region region, String nameStartsWith, VehicleLoader loader) {
Optional<List<VehicleMake>> regionMakes = Optional.ofNullable(region)
.flatMap(r -> Optional.ofNullable(loader).map(l -> l.getVehicleMakesByRegion(r.name())));
return Optional.ofNullable(nameStartsWith)
.map(s -> regionMakes
.map(Collection::stream)
.orElse(Stream.empty())
.filter(make -> make.getName() != null && make.getName().startsWith(s))
.collect(Collectors.toList()))
.orElse(Collections.emptyList());
}
If you really want to convert flow control to Optional, the code keep consistent with yours should be like this(I break the code in 2 lines for printing):
public static Optional<List<VehicleMake>> loadMatchingJava8(Region region,
String nameStartsWith,
VehicleLoader loader) {
if ((nameStartsWith == null) || (region == null) || (loader == null)) {
throw new IllegalArgumentException("The VehicleLoader and both region and " +
"nameStartsWith are required when loading VehicleMake matches");
}
return Optional.ofNullable(loader.getVehicleMakesByRegion(region.name()))
.map(makers -> makers.stream()
.filter((it) -> it.getName() != null
&& it.getName().startsWith(nameStartsWith))
.collect(Collectors.toList()));
}
NOTE: you can see more about why do not abuse Optional in this question.
I can't say this is very elegant, but it should satisfy your requirement. There are no explicit null checks, but it'll throw the exception if any input parameters are null, and it filters out vehicles with invalid names from the resulting list.
public static List<VehicleMake> loadMatching(Region region, String nameStartsWith, VehicleLoader loader) {
return Optional.ofNullable(nameStartsWith)
.flatMap(startWith -> Optional.ofNullable(loader)
.flatMap(vl -> Optional.ofNullable(region)
.map(Region::name)
.map(vl::getVehicleMakesByRegion))
.map(makes -> makes.stream()
.filter(make -> Optional.ofNullable(make.getName())
.filter(name -> name.startsWith(startWith))
.isPresent())
.collect(Collectors.toList())))
.orElseThrow(() -> new IllegalArgumentException("The VehicleLoader and both region and nameStartsWith are required when loading VehicleMake matches"));