Related
A web service returns a huge XML and I need to access deeply nested fields of it. For example:
return wsObject.getFoo().getBar().getBaz().getInt()
The problem is that getFoo(), getBar(), getBaz() may all return null.
However, if I check for null in all cases, the code becomes very verbose and hard to read. Moreover, I may miss the checks for some of the fields.
if (wsObject.getFoo() == null) return -1;
if (wsObject.getFoo().getBar() == null) return -1;
// maybe also do something with wsObject.getFoo().getBar()
if (wsObject.getFoo().getBar().getBaz() == null) return -1;
return wsObject.getFoo().getBar().getBaz().getInt();
Is it acceptable to write
try {
return wsObject.getFoo().getBar().getBaz().getInt();
} catch (NullPointerException ignored) {
return -1;
}
or would that be considered an antipattern?
Catching NullPointerException is a really problematic thing to do since they can happen almost anywhere. It's very easy to get one from a bug, catch it by accident and continue as if everything is normal, thus hiding a real problem. It's so tricky to deal with so it's best to avoid altogether. (For example, think about auto-unboxing of a null Integer.)
I suggest that you use the Optional class instead. This is often the best approach when you want to work with values that are either present or absent.
Using that you could write your code like this:
public Optional<Integer> m(Ws wsObject) {
return Optional.ofNullable(wsObject.getFoo()) // Here you get Optional.empty() if the Foo is null
.map(f -> f.getBar()) // Here you transform the optional or get empty if the Bar is null
.map(b -> b.getBaz())
.map(b -> b.getInt());
// Add this if you want to return null instead of an empty optional if any is null
// .orElse(null);
// Or this if you want to throw an exception instead
// .orElseThrow(SomeApplicationException::new);
}
Why optional?
Using Optionals instead of null for values that might be absent makes that fact very visible and clear to readers, and the type system will make sure you don't accidentally forget about it.
You also get access to methods for working with such values more conveniently, like map and orElse.
Is absence valid or error?
But also think about if it is a valid result for the intermediate methods to return null or if that is a sign of an error. If it is always an error then it's probably better throw an exception than to return a special value, or for the intermediate methods themselves to throw an exception.
Maybe more optionals?
If on the other hand absent values from the intermediate methods are valid, maybe you can switch to Optionals for them also?
Then you could use them like this:
public Optional<Integer> mo(Ws wsObject) {
return wsObject.getFoo()
.flatMap(f -> f.getBar())
.flatMap(b -> b.getBaz())
.flatMap(b -> b.getInt());
}
Why not optional?
The only reason I can think of for not using Optional is if this is in a really performance critical part of the code, and if garbage collection overhead turns out to be a problem. This is because a few Optional objects are allocated each time the code is executed, and the VM might not be able to optimize those away. In that case your original if-tests might be better.
I suggest considering Objects.requireNonNull(T obj, String message). You might build chains with a detailed message for each exception, like
requireNonNull(requireNonNull(requireNonNull(
wsObject, "wsObject is null")
.getFoo(), "getFoo() is null")
.getBar(), "getBar() is null");
I would suggest you not to use special return-values, like -1. That's not a Java style. Java has designed the mechanism of exceptions to avoid this old-fashioned way which came from the C language.
Throwing NullPointerException is not the best option too. You could provide your own exception (making it checked to guarantee that it will be handled by a user or unchecked to process it in an easier way) or use a specific exception from XML parser you are using.
Assuming the class structure is indeed out of our control, as seems to be the case, I think catching the NPE as suggested in the question is indeed a reasonable solution, unless performance is a major concern. One small improvement might be to wrap the throw/catch logic to avoid clutter:
static <T> T get(Supplier<T> supplier, T defaultValue) {
try {
return supplier.get();
} catch (NullPointerException e) {
return defaultValue;
}
}
Now you can simply do:
return get(() -> wsObject.getFoo().getBar().getBaz().getInt(), -1);
As already pointed out by Tom in the comment,
Following statement disobeys the Law of Demeter,
wsObject.getFoo().getBar().getBaz().getInt()
What you want is int and you can get it from Foo. Law of Demeter says, never talk to the strangers. For your case you can hide the actual implementation under the hood of Foo and Bar.
Now, you can create method in Foo to fetch int from Baz. Ultimately, Foo will have Bar and in Bar we can access Int without exposing Baz directly to Foo. So, null checks are probably divided to different classes and only required attributes will be shared among the classes.
My answer goes almost in the same line as #janki, but I would like to modify the code snippet slightly as below:
if (wsObject.getFoo() != null && wsObject.getFoo().getBar() != null && wsObject.getFoo().getBar().getBaz() != null)
return wsObject.getFoo().getBar().getBaz().getInt();
else
return something or throw exception;
You can add a null check for wsObject as well, if there's any chance of that object being null.
You say that some methods "may return null" but do not say in what circumstances they return null. You say you catch the NullPointerException but you do not say why you catch it. This lack of information suggests you do not have a clear understanding of what exceptions are for and why they are superior to the alternative.
Consider a class method that is meant to perform an action, but the method can not guarantee it will perform the action, because of circumstances beyond its control (which is in fact the case for all methods in Java). We call that method and it returns. The code that calls that method needs to know whether it was successful. How can it know? How can it be structured to cope with the two possibilities, of success or failure?
Using exceptions, we can write methods that have success as a post condition. If the method returns, it was successful. If it throws an exception, it had failed. This is a big win for clarity. We can write code that clearly processes the normal, success case, and move all the error handling code into catch clauses. It often transpires that the details of how or why a method was unsuccessful are not important to the caller, so the same catch clause can be used for handling several types of failure. And it often happens that a method does not need to catch exceptions at all, but can just allow them to propagate to its caller. Exceptions due to program bugs are in that latter class; few methods can react appropriately when there is a bug.
So, those methods that return null.
Does a null value indicate a bug in your code? If it does, you should not be catching the exception at all. And your code should not be trying to second guess itself. Just write what is clear and concise on the assumption that it will work. Is a chain of method calls clear and concise? Then just use them.
Does a null value indicate invalid input to your program? If it does, a NullPointerException is not an appropriate exception to throw, because conventionally it is reserved for indicating bugs. You probably want to throw a custom exception derived from IllegalArgumentException (if you want an unchecked exception) or IOException (if you want a checked exception). Is your program required to provide detailed syntax error messages when there is invalid input? If so, checking each method for a null return value then throwing an appropriate diagnostic exception is the only thing you can do. If your program need not provide detailed diagnostics, chaining the method calls together, catching any NullPointerException and then throwing your custom exception is clearest and most concise.
One of the answers claims that the chained method calls violate the Law of Demeter and thus are bad. That claim is mistaken.
When it comes to program design, there are not really any absolute rules about what is good and what is bad. There are only heuristics: rules that are right much (even almost all) of the time. Part of the skill of programming is knowing when it is OK to break those kinds of rules. So a terse assertion that "this is against rule X" is not really an answer at all. Is this one of the situations where the rule should be broken?
The Law of Demeter is really a rule about API or class interface design. When designing classes, it is useful to have a hierarchy of abstractions. You have low level classes that uses the language primitives to directly perform operations and represent objects in an abstraction that is higher level than the language primitives. You have medium level classes that delegate to the low level classes, and implement operations and representations at a higher level than the low level classes. You have high level classes that delegate to the medium level classes, and implement still higher level operations and abstractions. (I've talked about just three levels of abstraction here, but more are possible). This allows your code to express itself in terms of appropriate abstractions at each level, thereby hiding complexity. The rationale for the Law of Demeter is that if you have a chain of method calls, that suggests you have a high level class reaching in through a medium level class to deal directly with low level details, and therefore that your medium level class has not provided a medium-level abstract operation that the high level class needs. But it seems that is not the situation you have here: you did not design the classes in the chain of method calls, they are the result of some auto-generated XML serialization code (right?), and the chain of calls is not descending through an abstraction hierarchy because the des-serialized XML is all at the same level of the abstraction hierarchy (right?)?
As others have said, respecting the Law of Demeter is definitely part of the solution. Another part, wherever possible, is to change those chained methods so they cannot return null. You can avoid returning null by instead returning an empty String, an empty Collection, or some other dummy object that means or does whatever the caller would do with null.
To improve readability, you may want to use multiple variables, like
Foo theFoo;
Bar theBar;
Baz theBaz;
theFoo = wsObject.getFoo();
if ( theFoo == null ) {
// Exit.
}
theBar = theFoo.getBar();
if ( theBar == null ) {
// Exit.
}
theBaz = theBar.getBaz();
if ( theBaz == null ) {
// Exit.
}
return theBaz.getInt();
Don't catch NullPointerException. You don't know where it is coming from (I know it is not probable in your case but maybe something else threw it) and it is slow.
You want to access the specified field and for this every other field has to be not null. This is a perfect valid reason to check every field. I would probably check it in one if and then create a method for readability. As others pointed out already returning -1 is very oldschool but I don't know if you have a reason for it or not (e.g. talking to another system).
public int callService() {
...
if(isValid(wsObject)){
return wsObject.getFoo().getBar().getBaz().getInt();
}
return -1;
}
public boolean isValid(WsObject wsObject) {
if(wsObject.getFoo() != null &&
wsObject.getFoo().getBar() != null &&
wsObject.getFoo().getBar().getBaz() != null) {
return true;
}
return false;
}
Edit: It is debatable if it's disobeyes the Law Of Demeter since the WsObject is probably only a data structure (check https://stackoverflow.com/a/26021695/1528880).
If you don't want to refactor the code and you can use Java 8, it is possible to use Method references.
A simple demo first (excuse the static inner classes)
public class JavaApplication14
{
static class Baz
{
private final int _int;
public Baz(int value){ _int = value; }
public int getInt(){ return _int; }
}
static class Bar
{
private final Baz _baz;
public Bar(Baz baz){ _baz = baz; }
public Baz getBar(){ return _baz; }
}
static class Foo
{
private final Bar _bar;
public Foo(Bar bar){ _bar = bar; }
public Bar getBar(){ return _bar; }
}
static class WSObject
{
private final Foo _foo;
public WSObject(Foo foo){ _foo = foo; }
public Foo getFoo(){ return _foo; }
}
interface Getter<T, R>
{
R get(T value);
}
static class GetterResult<R>
{
public R result;
public int lastIndex;
}
/**
* #param args the command line arguments
*/
public static void main(String[] args)
{
WSObject wsObject = new WSObject(new Foo(new Bar(new Baz(241))));
WSObject wsObjectNull = new WSObject(new Foo(null));
GetterResult<Integer> intResult
= getterChain(wsObject, WSObject::getFoo, Foo::getBar, Bar::getBar, Baz::getInt);
GetterResult<Integer> intResult2
= getterChain(wsObjectNull, WSObject::getFoo, Foo::getBar, Bar::getBar, Baz::getInt);
System.out.println(intResult.result);
System.out.println(intResult.lastIndex);
System.out.println();
System.out.println(intResult2.result);
System.out.println(intResult2.lastIndex);
// TODO code application logic here
}
public static <R, V1, V2, V3, V4> GetterResult<R>
getterChain(V1 value, Getter<V1, V2> g1, Getter<V2, V3> g2, Getter<V3, V4> g3, Getter<V4, R> g4)
{
GetterResult result = new GetterResult<>();
Object tmp = value;
if (tmp == null)
return result;
tmp = g1.get((V1)tmp);
result.lastIndex++;
if (tmp == null)
return result;
tmp = g2.get((V2)tmp);
result.lastIndex++;
if (tmp == null)
return result;
tmp = g3.get((V3)tmp);
result.lastIndex++;
if (tmp == null)
return result;
tmp = g4.get((V4)tmp);
result.lastIndex++;
result.result = (R)tmp;
return result;
}
}
Output
241
4
null
2
The interface Getter is just a functional interface, you may use any equivalent.
GetterResult class, accessors stripped out for clarity, hold the result of the getter chain, if any, or the index of the last getter called.
The method getterChain is a simple, boilerplate piece of code, that can be generated automatically (or manually when needed).
I structured the code so that the repeating block is self evident.
This is not a perfect solution as you still need to define one overload of getterChain per number of getters.
I would refactor the code instead, but if can't and you find your self using long getter chains often you may consider building a class with the overloads that take from 2 to, say, 10, getters.
I'd like to add an answer which focus on the meaning of the error. Null exception in itself doesn't provide any meaning full error. So I'd advise to avoid dealing with them directly.
There is a thousands cases where your code can go wrong: cannot connect to database, IO Exception, Network error... If you deal with them one by one (like the null check here), it would be too much of a hassle.
In the code:
wsObject.getFoo().getBar().getBaz().getInt();
Even when you know which field is null, you have no idea about what goes wrong. Maybe Bar is null, but is it expected? Or is it a data error? Think about people who read your code
Like in xenteros's answer, I'd propose using custom unchecked exception. For example, in this situation: Foo can be null (valid data), but Bar and Baz should never be null (invalid data)
The code can be re-written:
void myFunction()
{
try
{
if (wsObject.getFoo() == null)
{
throw new FooNotExistException();
}
return wsObject.getFoo().getBar().getBaz().getInt();
}
catch (Exception ex)
{
log.error(ex.Message, ex); // Write log to track whatever exception happening
throw new OperationFailedException("The requested operation failed")
}
}
void Main()
{
try
{
myFunction();
}
catch(FooNotExistException)
{
// Show error: "Your foo does not exist, please check"
}
catch(OperationFailedException)
{
// Show error: "Operation failed, please contact our support"
}
}
NullPointerException is a run-time exception, so generally speaking is not recommended to catch it, but to avoid it.
You will have to catch the exception wherever you want to call the method (or it will propagate up the stack). Nevertheless, if in your case you can keep working with that result with value -1 and you are sure that it won't propagate because you are not using any of the "pieces" that may be null, then it seems right to me to catch it
Edit:
I agree with the later answer from #xenteros, it wil be better to launch your own exception instead returning -1 you can call it InvalidXMLException for instance.
Have been following this post since yesterday.
I have been commenting/voting the comments which says, catching NPE is bad. Here is why I have been doing that.
package com.todelete;
public class Test {
public static void main(String[] args) {
Address address = new Address();
address.setSomeCrap(null);
Person person = new Person();
person.setAddress(address);
long startTime = System.currentTimeMillis();
for (int i = 0; i < 1000000; i++) {
try {
System.out.println(person.getAddress().getSomeCrap().getCrap());
} catch (NullPointerException npe) {
}
}
long endTime = System.currentTimeMillis();
System.out.println((endTime - startTime) / 1000F);
long startTime1 = System.currentTimeMillis();
for (int i = 0; i < 1000000; i++) {
if (person != null) {
Address address1 = person.getAddress();
if (address1 != null) {
SomeCrap someCrap2 = address1.getSomeCrap();
if (someCrap2 != null) {
System.out.println(someCrap2.getCrap());
}
}
}
}
long endTime1 = System.currentTimeMillis();
System.out.println((endTime1 - startTime1) / 1000F);
}
}
public class Person {
private Address address;
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
}
package com.todelete;
public class Address {
private SomeCrap someCrap;
public SomeCrap getSomeCrap() {
return someCrap;
}
public void setSomeCrap(SomeCrap someCrap) {
this.someCrap = someCrap;
}
}
package com.todelete;
public class SomeCrap {
private String crap;
public String getCrap() {
return crap;
}
public void setCrap(String crap) {
this.crap = crap;
}
}
Output
3.216
0.002
I see a clear winner here. Having if checks is way too less expensive than catch an exception. I have seen that Java-8 way of doing. Considering that 70% of the current applications still run on Java-7 I am adding this answer.
Bottom Line For any mission critical applications, handling NPE is costly.
If efficiency is an issue then the 'catch' option should be considered.
If 'catch' cannot be used because it would propagate (as mentioned by 'SCouto') then use local variables to avoid multiple calls to methods getFoo(), getBar() and getBaz().
It's worth considering to create your own Exception. Let's call it MyOperationFailedException. You can throw it instead returning a value. The result will be the same - you'll quit the function, but you won't return hard-coded value -1 which is Java anti-pattern. In Java we use Exceptions.
try {
return wsObject.getFoo().getBar().getBaz().getInt();
} catch (NullPointerException ignored) {
throw new MyOperationFailedException();
}
EDIT:
According to the discussion in comments let me add something to my previous thoughts. In this code there are two possibilities. One is that you accept null and the other one is, that it is an error.
If it's an error and it occurs, You can debug your code using other structures for debugging purposes when breakpoints aren't enough.
If it's acceptable, you don't care about where this null appeared. If you do, you definitely shouldn't chain those requests.
The method you have is lengthy, but very readable. If I were a new developer coming to your code base I could see what you were doing fairly quickly. Most of the other answers (including catching the exception) don't seem to be making things more readable and some are making it less readable in my opinion.
Given that you likely don't have control over the generated source and assuming you truly just need to access a few deeply nested fields here and there then I would recommend wrapping each deeply nested access with a method.
private int getFooBarBazInt() {
if (wsObject.getFoo() == null) return -1;
if (wsObject.getFoo().getBar() == null) return -1;
if (wsObject.getFoo().getBar().getBaz() == null) return -1;
return wsObject.getFoo().getBar().getBaz().getInt();
}
If you find yourself writing a lot of these methods or if you find yourself tempted to make these public static methods then I would create a separate object model, nested how you would like, with only the fields you care about, and convert from the web services object model to your object model.
When you are communicating with a remote web service it is very typical to have a "remote domain" and an "application domain" and switch between the two. The remote domain is often limited by the web protocol (for example, you can't send helper methods back and forth in a pure RESTful service and deeply nested object models are common to avoid multiple API calls) and so not ideal for direct use in your client.
For example:
public static class MyFoo {
private int barBazInt;
public MyFoo(Foo foo) {
this.barBazInt = parseBarBazInt();
}
public int getBarBazInt() {
return barBazInt;
}
private int parseFooBarBazInt(Foo foo) {
if (foo() == null) return -1;
if (foo().getBar() == null) return -1;
if (foo().getBar().getBaz() == null) return -1;
return foo().getBar().getBaz().getInt();
}
}
return wsObject.getFooBarBazInt();
by applying the the Law of Demeter,
class WsObject
{
FooObject foo;
..
Integer getFooBarBazInt()
{
if(foo != null) return foo.getBarBazInt();
else return null;
}
}
class FooObject
{
BarObject bar;
..
Integer getBarBazInt()
{
if(bar != null) return bar.getBazInt();
else return null;
}
}
class BarObject
{
BazObject baz;
..
Integer getBazInt()
{
if(baz != null) return baz.getInt();
else return null;
}
}
class BazObject
{
Integer myInt;
..
Integer getInt()
{
return myInt;
}
}
Giving answer which seems different from all others.
I recommend you to check for NULL in ifs.
Reason :
We should not leave a single chance for our program to be crashed.
NullPointer is generated by system. The behaviour of System
generated exceptions can not be predicted. You should not leave your
program in the hands of System when you already have a way of handling
it by your own. And put the Exception handling mechanism for the extra safety.!!
For making your code easy to read try this for checking the conditions :
if (wsObject.getFoo() == null || wsObject.getFoo().getBar() == null || wsObject.getFoo().getBar().getBaz() == null)
return -1;
else
return wsObject.getFoo().getBar().getBaz().getInt();
EDIT :
Here you need to store these values wsObject.getFoo(),
wsObject.getFoo().getBar(), wsObject.getFoo().getBar().getBaz() in
some variables. I am not doing it because i don't know the return
types of that functions.
Any suggestions will be appreciated..!!
I wrote a class called Snag which lets you define a path to navigate through a tree of objects. Here is an example of its use:
Snag<Car, String> ENGINE_NAME = Snag.createForAndReturn(Car.class, String.class).toGet("engine.name").andReturnNullIfMissing();
Meaning that the instance ENGINE_NAME would effectively call Car?.getEngine()?.getName() on the instance passed to it, and return null if any reference returned null:
final String name = ENGINE_NAME.get(firstCar);
It's not published on Maven but if anyone finds this useful it's here (with no warranty of course!)
It's a bit basic but it seems to do the job. Obviously it's more obsolete with more recent versions of Java and other JVM languages that support safe navigation or Optional.
So our project back-end is a Java 8 Springboot application, springboot allows you to do some stuff really easily. ex, request validation:
class ProjectRequestDto {
#NotNull(message = "{NotNull.DotProjectRequest.id}")
#NotEmpty(message = "{NotEmpty.DotProjectRequest.id}")
private String id;
}
When this constraint is not meet, spring (springboot?) actually throws a validation exception, as such, we catch it somewhere in the application and construct a 404 (Bad Request) response for our application.
Now, given this fact, we kinda followed the same philosophy throughout our application, that is, on a deeper layer of the application we might have something like:
class ProjectService throws NotFoundException {
DbProject getProject(String id) {
DbProject p = ... // some hibernate code
if(p == null) {
Throw new NotFoundException();
}
return p;
}
}
And again we catch this exception on a higher level, and construct another 404 for the client.
Now, this is causing a few problems:
The most important one: Our error tracing stops being useful, we cannot differentiate (easily) when the exception is important, because they happen ALL the time, so if the service suddenly starts throwing errors we would not notice until it is too late.
Big amount of useless logging, on login requests for example, user might mistyped his password, and we log this and as a minor point: our analytics cannot help us determine what we are actually doing wrong, we see a lot of 4xx's but that is what we expect.
Exceptions are costly, gathering the stack trace is a resource intensive task, minor point at this moment, as the service scales up with would become more of a problem.
I think the solution is quite clear, we need to make an architectural change to not make exceptions part of our normal data flow, however this is a big change and we are short on time, so we plan to migrate over time, yet the problem remains for the short term.
Now, to my actual question: when I asked one of our architects, he suggested the use of monads (as a temporal solution ofc), so we don't modify our architecture, but tackle the most contaminating endpoints (ex. wrong login) in the short term, however I'm struggling with the monad paradigm overall and even more in java, I really have no idea on how to apply it to our project, could you help me with this? some code snippets would be really good.
TL:DR: If you take a generic spring boot application that throws errors as a part of its data flow, how can you apply the monad pattern to avoid login unnecessary amount of data and temporarily fix this Error as part of data flow architecture.
The standard monadic approach to exception handling is essentially to wrap your result in a type that is either a successful result or an error. It's similar to the Optional type, though here you have an error value instead of an empty value.
In Java the simplest possible implementation is something like the following:
public interface Try<T> {
<U> Try<U> flatMap(Function<T, Try<U>> f);
class Success<T> implements Try<T> {
public final T value;
public Success(T value) {
this.value = value;
}
#Override
public <U> Try<U> flatMap(Function<T, Try<U>> f) {
return f.apply(value);
}
}
class Fail<T> implements Try<T> {
// Alternatively use Exception or Throwable instead of String.
public final String error;
public Fail(String error) {
this.error = error;
}
#Override
public <U> Try<U> flatMap(Function<T, Try<U>> f) {
return (Try<U>)this;
}
}
}
(with obvious implementations for equals, hashCode, toString)
Where you previously had operations that would either return a result of type T or throw an exception, they would return a result of Try<T> (which would either be a Success<T> or a Fail<T>), and would not throw, e.g.:
class Test {
public static void main(String[] args) {
Try<String> r = ratio(2.0, 3.0).flatMap(Test::asString);
}
static Try<Double> ratio(double a, double b) {
if (b == 0) {
return new Try.Fail<Double>("Divide by zero");
} else {
return new Try.Success<Double>(a / b);
}
}
static Try<String> asString(double d) {
if (Double.isNaN(d)) {
return new Try.Fail<String>("NaN");
} else {
return new Try.Success<String>(Double.toString(d));
}
}
}
I.e. instead of throwing an exception you return a Fail<T> value which wraps the error. You can then compose operations which might fail using the flatMap method. It should be clear that once an error occurs it will short-circuit any subsequent operations - in the above example if ratio returns a Fail then asString doesn't get called and the error propagates directly through to the final result r.
Taking your example, under this approach it would look like this:
class ProjectService throws NotFoundException {
Try<DbProject> getProject(String id) {
DbProject p = ... // some hibernate code
if(p == null) {
return new Try.Fail<DbProject>("Failed to create DbProject");
}
return new Try.Succeed<DbProject>(p);
}
}
The advantage over raw exceptions is it's a bit more composable and allows, for example, for you to map (e.g. Stream.map) a fail-able function over a collection of values and end up with a collection of Fails and Successes. If you were using exceptions then the first exception would fail the entire operation and you would lose all results.
One downside is that you have to use Try return types all the way down your call stack (somewhat like checked exceptions). Another is that since Java doesn't have built-in monad support (al la Haskell & Scala) then the flatMap'ing can get slightly verbose. For example something like:
try {
A a = f(x);
B b = g(a);
C c = h(b);
} catch (...
where f, g, h might throw, becomes instead:
Try<C> c = f(x).flatMap(a -> g(a))
.flatMap(b -> h(b));
You can generalise the above implementation by making the error type an generic parameter E (instead of String), so it then becomes Try<T, E>. whether this is useful depends on your requirements - I've never needed it.
I have a more fully-implemented version here, alternatively the Javaslang and FunctionalJava libraries offer their own variants.
Some words to introduce the situation.
Context: To ease my workflow while writing Bukkit plugins (the basically de-facto API for the Minecraft Server until Sponge gets it's implementation going), I've decided to put together a "mini-framework" for myself to not have to repeat the same tasks over and over again. (Also, I'm trying to design it to not depend too much on Bukkit, so I can continue using it on Sponge by just changing my implementation)
Intention: Command handling in Bukkit is, frankly, a mess. You have to define your root command (for example, you want to run /test ingame, "test" is the root) in a YML file (instead of calling some sort of factory?), child command handling is nonexistant and implementation details is hidden so producing 100% reliable results is hard. It's the only part of Bukkit that has annoyed me, and it was the main initiator of me deciding to write a framework.
Goal: Abstract away the nasty Bukkit command handling, and replace it with something that's clean.
Working towards it:
This is going to be the long paragraph where I'm going to explain how Bukkit command handling is originally implemented, as that will give a deeper understanding of important command parameters and such.
Any user connected to a Minecraft server can start a chat message with '/', which will result in it being parsed as a command.
To offer an example situation, any player in Minecraft has a life bar, which defaults to capping at 10 hearts, and depletes when taking damage. The maximum and current "hearts" (read: health) may be set by the server at any time.
Lets say we want to define a command like this:
/sethealth <current/maximum> <player or * for all> <value>
To start implementing this...oh boy. If you like clean code, I'd say skip this...I'll comment to explain, and whenever I feel like Bukkit did a mistake.
The mandatory plugin.yml:
# Full name of the file extending JavaPlugin
# My best guess? Makes lazy-loading the plugin possible
# (aka: just load classes that are actually used by replacing classloader methods)
main: com.gmail.zkfreddit.sampleplugin.SampleJavaPlugin
# Name of the plugin.
# Why not have this as an annotation on the plugin class?
name: SamplePlugin
# Version of the plugin. Why is this even required? Default could be 1.0.
# And again, could be an annotation on the plugin class...
version: 1.0
# Command section. Instead of calling some sort of factory method...
commands:
# Our '/sethealth' command, which we want to have registered.
sethealth:
# The command description to appear in Help Topics
# (available via '/help' on almost any Bukkit implementation)
description: Set the maximum or current health of the player
# Usage of the command (will explain later)
usage: /sethealth <current/maximum> <player/* for all> <newValue>
# Bukkit has a simple string-based permission system,
# this will be the command permission
# (and as no default is specified,
# will default to "everybody has it")
permission: sampleplugin.sethealth
The main plugin class:
package com.gmail.zkfreddit.sampleplugin;
import org.bukkit.command.PluginCommand;
import org.bukkit.plugin.java.JavaPlugin;
public class SampleJavaPlugin extends JavaPlugin {
//Called when the server enables our plugin
#Override
public void onEnable() {
//Get the command object for our "sethealth" command.
//This basically ties code to configuration, and I'm pretty sure is considered bad practice...
PluginCommand command = getCommand("sethealth");
//Set the executor of that command to our executor.
command.setExecutor(new SampleCommandExecutor());
}
}
The command executor:
package com.gmail.zkfreddit.sampleplugin;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
public class SampleCommandExecutor implements CommandExecutor {
private static enum HealthOperationType {
CURRENT,
MAXIMUM;
public void executeOn(Player player, double newHealth) {
switch (this) {
case CURRENT:
player.setHealth(newHealth);
break;
case MAXIMUM:
player.setMaxHealth(newHealth);
break;
}
}
}
#Override
public boolean onCommand(
//The sender of the command - may be a player, but might also be the console
CommandSender commandSender,
//The command object representing this command
//Why is this included? We know this is our SetHealth executor,
//so why add this as another parameter?
Command command,
//This is the "label" of the command - when a command gets registered,
//it's name may have already been taken, so it gets prefixed with the plugin name
//(example: 'sethealth' unavailable, our command will be registered as 'SamplePlugin:sethealth')
String label,
//The command arguments - everything after the command name gets split by spaces.
//If somebody would run "/sethealth a c b", this would be {"a", "c", "b"}.
String[] args) {
if (args.length != 3) {
//Our command does not match the requested form {"<current/maximum>", "<player>", "<value>"},
//returning false will, ladies and gentleman...
//display the usage message defined in plugin.yml. Hooray for some documented code /s
return false;
}
HealthOperationType operationType;
double newHealth;
try {
//First argument: <current/maximum>
operationType = HealthOperationType.valueOf(args[0].toUpperCase());
} catch (IllegalArgumentException e) {
return false;
}
try {
//Third argument: The new health value
newHealth = Double.parseDouble(args[2]);
} catch (NumberFormatException e) {
return false;
}
//Second argument: Player to operate on (or all)
if (args[1].equalsIgnoreCase("*")) {
//Run for all players
for (Player player : Bukkit.getOnlinePlayers()) {
operationType.executeOn(player, newHealth);
}
} else {
//Run for a specific player
Player player = Bukkit.getPlayerExact(args[1]);
if (player == null) {
//Player offline
return false;
}
operationType.executeOn(player, newHealth);
}
//Handled successfully, return true to not display usage message
return true;
}
}
Now you may understand why I'm choosing to abstract the command handling away in my framework. I don't think I'm alone in thinking that this way is not self-documenting and handling child commands this way does not feel right.
My Intention:
Similiar to how the Bukkit Event System works, I want to develop a framework/API to abstract this away.
My idea is annotating command methods with a respective annotation that includes all neccassary information, and use some sort of registerer (in the event case: Bukkit.getPluginManager().registerEvents(Listener, Plugin)) to register the command.
Again similiar to the Event API, command methods would have a definied signature. As dealing with multiple parameters is annoying, I decided to pack it all in a context interface (also, this way I do not break all previous code in case I need to add something to the context!). However, I also needed a return type in case I want to display the usage quickly (but I'm not going to pick a boolean, that's for sure!), or do some other stuff. So, my idea signature boils down to CommandResult <anyMethodName>(CommandContext).
The command registration would then create the command instances for annotated methods and register them.
My basic outline took form. Note that I haven't came around to writing JavaDoc yet, I added some quick comments on not self-documenting code.
Command registration:
package com.gmail.zkfreddit.pluginframework.api.command;
public interface CommandRegistration {
public static enum ResultType {
REGISTERED,
RENAMED_AND_REGISTERED,
FAILURE
}
public static interface Result {
ResultType getType();
//For RENAMED_AND_REGISTERED
Command getConflictCommand();
//For FAILURE
Throwable getException();
//If the command got registered in some way
boolean registered();
}
Result register(Object commandObject);
}
The command result enumeration:
package com.gmail.zkfreddit.pluginframework.api.command;
public enum CommandResult {
//Command executed and handlded
HANDLED,
//Show the usage for this command as some parameter is wrong
SHOW_USAGE,
//Possibly more?
}
The command context:
package com.gmail.zkfreddit.pluginframework.api.command;
import org.bukkit.command.CommandSender;
import java.util.List;
public interface CommandContext {
CommandSender getSender();
List<Object> getArguments();
#Deprecated
String getLabel();
#Deprecated
//Get the command annotation of the executed command
Command getCommand();
}
The main command annotation to be put on command methods:
package com.gmail.zkfreddit.pluginframework.api.command;
import org.bukkit.permissions.PermissionDefault;
public #interface Command {
public static final String DEFAULT_STRING = "";
String name();
String description() default DEFAULT_STRING;
String usageMessage() default DEFAULT_STRING;
String permission() default DEFAULT_STRING;
PermissionDefault permissionDefault() default PermissionDefault.TRUE;
Class[] autoParse() default {};
}
The autoParse intention is that I can define something quick, and if parsing fails, it just displays the usage message of the command.
Now, once I have my implementation written up, I can rewrite the mentioned "sethealth" command executor to something like this:
package com.gmail.zkfreddit.sampleplugin;
import de.web.paulschwandes.pluginframework.api.command.Command;
import de.web.paulschwandes.pluginframework.api.command.CommandContext;
import org.bukkit.entity.Player;
import org.bukkit.permissions.PermissionDefault;
public class BetterCommandExecutor {
public static enum HealthOperationType {
CURRENT,
MAXIMUM;
public void executeOn(Player player, double newHealth) {
switch (this) {
case CURRENT:
player.setHealth(newHealth);
break;
case MAXIMUM:
player.setMaxHealth(newHealth);
break;
}
}
}
#Command(
name = "sethealth",
description = "Set health values for any or all players",
usageMessage = "/sethealth <current/maximum> <player/* for all> <newHealth>",
permission = "sampleplugin.sethealth",
autoParse = {HealthOperationType.class, Player[].class, Double.class} //Player[] as there may be multiple players matched
)
public CommandResult setHealth(CommandContext context) {
HealthOperationType operationType = (HealthOperationType) context.getArguments().get(0);
Player[] matchedPlayers = (Player[]) context.getArguments().get(1);
double newHealth = (Double) context.getArguments().get(2);
for (Player player : matchedPlayers) {
operationType.executeOn(player, newHealth);
}
return CommandResult.HANDLED;
}
}
I believe I speak for most here that this way feels cleaner.
So where am I asking a question here?
Where I'm stuck.
Child command handling.
In the example, I was able to get away with a simple enum based on the two cases for the first argument.
There may be cases where I have to create a lot of child commands similiar to "current/maximum". A good example may be something that handles joining players together as a team - I would need:
/team create ...
/team delete ...
/team addmember/join ...
/team removemember/leave ...
etc. - I want to be able to create seperate classes for these child commands.
How exactly am I going to introduce a clean way to say "Hey, when the first argument of this matches something, do this and that!" - heck, the "matched" part doesn't even have to be a hardcoded String, I may want something like
/team [player] info
at the same time, while still matching all the previous child commands.
Not only do I have to link to child command methods, I also have to somehow link the required object - after all, my (future) command registration will take an instantiated object (in the example case, of BetterCommandExecutor) and register it. How will I tell "Use this child command instance!" to the registration when passing in the object?
I have been thinking about saying "**** everything, link to a child command class and just instantiate the no-args constructor of it", but while this would probaly procude the least code, it would not give much insight into how exactly child command instances get created. If I do decide to go that way, I'll probaly just define a childs parameter in my Command annotation, and make it take some sort of #ChildCommand annotation list (annotations in annotations? Yo dawk, why not?).
So after all this, the question is: With this setup, is there a way I will be able to cleanly define child commands, or will I have to change my footing completely? I thought about extending from some sort of abstract BaseCommand (with an abstract getChildCommands() method), but the annotation method has the advantage of being able to handle multiple commands from one class. Also, as far as I have picked up open-source code until now, I get the impression that extends is 2011 and implements is the flavour of the year, so I should probaly not force myself to extend something every time I'm creating some sort of command handler.
I am sorry for the long post. This went longer than I expected :/
Edit #1:
I've just realized what I am basically creating is some sort of...tree? of commands. However, just simply using some sort of CommandTreeBuilder falls away as it goes against one of the things I wanted from this idea: Being able to define multiple command handlers in one class. Back to brainstorming.
The only thing I can think of is splitting your annotations up. You would have one class that has the Base Command as an annotation and then methods in that class with the different sub commands:
#Command("/test")
class TestCommands {
#Command("sub1"// + more parameters and stuff)
public Result sub1Command(...) {
// do stuff
}
#Command("sub2"// + more parameters and stuff)
public Result sub2Command(...) {
// do stuff
}
}
If you want more flexibility you could also take the inheritance hierarchy into account, but I'm not sure how self-documenting that would be then (since part of the commands would be hidden away in parent classes).
This solution does not solve your /team [player] info example though, but I think that is a minor thing. It'd be confusing anyway to have subcommands show up in different parameters of your command.
The standard Bukkit API for command handling is pretty good in my opinion, so why not to use it?
I think you are just confused, then you avoid it.
Here is how I do.
Register the command
Create a new section called commands, where you will put all them as child nodes.
commands:
sethealth:
Avoid using the permission key: we will check that later.
Avoid using the usage key: it is difficult to write a great error message valid in each case.
In general, I hate these sub keys, so leave the parent node empty.
Handle it on its own class
Use a separate class which implements the CommandExecutor interface.
public class Sethealth implements CommandExecutor {
#Override
public boolean onCommand(CommandSender sender, Command command, String alias, String[] args) {
// ...
return true;
}
}
Add the following under the onEnable() method in the main class.
getCommand("sethealth").setExecutor(new Sethealth());
You do not need to check for command.getName() if you use this class only for this command.
Make the method return true in any case: you have not defined the error message, so why should you get it?
Make it safe
You will no longer need to worry about if you process sender at the first line.
Also, you may check any generic permissions here.
if (!(sender instanceof Player)) {
sender.sendMessage("You must be an in-game player.");
return true;
}
Player player = (Player)sender;
if (!player.hasPermission("sethealth.use")) {
player.sendMessage(ChatColor.RED + "Insufficient permissions.");
return true;
}
// ...
You can use colors to make messages more readable.
Dealing with arguments
It is simple to produce 100% reliable results.
This is just an incomplete example on how you should work.
if (args.length == 0) {
player.sendMessage(ChatColor.YELLOW + "Please specify the target.");
return true;
}
Player target = Server.getPlayer(args[0]);
if (target == null) {
player.sendMessage(ChatColor.RED + "Target not found.");
return true;
}
if (args.length == 1) {
player.sendMessage(ChatColor.YELLOW + "Please specify the new health.");
return true;
}
try {
double value = Double.parseDouble(args[1]);
if (value < 0D || value > 20D) {
player.sendMessage(ChatColor.RED + "Invalid value.");
return true;
}
target.setHealth(value);
player.sendMessage(ChatColor.GREEN + target.getName() + "'s health set to " + value + ".");
} catch (NumberFormatException numberFormat) {
player.sendMessage(ChatColor.RED + "Invalid number.");
}
Plan your code using guard clauses and if you want sub commands, always check them with String.equalsIgnoreCase(String).
How is it possible, to improve your logging mechanism, by not having the overhead of string concatenations?
Consider the following example:
import java.util.logging.Level;
import java.util.logging.Logger;
public class LoggerTest {
public static void main(String[] args) {
// get logger
Logger log = Logger.getLogger(LoggerTest.class.getName());
// set log level to INFO (so fine will not be logged)
log.setLevel(Level.INFO);
// this line won't log anything, but will evaluate the getValue method
log.fine("Trace value: " + getValue());
}
// example method to get a value with a lot of string concatenation
private static String getValue() {
String val = "";
for (int i = 0; i < 1000; i++) {
val += "foo";
}
return val;
}
}
The log method log.fine(...) will not log anything, because the log level is set to INFO. The problem is, that the method getValue will be evaluated anyway.
And this is a big performance issue in big applications with a lot of debug statements.
So, how to solve this problem?
Since Java8 it is possible to use the new introduced lambda expressions for this scenario.
Here is a modified example of the logging:
LoggerTest.class
import java.util.logging.Level;
import java.util.logging.Logger;
public class LoggerTest {
public static void main(String[] args) {
// get own lambda logger
LambdaLogger log = new LambdaLogger(LoggerTest.class.getName());
// set log level to INFO (so fine will not be logged)
log.setLevel(Level.INFO);
// this line won't log anything, and will also not evaluate the getValue method!
log.fine(()-> "Trace value: " + getValue()); // changed to lambda expression
}
// example method to get a value with a lot of string concatenation
private static String getValue() {
String val = "";
for (int i = 0; i < 1000; i++) {
val += "foo";
}
return val;
}
}
LambdaLogger.class
import java.util.concurrent.Callable;
import java.util.logging.Level;
import java.util.logging.Logger;
public class LambdaLogger extends Logger {
public LambdaLogger(String name) {
super(name, null);
}
public void fine(Callable<String> message) {
// log only, if it's loggable
if (isLoggable(Level.FINE)) {
try {
// evaluate here the callable method
super.fine(message.call());
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
With this modification you can improve the performance of your applications a lot, if you have many log statements, which are only for debugging purposes.
Of course you can use any Logger you want. This is only an example of the java.util.Logger.
#bobbel has explained how to do it.
I'd like to add that while this represents a performance improvement over your original code, the classic way of dealing with this is still faster:
if (log.isLoggable(Level.FINE)) {
log.fine("Trace value: " + getValue());
}
and only marginally more verbose / wordy.
The reason it is faster is that the lambda version has the additional runtime overheads of creating the callable instance (capture cost), and an extra level of method calls.
And finally, there is the issue of creating the LambdaLogger instances. #bobbel's code shows this being done using a constructor, but in reality java.util.logging.Logger objects need to be created by a factory method to avoid proliferation of objects. That implies a bunch of extra infrastructure (and code changes) to get this to work with a custom subclass of Logger.
Apparently Log4j 2.4 includes support for lambda expressions which are exactly useful for your case (and which other answers have replicated manually):
From https://garygregory.wordpress.com/2015/09/16/a-gentle-introduction-to-the-log4j-api-and-lambda-basics/
// Uses Java 8 lambdas to build arguments on demand
logger.debug("I am logging that {} happened.", () -> compute());
Just create wrapper methods for your current logger as:
public static void info(Logger logger, Supplier<String> message) {
if (logger.isLoggable(Level.INFO))
logger.info(message.get());
}
and use it:
info(log, () -> "x: " + x + ", y: " + y);
Reference: JAVA SE 8 for the Really Impatient eBook, pages 48-49.
use a format String, and an array of Supplier<String>. this way no toString methods are called unless the the log record is actually publishable. this way you dont have to bother with ugly if statements about logging in application code.
Does anyone know if there is a way to generate different code in the catch block automatically depending on the exception?
The Eclipse function 'Surround with try/catch' generates a try/catch block which just includes dumping a stack trace.
I'm doing a bunch of similar things in the code and so most of my exceptions will boil down to probably three or so different types. I'd like to have different catch block code for each one and have eclipse auto format based on the exception.
For example:
if my code generates a RemoteConnectionException I'd like to display a dialog to the user to reconnect.
If it generates a RemoteContentException I'd like to log it.
(I made these up.)
Thanks in advance
UPDATE:
I've been poking around and have two potential solutions.
1) I've found something called the fast code plugin which might do what I'm looking for.
http://fast-code.sourceforge.net/index.htm
2) For specifically handling exceptions I'll probably just write a generic exception handler and modify the catch block code to pass the exception to that instead of printing the stack trace. Then the java code will determine which action to take based on exception type.
Templating has it's limits. However your problem can be solved very elegantly with Aspect. ( http://www.eclipse.org/aspectj/ ) Just create a new annotation for every type of "template-case" you need and use an around advice.
Ps: don't use printStackTrace() to syserr/sysout. There are so many production grade, lightweight logging frameworks.... pleeeaseee... don't abuse poor little System.out/err :)
EDIT:
Some example for a logging / benchmarking advice. (note: I'm using spring AOP for aspects, and lombok for easy access to the logging framework. The getCurrentUser() code is not really relevant here, it's just for getting the current user from Spring Security)
package com.XXXXXXXX.aspects;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
#Component
#Aspect
#Slf4j
public class LoggerAspect {
private final static String DOMAIN = "XXXXXXXX";
private static String getCurrentUser() {
String username = "Unknown";
try {
Object principal = SecurityContextHolder.getContext().
getAuthentication().
getPrincipal();
if (principal instanceof UserDetails) {
username = ((UserDetails) principal).getUsername();
} else {
username = principal.toString();
}
} catch (Exception e) {
}
return username;
}
#Pointcut("within(com.XXXXXXXX.services..*)")
public void inServiceLayer() {
}
#Pointcut("execution(* getMatcherInfo(..)) || execution(* resetCounter(..))")
public void notToAdvise() {
}
#Around("com.XXXXXXXX.aspects.LoggerAspect.inServiceLayer() && !com.XXXXXXXX.aspects.LoggerAspect.notToAdvise()")
public Object doLogging(ProceedingJoinPoint pjp)
throws Throwable {
long start = System.nanoTime();
StringBuilder sb = new StringBuilder(DOMAIN);
sb.append('/').
append(getCurrentUser()).
append(" accessing ").
append(pjp.getSignature().
getDeclaringTypeName()).
append('.').
append(pjp.getSignature().
getName());
log.trace("START: " + sb.toString());
Object retVal = pjp.proceed(pjp.getArgs());
long duration = System.nanoTime() - start;
log.trace("STOP: " + duration / 1000000 + " msec. " + sb.toString());
return retVal;
}
}
I'm not sure if there is such an option available in eclipse. I've been using the surround with try/catch option for quite sometime now and it always dumps the default e.printStackTrace() line in the catch block for the Exception e.