I am quite new to the concept of Optional. In the code posted below, i am checking the following:
if (operation_1) {
if (operation_2) {
if (operation_3) {
} else {
throw_3
}
} else {
throw_2
}
} else {
throw_1
}
but for this code, android studio, generates an error for the second orElseThrow() operation "marked below".
please let me why I receive this error?how to fix it? whether or not the code i wrote below satisfies the conditions shown above.
code:
OptionalsUtils.toOptional(Room.databaseBuilder(getApplicationContext(), MovieDatabase.class, ActMain.DATA_BASE_NAME))//operation_1
.map(x->{
MovieDatabase movieRoomDb = x.fallbackToDestructiveMigration().build();
this.setInitializedBuiltMovieRoomDatabase(movieRoomDb);
return movieRoomDb;
})//operation_2
.map(y->{
SupportSQLiteOpenHelper openHelperInstance = y.getOpenHelper();
this.setSQLOpenHelperInstance(openHelperInstance);
return openHelperInstance;
})//operation_3
.orElseThrow(()-> new NullPointerException(THROW_SQL_OPEN_HELPER_NULL))//throw_3
.orElseThrow(()-> new NullPointerException(THROW_ROOM_DATABASE_PERSISTENT_BUILD_NULL))//throw_2<-cases error
.orElseThrow(()-> new NullPointerException(THROW_ROOM_DATABASE_PERSISTENT_BUILDER_NULL));//throw_1
I wouldn't recommend using an Optional here as it's not meant to
replace simple "if" cases.
instead, invert the if conditions to remove the nesting:
if (!operation_1)
throw_1;
if(!operation_2)
throw_2;
if(! operation_3)
trow_3;
...
...
As for your code, you cannot just chain orElseThrow methods as shown because the first call to orElseThrow will return the value encapsulated within the Optional if present otherwise throws the supplied exception thus the result of this method call is no longer an Optional.
Related
I have a REST Controller
#GetMapping("/getByClientId/{clientId}")
public ResponseEntity<Optional<List<EquityFeeds>>> getByClientId(#PathVariable("clientId") final String clientId) {
Optional<List<EquityFeeds>> cId = Optional.ofNullable(equityFeedsService.findByClientId(clientId));
System.out.println("Client Id: "+cId);
if(cId.isPresent()) {
return ResponseEntity.ok(cId);
} else {
cId.orElseThrow(() -> new ClientIdNotFoundException(clientId));
}
return ResponseEntity.ok(cId);
}
Service Class Code:
public List<EquityFeeds> findByClientId(String clientId) {
List<EquityFeeds> cId = equityFeedsRedisRepositoryImpl.findByClientId(clientId);
System.out.println("In EquityFeedService "+cId);
return cId;
}
Impl. Code (REDIS):
public List<EquityFeeds> findByClientId(String clientId) {
return (List<EquityFeeds>) listOperations.range(clientId, 0, -1);
}
Issue:
1) When the getClientId is called using a REST Controller and the clientId is not present in the REDIS Cache then:
Service class Code returns: In EquityFeedService []
The REST Controller returns: Client Id: Optional[[]]
In the REST Controller the code goes inside the if loop and displays nothing on the screen since the List is empty i.e.
if(cId.isPresent()) {
return ResponseEntity.ok(cId);
}
Why? Why cId.isPresent() returns true and the code goes inside the if loop. Ideally the code should go inside the else loop and throw an Exception since the List is empty. This is happening in case of List only it seems as my other method which has a return type of POJO doesn't have this issue.
Please help me understand this behavior and what should be done to fix this.
cId.isPresent() return true because
List<EquityFeeds> is not null , it's empty list
if(!cId.get().isEmpty()) {
return ResponseEntity.ok(cId);
} else {
throw new ClientIdNotFoundException(clientId);
}
The reason the Optional.isPresent returns true is that there is an actual value - an empty List. The Optional checks whether the value it holds is a null or not, nothing else. The isPresent checks whether the value is present inside the Optional, not inside the List itself.
So you have to treat Optional a bit different. Moreover, don't use Optional like that as substitution to the if-else constructs.
Here is a way to go:
return cId.filter(Predicate.not(List::Empty)) // if the list is not empty
.map(ResponseEntity::ok) // create a response
.orElseThrow(() -> // or else throw an exception
new ClientIdNotFoundException(clientId));
By the way, you don't want to return Optional wrapped inside the ResponseEntity. Unwrap it and return the List itself. If it is empty or null was already handled and the exception would be thrown first.
return cId.filter(Predicate.not(List::Empty))
.map(Optional::get) // exctract from the Optional
.map(ResponseEntity::ok)
.orElseThrow(() -> new ClientIdNotFoundException(clientId));
I'm communicating with an API, and I have utilised the use of the Optional class. But I feel like the error handling could be more elegant, so any suggestions on how to improve this will be well received. Also am I missing a exception handling in the actual api calls?
public Optional<Account> getGreenqloudAccount(String accountUUid) {
System.out.println("tmplog: GreenqloudAccountDao->getGreenqloudAccount");
for (Account account : apiClient.accountList()) {
if (account.getUuid().equals(accountUUid)) {
System.out.println("getGreenqloudAccount, account: " + account.toString());
return Optional.of(account);
}
}
return Optional.empty();
}
public Optional<String> getMarketplaceCustomerIdByUsername(String username) {
if (username == null || username.equals("")) {
return Optional.empty();
}
AwsMarketplace marketplaceData = apiClient.getMarketplaceData(getKeys(username));
if (marketplaceData == null) {
return Optional.empty();
}
return Optional.ofNullable(marketplaceData.getObjects().get(0).getCustomerId());
}
private Pair getKeys(String username) {
GetKeys getKeys = apiClient.getKeys(username);
return new Pair(getKeys.getApiPrivateKey(), getKeys.getApiPublicKey());
}
The main problem with your code: you throw plenty of very different outcomes into the same "bucket".
getMarketplaceCustomerIdByUsername() for example returns an empty Optional when:
the username is null
the username is "" (and think about it "" means empty, but " " isnt empty?!)
no AwsMarketplace instance can be found for the given user
As said, these are very different problems. The first one might indicate: the provided user name is bad, so you should tell your user about that. The last one means: "something is fishy, maybe the user is unknown, or something else happened".
Thus: consider to not reduce different results into an empty Optional. Rather consider to throw (different?) exceptions. You use Optional when "no result" is a valid result of the operation. But "no result, because bad user name" doesn't feel like a valid result.
If you mean handling corner cases, you could improve the code readability along with them as in the first method using findFirst such as:
public Optional<Account> getGreenqloudAccount(String accountUUid) {
System.out.println("tmplog: GreenqloudAccountDao->getGreenqloudAccount");
return apiClient.accountList().stream()
.filter(account -> account.getUuId().equals(accountUUid))
// you can 'peek' and log
.findFirst(); // you return the first account or empty
}
Moving further with the other API, notice Optional.map handles operations returning null values and returns Optional.empty for them implicitly. So you can use:
public Optional<String> getMarketplaceCustomerIdByUsername(String username) {
return Optional.ofNullable(username) // if username is null empty
.filter(name -> !name.isEmpty()) // empty string returns filtered out
.map(name -> apiClient.getMarketplaceData(getKeys(name))) // handles 'null' calue returned
.map(marketplaceData -> marketplaceData.getObjects().get(0).getCustomerId()); // here as well
}
You can use a check using Optional.isPresent()
or
use Optional.orElseThrow(Supplier<? extends X> exceptionSupplier)
Read JDK8 Doc about Optional here
Additionally, you might want to trim your input parameters before checking for empty strings
Is method chaining good?
I am not against functional programming that uses method chaining a lot, but against a herd mentality where people mindlessly run behind something that is new.
The example, if I am processing a list of items using stream programming and need to find out the exact row that resulted into throwing NullPointerException.
private void test() {
List<User> aList = new ArrayList<>();
// fill aList with some data
aList.stream().forEach(x -> doSomethingMeaningFul(x.getAddress()));
}
private void doSomethingMeaningFul(Address x) {
// Do something
}
So in the example above if any object in list is null, it will lead to NullPointerException while calling x.getAddress() and come out, without giving us a hook to identify a User record which has this problem.
I may be missing something that offers this feature in stream programming, any help is appreciated.
Edit 1:
NPE is just an example, but there are several other RuntimeExceptions that could occur. Writing filter would essentially mean checking for every RTE condition based on the operation I am performing. And checking for every operation will become a pain.
To give a better idea about what I mean following is the snippet using older methods; I couldn't find any equivalent with streams / functional programming methods.
List<User> aList = new ArrayList<>();
// Fill list with some data
int counter = 0;
User u = null;
try {
for (;counter < aList.size(); counter++) {
u = aList.get(counter);
u.doSomething();
int result = u.getX() / u.getY();
}
} catch(Exception e) {
System.out.println("Error processing at index:" + counter + " with User record:" + u);
System.out.println("Exception:" + e);
}
This will be a boon during the maintenance phase(longest phase) pointing exact data related issues which are difficult to reproduce.
**Benefits:**
- Find exact index causing issue, pointing to data
- Any RTE is recorded and analyzed against the user record
- Smaller stacktrace to look at
Is method chaining good?
As so often, the simple answer is: it depends.
When you
know what you are doing
are be very sure that elements will never be null, thus the chance for an NPE in such a construct is (close to) 0
and the chaining of calls leads to improved readability
then sure, chain calls.
If any of the above criteria isn't clearly fulfilled, then consider not doing that.
In any case, it might be helpful to distribute your method calls on new lines. Tools like IntelliJ actually give you advanced type information for each line, when you do that (well, not always, see my own question ;)
From a different perspective: to the compiler, it doesn't matter much if you chain call. That really only matters to humans. Either for readability, or during debugging.
There are a few aspects to this.
1) Nulls
It's best to avoid the problem of checking for nulls, by never assigning null. This applies whether you're doing functional programming or not. Unfortunately a lot of library code does expose the possibility of a null return value, but try to limit exposure to this by handling it in one place.
Regardless of whether you're doing FP or not, you'll find you get a lot less frustrated if you never have to write null checks when calling your own methods, because your own methods can never return null.
An alternative to variables that might be null, is to use Java 8's Optional class.
Instead of:
public String myMethod(int i) {
if(i>0) {
return "Hello";
} else {
return null;
}
}
Do:
public Optional<String> myMethod(int i) {
if(i>0) {
return Optional.of("Hello");
} else {
return Optional.empty();
}
Look at Optional Javadoc to see how this forces the caller to think about the possibility of an Optional.empty() response.
As a bridge between the worlds of "null represents absent" and "Optional.empty() represents absent", you can use Optional.ofNullable(val) which returns Empty when val == null. But do bear in mind that Optional.empty() and Optional.of(null) are different values.
2) Exceptions
It's true that throwing an exception in a stream handler doesn't work very well. Exceptions aren't a very FP-friendly mechanism. The FP-friendly alternative is Either -- which isn't a standard part of Java but is easy to write yourself or find in third party libraries: Is there an equivalent of Scala's Either in Java 8?
public Either<Exception, Result> meaningfulMethod(Value val) {
try {
return Either.right(methodThatMightThrow(val));
} catch (Exception e) {
return Either.left(e);
}
}
... then:
List<Either<Exception, Result>> results = listOfValues.stream().map(meaningfulMethod).collect(Collectors.toList());
3) Indexes
You want to know the index of the stream element, when you're using a stream made from a List? See Is there a concise way to iterate over a stream with indices in Java 8?
In your test() function you are creating an emptylist List<User> aList = new ArrayList<>();
And doing for each on it. First add some element to
aList
If you want to handle null values you can add .filter(x-> x != null) this before foreach it will filter out all null value
Below is code
private void test() {
List<User> aList = new ArrayList<>();
aList.stream().filter(x-> x != null).forEach(x -> doSomethingMeaningFul(x.getAddress()));
}
private void doSomethingMeaningFul(Address x) {
// Do something
}
You can write a black of code in streams. And you can find out the list item which might result in NullPointerException. I hope this code might help
private void test() {
List<User> aList = new ArrayList<>();
aList.stream().forEach(x -> {
if(x.getAddress() != null)
return doSomethingMeaningFul(x.getAddress())
else
system.out.println(x+ "doesn't have address");
});
}
private void doSomethingMeaningFul(Address x) {
// Do something
}
If you want you can throw NullPointerException or custom excption like AddressNotFoundException in the else part
We have a huge project where many methods have been declared upfront and implementations are in progress. All declared methods have a body which simply throws an exception, say, UnimplException.
Now since the methods have been declared and a valid (compilable) body has been provided, they can be called from within other methods.
Now the question is that is there any way to list all such unimplemented (having just a compilable body throwing a particular exception) methods given a particular method?
To illustrate more(the code is to convey the idea and not strictly compiler friendly):
class A {
methA () {
throw new UnimplException();
}
}
class B {
methB () {
// proper body
// and calls methA
A.methA();
// does something else
// and returns.
}
}
class C {
methC () {
// proper body
// calls methB
B.methB();
}
}
So, if we start from, say, methC, then we want to travel all the way down the method tree to reach to methA because methC calls methB (which is properly implemented and we are not interested) which in turn calls methA which is not properly implemented and that is what we want to find.
We want to search for all such unimplemented methods starting from a method and going few levels deep until we cover all such unimplemented methods.
We thought of JavaAssist but we aren't sure how to go down all the levels because it seems to be giving us all methods called from within a method but not recursively.
Any help is greatly appreciated :)
Have you seen this project: https://github.com/gousiosg/java-callgraph? This appears to do the Java introspection part, listing every method call from every method in a jar file. I'd try using that to do the heavy lifting of parsing your code, then just recurse through the results.
Something like:
Use the callgraph code to build a list of all method calls.
Save that data somewhere.
Recursively parse that structure to find matching methods.
So from your example, step 1 would give something like the following:
A:methA -> UnimplException:<init>
B:methB -> A:methA
C:methC -> B:methB
Then shove those in a Multimap and do a fairly straightforward recursive search:
// this is populated from the output of the callgraph code
com.google.common.collect.Multimap<String, String> methodMap;
void checkAllMethods() {
for (String method : methodMap.keySet()) {
List<String> callStack = new ArrayList<>();
if (doesMethodThrowUnimplException(method, callStack)) {
System.out.println(method);
// can print callStack too if interested
}
}
}
boolean doesMethodThrowUnimplException(String method, List<String> callStack) {
for (String child : methodMap.get(method)) {
// have to check the exact method name from callgraph
if (child.equals("UnimplException:<init>")) {
return true;
}
// recurse into child if not already seen
if (!callStack.contains(child)) {
callStack.add(child);
if (doesMethodThrowUnimplException(child, callStack)) {
return true;
}
callStack.remove(callStack.size() - 1);
}
}
return false;
}
Doesn't strictly satisfy your requirements as this will report any method which throws the UnimplException, not those who only throw the exception, but not sure if that matters.
Standard disclaimer - just typed this in - haven't compiled / run it, so may well be typos, but hopefully the idea helps.
I want to verify multiple conditions for validations. Currently, I have it set up such that in case of an error, each condition returns the error message, and an empty string in the absence of any errors. As a result, my code looks something like this:
String error = condition1(argA, argB);
if (!"".equals(error)) {
return error;
}
error = condition2(argC, argD);
.
.
.
and so on.
I wanted to know if there's a more elegant way of doing this in Java (or cofeescript)?
How about rather than having a lot of if statements you just create one method to check since if seems the check is the same for all conditions like.
public String check(String err)
{
if (!"".equals(err))
{
return err;
}
return err;
}
Now whenever you checking you just call the method
check(condition1(argA,argB));
and
check(condition2(argC,argB));
The string returned ofcause you know what to do with it.
Hope that helps