What would be a good pattern to use here?
I donĀ“t want to return nulls, that just does not feel right.
Another thing is, what if I want to return the reason that causes it to null? If caller knows why it is null, it can do some extra things so I want caller knows it and acts that way
Public CustomerDetails getCustomerDetails(){
if(noCustomer){
..log..etc..
return null;
}
if(some other bad weird condition){
..log..etc..
return null;
}
CustomerDetails details= getCustomerDetailsFromSomewhere();
if (details!=null){
return details;
}
else {
..log..etc..
return null;
}
}
I think you have 3 main options:
If null is a valid state I see no problem in returning null
If null is an invalid state you should throw an exception
Or make use of the Null object pattern
If you are using googles Guava libraries you can also use the Optional class.
The more natural way in Java is to throw an exception on an error condition.
public CustomerDetails getCustomerDetails(){
if(noCustomer){
..log..etc..
throw new NoSuchCustomer(customerName);
}
if(some other bad weird condition){
..log..etc..
throw new IllegalStateException("some other bad weird condition occurred");
}
CustomerDetails details= getCustomerDetailsFromSomewhere();
if (details==null)
throw new IllegalStateException("Failed to get customer details for "+ customerName);
return details;
}
The method getCustomerDetailsFromSomewhere() could throw an exception instead of returning null.
If you mean that the null does not explain its state, you can wrapper CustomerDetails with another class that can give more details. For example:
class Feedback()
{
private CustomerDetails result;
private int status;
public static final int STATUS_OK = 0;
public static final int STATUS_NULL = 1;
public static final int STATUS_NO_CUSTOMER = 2;
public static final int STATUS_BAD_CONDITION = 3;
public Feedback(CustomerDetails result, int status)
{
this.result = result;
this.status= status;
}
public CustomerDetails getResult(){return result;}
public int getStatus(){return status;}
}
and change your method with:
Public Feedback getCustomerDetails()
{
if(noCustomer)
{
..log..etc..
return new Feedback(null, Feeback.STATUS_NO_CUSTOMER);
}
if(some other bad weird condition)
{
..log..etc..
return new Feedback(null, Feeback.STATUS_BAD_CONDITION);
}
CustomerDetails details = getCustomerDetailsFromSomewhere();
if(details != null)
{
return new Feedback(details, Feeback.STATUS_OK);
}
else
{
..log..etc..
return new Feedback(null, Feeback.STATUS_NULL);
}
}
Then you can get the status by feedback.getStatus().
Try Guava's Optional. See this article on avoiding null: http://code.google.com/p/guava-libraries/wiki/UsingAndAvoidingNullExplained
Use Google Guava Optional.
This will help.
Many of the cases where programmers use null is to indicate some sort
of absence: perhaps where there might have been a value, there is
none, or one could not be found. For example, Map.get returns null
when no value is found for a key.
Optional is a way of replacing a nullable T reference with a
non-null value. An Optional may either contain a non-null T reference
(in which case we say the reference is "present"), or it may contain
nothing (in which case we say the reference is "absent"). It is never
said to "contain null."
Optional<Integer> possible = Optional.of(5);
possible.isPresent(); // returns true
possible.get(); // returns 5
You could try;
CustomerDetails details = setDetailsToEmpty();
or some equivalent.
You still have to check, either for null or empty customer details.
If you really don't want null create a special CustomerDetails object
...
public static final CustomerDetails EMPTY_CUSTOMER_DETAILS = new CustomerDetails();
...
public CustomerDetails getCustomerDetails(){
...
if (details!=null){
return details;
}
...
return EMPTY_CUSTOMER_DETAILS;
Related
I'm implementing an API but in my service layer I don't really know how to handle .get() of Optionals.
#Service
public class AttributedValueService {
...
public AttributedValueDTO createAttributedValue(ActionDTO actionDTO) {
Optional<RedeemableValue> redeemableValue = redeemableValueRepository.findRedeemableValueByProductId(actionDTO.getProductId());
Optional<Value> value = valueRepository.findById(redeemableValue.get().getValue().getId());
AttributedValue attributedValue = new AttributedValue(value.get(), actionDTO.getId(), actionDTO.getUserId());
return new AttributedValueDTO(attributedValueRepository.save(attributedValue));
}
}
My API receives a object and retrieves some other objects from the DB using info from that object and I want to make sure that a ObjectNotFound is returned when one of the .get() doesn't find a object.
Currently I'm thinking about using a orElseThrow on the find calls, something like that:
#Service
public class AttributedValueService {
...
public AttributedValueDTO createAttributedValue(ActionDTO actionDTO) {
RedeemableValue redeemableValue = redeemableValueRepository.findRedeemableValueByProductId(actionDTO.getProductId())
.orElseThrow(() -> new ObjectNotFoundException("Id: "+redeemableValueDTO.getRedeemableValueId(),"Referred Redeemable Value could not be found"));
Value value = valueRepository.findById(redeemableValue.get().getValue().getId())
.orElseThrow(() -> new ObjectNotFoundException("Id: "+valueDTO.getValueId(),"Referred Value could not be found"));
AttributedValue attributedValue = new AttributedValue(value.get(), actionDTO.getId(), actionDTO.getUserId());
return new AttributedValueDTO(attributedValueRepository.save(attributedValue));
}
}
Leaving exception handling for Spring, which returns a 404. But, is this the correct approach?
edit:
Fixed the Optional return of the createAttributedValue method, thanks for the tips.
First of all, as #Turing85 said, there is no silver bullet.
If you have a RedeemableValueService and ValueService you can let those classes handle the Optional instead of handling it at AttributedValueService
It would be something like:
#Service
public class AttributedValueService {
...
public AttributedValueDTO createAttributedValue(ActionDTO actionDTO) {
Value value = valueService.findByProductId(actionDTO.getProductId());
AttributedValue attributedValue = new AttributedValue(value, actionDTO.getId(), actionDTO.getUserId());
return new AttributedValueDTO(attributedValueRepository.save(attributedValue));
}
}
#Service
public class ValueService {
...
public Value findByProductId(IdType productId) {
RedeemableValue redeemableValue = redeemableValueService.findByProductId(productId);
return valueRepository.findById(redeemableValue.getValue().getId()).orElseThrow(YourException::new);
}
}
#Service
public class RedeemableValueService {
...
public RedeemableValue findByProductId(IdType productId) {
return redeemableValueRepository.findRedeemableValueByProductId(productId).orElseThrow(YourException::new);
}
}
If i get you right, then you only have the use cases:
either you find nothing, then an exception is thrown
or you find something, then you return the object
Thus there is no need for an Optional because it will never be absent ^^ So why add this complexity?
As far as I understand your question, your requirement is to check whether the object you are fetching from database is present or not if not then you want to throw some exception.
Here in Optional class we have one method isPresent() it will return true if Optional has some value or it will return false if not.
You can do like below:
#Service
public class AttributedValueService {
...
public Optional<AttributedValueDTO> createAttributedValue(ActionDTO actionDTO) {
Optional<RedeemableValue> redeemableValue = redeemableValueRepository.findRedeemableValueByProductId(actionDTO.getProductId());
if(redeemableValue.isPresent()){
Optional<Value> value = valueRepository.findById(redeemableValue.get().getValue().getId());
if(value.isPresent()){
AttributedValue attributedValue = new AttributedValue(value.get(), actionDTO.getId(), actionDTO.getUserId());
return Optional.of(new AttributedValueDTO(attributedValueRepository.save(attributedValue)));}
else{
throw ObjectNotFoundException() // custom exception
}
}
else{
throw ObjectNotFoundException() // custom exception
}
}
}
I don't understand your logic behind returning the Optional, because at each step we are checking for optional value then its not required.
Does anyone know any solution to safely get value without NPE and without a lot of if statements?
For example, we have: userInfo.getAddressInfo().getCityName(),
how to get cityName without null-checks?
Sometimes, for my pet projects I use something like that:
public static <T> String safeGetValue(Supplier<String> supplier) {
try {
return supplier.get();
} catch (NullPointerException e) {
e.printStackTrace();
}
return "";
}
Maybe exists better way to do this.
Full example:
import java.util.function.Supplier;
public class ExampleClass {
public static void main(String[] args) {
UserInfoResponse userInfo = new UserInfoResponse();
String value = safeGetValue(() -> userInfo.getAddressInfo().getCityName());
System.out.println(value);
}
public static <T> String safeGetValue(Supplier<String> supplier) {
try {
return supplier.get();
} catch (NullPointerException e) {
e.printStackTrace();
}
return "";
}
public static <T> String safeGetValue(Supplier<String> supplier, String defaultValue) {
try {
return supplier.get();
} catch (NullPointerException e) {
e.printStackTrace();
}
return defaultValue;
}
public static <T> String safeGetValue(Supplier<String> supplier, Runnable runnable) {
try {
return supplier.get();
} catch (NullPointerException e) {
runnable.run();
}
return "";
}
public static <T> String safeGetValue(Supplier<String> supplier, Runnable runnable, String defaultValue) {
try {
return supplier.get();
} catch (NullPointerException e) {
runnable.run();
}
return defaultValue;
}
}
class UserInfoResponse {
private String firstName;
private UserAddressInfo addressInfo;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public UserAddressInfo getAddressInfo() {
return addressInfo;
}
public void setAddressInfo(UserAddressInfo addressInfo) {
this.addressInfo = addressInfo;
}
}
class UserAddressInfo {
private String cityName;
public String getCityName() {
return cityName;
}
public void setCityName(String cityName) {
this.cityName = cityName;
}
}
I'm looking for a solution without if statements.
Ternary statement can't be a good solution too.
Unfortunately, if tests and conditional expressions are the only alternatives to catching NPEs. (But they are better alternatives!)
To me, the real problem is that the nulls are there in the first place. A better idea is to modify the design so that nulls are not returned. If they are not returned by getters, then you don't have to deal with them.
Here are some ways to design your APIs to not return null.
Make it impossible to create domain objects with null field values:
Constructors and setters should check that their arguments are not null, and thrown an exception (e.g. NPE) when called with bogus null arguments.
Fields could be default initialized with non-null values.
Have the getters return non-null values when field values are null. (But see below!)
Have the getters throw an exception when the user gets a field which should not be null has a null value.
Use the Null Object pattern. Create an special instance of each of your domain objects that represents "no object". Ideally, a Null Object should be immutable ... or should throw an exception if you attempt to modify it by accident.
Use Optional<ReferenceType>.
For builtin types / common types:
use "" instead of null for strings
use a zero length array instead of null for arrays
use (immutable) empty collection objects instead of null for collection types
avoid the primitive wrapper types: use the primitive types that cannot be null.
The other way to look at this is that if your API is specified so that a getter shouldn't return a null, then if it does return a null that is a bug. So, if you then write code to turn the nulls into something else (e.g. empty strings) to avoid the pesky NPEs, what you actually doing is hiding the bugs. A better idea is to let the NPE happen, log it, and then crash the application. (Or return a "500 Internal Error" response.)
Fixing a bug is better than hiding a bug.
But (I hear you ask) "What about reliability? It is embarrassing if my code crashes with NPEs!"
Well yes, but an NPE is better than a null workaround that gives incorrect answers to your users ... or writes bad data into your database.
And the conventional way to avoid bugs (e.g. NPEs) showing up in production is extensive automated testing. More / better unit tests. More / better system tests. Beta test releases, pre-production servers, etc.
Using Optional<T> chain you can write following
UserInfoResponse userInfo = new UserInfoResponse();
String value = Optional.ofNullable(userInfo.getAddressInfo())
.map(UserAddressInfo::getCityName)
.orElse(null);
or
String value = Optional.ofNullable(userInfo)
.map(UserInfoResponse::getAddressInfo)
.map(UserAddressInfo::getCityName)
.orElse(null);
or
String value = Optional.ofNullable(userInfo)
.map(ui -> ui.getAddressInfo())
.map(uai -> uai.getCityName())
.orElse(null);
I have a class structure like this:
public class Foo {
private FooB foob;
public Optional<FooB> getFoob() {
return Optional.ofNullable(foob);
}
}
public class FooB {
private int valA;
public int getValA() {
return valA;
}
}
My objective is to call the get method for fooB and then check to see if it's present. If it is present then return the valA property, if it doesn't then just return null. So something like this:
Integer valA = foo.getFoob().ifPresent(getValA()).orElse(null);
Of course this isn't proper Java 8 optional syntax but that's my "psuedo code". Is there any way to achieve this in Java 8 with 1 line?
What you are describing is the method Optional.map:
Integer valA = foo.getFoob().map(foo -> foo.getValA()).orElse(null);
map lets you transform the value inside an Optional with a function if the value is present, and returns an empty the optional if the value in not present.
Note also that you can return null from the mapping function, in which case the result will be Optional.empty().
Why you dont add a getValue methode to the class Foo? This would be a kind of delegation.
public class Foo {
...
public Integer getValue() {
if (foob == null) {
return null;
}
return foob.getValA();
}
}
Can someone get me out of LambdaJ pit I fell into please?
let's assume I have a list of objects of this class:
private class TestObject {
private String A;
private String B;
//gettters and setters
}
Let's say I want to select the objects from the list where A.equals(B)
I tried this:
List<TestObject> theSameList = select(testList, having(on(TestObject.class).getA(), equalTo(on(TestObject.class).getB())));
but this returns an empty list
And this:
List<TestObject> theSameList = select(testList, having(on(TestObject.class).getA().equals(on(TestObject.class).getB())));
but that throws an exception [EDIT: due to known limitations of proxying final classes]
Note, One way of getting around this is to have a method that compares the two fields inside the TestObject, but let's assume I cannot do this for a reason of your choice.
What am I missing?
After poking and fiddling with LambdaJ to match on the fields of the same object, the only solution that is working for me is writing a custom matcher. Here's quick and dirty implementation of one that would do the job:
private Matcher<Object> hasPropertiesEqual(final String propA, final String propB) {
return new TypeSafeMatcher<Object>() {
public void describeTo(final Description description) {
description.appendText("The propeties are not equal");
}
#Override
protected boolean matchesSafely(final Object object) {
Object propAValue, propBValue;
try {
propAValue = PropertyUtils.getProperty(object, propA);
propBValue = PropertyUtils.getProperty(object, propB);
} catch(Exception e) {
return false;
}
return propAValue.equals(propBValue);
}
};
}
The PropertyUtils is the class from org.apache.commons.beanutils
The way to use this matcher:
List<TestObject> theSameList = select(testList, having(on(TestObject.class), hasPropertiesEqual("a", "b")));
I am using the Oval validation framework to validate fields that HTML fields cannot hold malicious javascript code. For the malicious code detection, I am using an external framework that returns me a list of errors that I would like to use as error messages on the field. The problem I am running into is that I can only setMessage in the check implementation, while I would rather do something like setMessages(List). So while I am currently just joining the errors with a comma, I would rather pass them back up as a list.
Annotation
#Target({ ElementType.METHOD, ElementType.FIELD})
#Retention( RetentionPolicy.RUNTIME)
#Constraint(checkWith = HtmlFieldValidator.class)
public #interface HtmlField {
String message() default "HTML could not be validated";
}
Check
public class HtmlFieldValidator extends AbstractAnnotationCheck<HtmlDefaultValue> {
public boolean isSatisfied( Object o, Object o1, OValContext oValContext, Validator validator ) throws OValException {
if (o1 == null) {
return true;
} else {
CleanResults cleanResults = UIowaAntiSamy.cleanHtml((String) o1);
if (cleanResults.getErrorMessages().size() > 0) {
String errors = StringUtils.join(cleanResults.getErrorMessages(), ", ");
this.setMessage(errors);
return false;
} else {
return true;
}
}
}
}
Model class
class Foo {
#HtmlField
public String bar;
}
Controller code
Validator validator = new Validator(); // use the OVal validator
Foo foo = new Foo();
foo.bar = "<script>hack()</script>";
List<ConstraintViolation> violations = validator.validate(bo);
if (violations.size() > 0) {
// inform the user that I cannot accept the string because
// it contains invalid html, using error messages from OVal
}
If setMessage(String message) is a method created by a superclass, you can override it and once it receives the data, simply split the string into a list and call a second function in which you would actually place your code. On a side note, I would also recommend changing the separating string to something more unique as the error message itself could include a comma.
Your question doesn't really make much sense though. If you are "passing them back up" to a method implemented in a superclass, then this voids the entire point of your question as the superclass will be handling the data.
I am going to assume the setError methods is a simple setter that sets a String variable to store an error message that you plan to access after checking the data. Since you want to have the data in your preferred type, just create a new array of strings in your class and ignore the superclass. You can even use both if you so desire.
public class HtmlFieldValidator extends AbstractAnnotationCheck<HtmlDefaultValue> {
public String[] errorMessages = null;
public void setErrorMessages(String[] s) {
this.errorMessages = s;
}
public boolean isSatisfied( Object o, Object o1, OValContext oValContext, Validator validator ) throws OValException {
if (o1 == null) {
return true;
} else {
CleanResults cleanResults = UIowaAntiSamy.cleanHtml((String) o1);
if (cleanResults.getErrorMessages().size() > 0) {
//String errors = StringUtils.join(cleanResults.getErrorMessages(), ", ");
//this.setMessage(errors);
this.setErrorMessages(cleanResults.getErrorMessages());
return false;
} else {
return true;
}
}
}
}
Elsewhere:
HtmlFieldValidator<DefaultValue> hfv = new HtmlFieldValidator<DefaultValue>();
boolean satisfied = hfv.isSatisfied(params);
if (!satisfied) {
String[] errorMessages = hfv.errorMessages;
//instead of using their error message
satisfy(errorMessages);//or whatever you want to do
}
EDIT:
After you updated your code I see what you mean. While I think this is sort of overdoing it and it would be much easier to just convert the string into an array later, you might be able to do it by creating a new class that extends Validator its setMessage method. In the method, you would call super.setMethod as well as splitting and storing the string as an array in its class.
class ValidatorWithArray extends Validator {
public String[] errors;
public final static String SPLIT_REGEX = ";&spLit;";// Something unique so you wont accidentally have it in the error
public void setMessage(String error) {
super.setMessage(error);
this.errors = String.split(error, SPLIT_REGEX);
}
}
In HtmlFieldValidator:
public boolean isSatisfied( Object o, Object o1, OValContext oValContext, Validator validator ) throws OValException {
if (o1 == null) {
return true;
} else {
CleanResults cleanResults = UIowaAntiSamy.cleanHtml((String) o1);
if (cleanResults.getErrorMessages().size() > 0) {
String errors = StringUtils.join(cleanResults.getErrorMessages(), ValidatorWithArray.SPLIT_REGEX);
this.setMessage(errors);
return false;
} else {
return true;
}
}
}
And now just use ValidatorWithArray instead of Validator
The situation in which I want to achieve this was different from yours, however what I found was best in my case was to create an annotation for each error (rather than having one that would return multiple errors). I guess it depends on how many errors you are likely to be producing in my case it was only two or three.
This method makes also makes your code really easy to reuse as you can just add the annotations wherenever you need them and combine them at will.