Guice provides a way to bind to provider:
bind(A.class).toProvider(AProvider.class);
Although if my provider needs to throw an exception then it seems that CheckedProvider is a right base interface:
public interface ConfigCheckedProvider<T> extends CheckedProvider<T> {
T get() throws ConfigException;
}
public AProvider implements ConfigCheckedProvider<A> { ... }
But now some of my classes need instance of A to be injected. And this I can't change. But it looks like toProvider method doesn't accept CheckedProvider types.
How I can use providers based on CheckedProvider to inject instances not providers?
As you requested, I'm posting my comment as an answer.
If you have a class T and a checked provider TProvider extends CheckedProvider<T>, you cannot inject just T:
#Inject
SomeClass(T t) { // Won't work
...
}
as you would be able if you had used plain Provider<T>. This is done intentionally. Checked providers are needed when creation of an object may fail with a particular type of exception, and this failure must be handled by user code. Plain providers do not have such feature.
Provider<T> does not allow throwing checked exceptions from its get() method, and any unchecked exceptions it throws may be wrapped into a ProvisionException, so you cannot reliably catch your exception. Also, if you inject T directly and your provider's get() method fails, then you will get an error during the injection, which may lead to incomprehensible stacktraces (especially if you are not using Injectors directly) or even their absence.
Checked providers allow you to throw predeclared types of exceptions from your providers, and these exceptions are guaranteed to be passed as is to the code which calls get() on your checked provider. This way you can reliably catch them, but in return you lose an ability to inject objects which are created by the provider directly.
See this manual on throwing and checked providers for more background on what I just have written.
It's clear that what I'm asked for is intentionally not provided in guice. However the one might write his own checked provider which will implement Provider and therefore usable in toProvider bindings.
For example I have provided in question the following Checked Provider might make sense:
public abstract class MyCheckedProvider<T, E extends Exception>
implements Provider<T> {
public abstract T getChecked() throws E;
#Override
public T get() {
try {
return getChecked();
} catch (Exception e) {
throw new ProvisionException("Checked provider threw exception", e );
}
}
}
With this MyProvider the AProvider might look like:
public class AProvider extends MyCheckedProvider<A, ConfigException> {
#Override
public A getChecked() throws ConfigException {
...
}
}
bind(A.class).toProvider(AProvider.class);
All this works only if you want to throw ProvisionExceptions if something goes wrong in provider. For other logic MyProvider should obviously have other implmentation of get method...
Related
Let's say I have a class as below, as the class name suggests, this class doesn't allow auto commit.
So my question is that if it is better to leave it like below (empty body, maybe add some logging #WARN/ERROR level) or to throw UnsupportedOperationException?
public class NoAutoCommitConnection implements java.sql.Connection {
public void setAutoCommit(boolean autoCommit) throws SQLException {
}
}
I would actually go with if(autoCommit) { throw new UnsupportedOperationException(); }, since it clearly communicates that auto commiting is not supported, but won't fail setAutoCommit(false) calls.
Not implementing the method or rather it's intention breaks the contract of the interface.
I think the least you can do in such a situation is to throw an exception at runtime.
In a flow I've designed, I have a Validation component with a custom validator that references a class, DataValidator, implementing the mule Validator interface. In the DataValidator, I validate several properties and would like to throw different kinds of exceptions (possibly custom exceptions, created by me) for each one. Is this possible?
My understanding is that, by specifying the exceptionClass, the Validation component will only throw exceptions of that class.
There's the option to use an ExceptionFactory instead of an exceptionClass.
Does using it allows throwing several types of exception? If so, how can I use it? I checked this blog
post, but didn't understand it well enough.
In the case that none of this is possible, is there any way I can get the ValidationResult message in the custom validator component, so that I can use it in the message?
Yes you can throw several types of exceptions. As you mentioned, you'll have to implement the DataValidator and ExceptionFactory interface and configure your component to use them.
With Studio, choose "Use Exception Factory Config" and specify the full class name you want to use. With XML, specify the exception-factory you implemented in your validation-config. (You can also configure a Spring Bean and reference it):
<validation:config name="Validation_Configuration" doc:name="Validation Configuration">
<validation:exception-factory class="com.mycomp.validation.MyExceptionFactory"/>
</validation:config>
In your flow configure acustom-validator and reference your configuration with exception factory, your validator implementation and the type of exception you want to throw with exceptionClass. To be able to throw any kind of Exception, specify java.lang.Exception or a class from which the custom exceptions you'll want to use can inherit:
<flow name="validation-exceptionFlow">
...
<validation:custom-validator
config-ref="Validation_Configuration"
class="com.mycomp.validation.MyValidator"
exceptionClass="java.lang.Exception"
doc:name="Validation" />
...
</flow>
Depending on your need you may want to specify exceptionClass differently, the idea being that your actual exceptions should extend it.
Yout ExceptionFactory implementation is then up to you. You can return whatever exception you want... For example:
public class MyExceptionFactory implements ExceptionFactory{
#Override
public <T extends Exception> T createException(ValidationResult result, Class<T> exceptionClass, MuleEvent event) {
return (T) createException(result, exceptionClass.getCanonicalName(), event);
}
#Override
public Exception createException(ValidationResult result, String exceptionClassName, MuleEvent event) {
//...
//some logic to identify which kind of exception you want to throw
//from result and event
//...
if(something) {
return new SomeException("Something happened");
} else if (somethingElse) {
return new AnotherException("I am en error...");
} else {
return new BananaException("Ook");
}
}
}
It appears the interface has two methods, one returning a generic and the other a plain Exception. Not knowing the specific usage of your ExceptionFactory I won't be able to provide much guidance, but be aware that Mule may call any of these methods, and the doc provides some requirements:
The above interface receives the Event that was rejected by the
validation and the validator that raised the error. This method is
intended to return the exception to be thrown but not to throw it.
Implementations of this interface should never throw exceptions. They
should also be thread-safe and have a public default constructor. See
Also
Suppose I've got an endpoint in Dropwizard, say
#GET
public Response foo() { throw new NullPointerException(); }
When I hit this endpoint it logs the exception and everything, which is great! I love it. What I love less is that it returns a big status object to the user with status: ERROR (which is fine) as well as a gigantic stack trace, which I'm less excited about.
Obviously it's best to catch and deal with exceptions on my own, but from time to time they're going to slip through. Writing a try catch block around the entire resource every time is fine, but (a) it's cumbersome, and (b) I always prefer automated solutions to "you have to remember" solutions.
So what I would like is something that does the following:
Logs the stack trace (I use slf4j but I assume it would work for whatever)
Returns a general purpose error response, which does not expose potentially privileged information about my server!
I feel like there must be a built-in way to do this -- it already handles exceptions in a relatively nice way -- but searching the docs hasn't turned up anything. Is there a good solution for this?
As alluded to by reek in the comments, the answer is an ExceptionMapper. You'll need a class like this:
#Provider
public class RuntimeExceptionMapper implements ExceptionMapper<RuntimeException> {
#Override
public Response toResponse(RuntimeException runtime) {
// ...
}
}
You can do whatever logging or etc. you like in the toResponse method, and the return value is what is actually sent up to the requester. This way you have complete control, and should set up sane defaults -- remember this is for errors that slip through, not for errors you actually expect to see! This is also a good time to set up different behaviors depending on what kind of exceptions you're getting.
To actually make this do anything, simply insert the following line (or similar) in the run method of your main dropwizard application:
environment.jersey().register(new RuntimeExceptionMapper());
where environment is the Environment parameter to the Application's run method. Now when you have an uncaught RuntimeException somewhere, this will trigger, rather than whatever dropwizard was doing before.
NB: this is still not an excuse not to catch and deal with your exceptions carefully!
Add the following to your yaml file. Note that it will remove all the default exception mappers that dropwizard adds.
server:
registerDefaultExceptionMappers: false
Write a custom exception mapper as below:
public class CustomExceptionMapper implements ExceptionMapper<RuntimeException> {
#Override
public Response toResponse(RuntimeException runtime) {
// ...
}
}
Then register the exception mapper in jersey:
environment.jersey().register(new CustomExceptionMapper());
Already mentioned this under the comments, but then thought I would give it a try with a use case.
Would suggest you to start differentiating the Exception that you would be throwing. Use custom exception for the failures you know and throw those with pretty logging. At the same RuntimeException should actually be fixed. Anyhow if you don't want to display stack trace to the end user you can probably catch a generic exception, log the details and customize the Response and entity accordingly.
You can define a
public class ErrorResponse {
private int code;
private String message;
public ErrorResponse() {
}
public ErrorResponse(int code, String message) {
this.code = code;
this.message = message;
}
... setters and getters
}
and then within you resource code you can modify the method as -
#GET
public Response foo() {
try {
...
return Response.status(HttpStatus.SC_OK).entity(response).build();
} catch (CustomBadRequestException ce) {
log.error(ce.printStackTrace());
return Response.status(HttpStatus.SC_BAD_REQUEST).entity(new ErrorResponse(HttpStatus.SC_BAD_REQUEST, ce.getMessage())).build();
} catch (Exception e) {
log.error(e.printStackTrace(e));
return Response.status(HttpStatus.SC_INTERNAL_SERVER_ERROR).entity(new ErrorResponse(HttpStatus.SC_INTERNAL_SERVER_ERROR, e.getMessage())).build();
}
}
This article details Checked and Unchecked Exceptions implementation for Jersey with customized ExceptionMapper:
https://www.codepedia.org/ama/error-handling-in-rest-api-with-jersey/
Official Dropwizard documentation also covers a simpler approach, just catching using WebApplicationException:
#GET
#Path("/{collection}")
public Saying reduceCols(#PathParam("collection") String collection) {
if (!collectionMap.containsKey(collection)) {
final String msg = String.format("Collection %s does not exist", collection);
throw new WebApplicationException(msg, Status.NOT_FOUND)
}
// ...
}
https://www.dropwizard.io/en/stable/manual/core.html#responses
It worked for me by simply registering the custom exception mapper created in the run method of the main class.
environment.jersey().register(new CustomExceptionMapper());
where CustomExceptionMapper can implement ExceptionMapper class like this
public class CustomExceptionMapperimplements ExceptionMapper<Exception>
I'm working on a simple plugin system, where third party plugins implement a Plugin interface. A directory of JARs is scanned, and the implementing classes are instantiated with Constructor#newInstance.
The thing is, these plugins call back into register* methods of the plugin host. These registrations use the Plugin instance as a handle. My problem is how to clean up these registrations if the constructor decides to fail and throw halfway through.
InvocationTargetException doesn't seem to have anything on it to get the instance. Is there a way to get at the instance of an exception throwing constructor?
P.S.: It's typically strongly advised to users that the constructor not do anything, but in practice people are doing it any ways.
What you are in effect asking is whether there is a way to get hold of the (partial) instance when a constructor throws an exception.
The answer is No. But it is not because the instance is "dead". In fact the reference to the instance could still be reachable and usable by other parts of the application ... if it has been "published" before the constructor completed.
The real reason is that neither creating or throwing an exception records the instance associated with the method or constructor doing the creating / throwing.
You will need to solve this some other way. My suggestion is you make it a rule that these plugin classes must only register the instance as the last statement of the constructor; i.e. when no more initialization-related exceptions could be thrown.
Is it possible to do the registration through a holder object which is then used for actual plugin registration after the plugin class has been constructed successfully? I'm thinking of something like this:
public class MyPlugin extends BasePlugin {
public MyPlugin(PluginRegistry registry) {
super(registry);
// here be things which may cause an exception
// to be thrown, among other things
}
}
public interface PluginRegistry {
// method(s) for registration
}
public class PluginRegistryHolder implements PluginRegistry {
// implementations of the required method(s) for registration
// also a method for getting temporary registration data from within the class
}
// Actual usage in your code
public void registerPlugin(final String className) {
PluginRegistryHolder h = new PluginRegistryHolder();
Constructor c = /* acquire correct constructor, omitted for clarity */
try {
Object o = c.newInstance(new Object[] {h});
this.actualRegistry.register(o, h.getRegistrationData());
} catch (Throwable t) { /* die */
}
}
So basically handle the registration gracefully and never let the plugin class register directly but instead through a managed proxy.
What is the best practice to follow when you need to throw an exception which was not defined in an interface that you are implementing?
Here is an example:
public interface Reader
{
public abstract void read() throws IOException;
}
public class CarrotReader implements Reader
{
public void read() throws IOException {}
}
public class CupcakeReader implements Reader
{
public void read() throws IOException, CupcakeException {}
}
In this case, you have a specific exception that occurs when reading cupcakes, so you want to throw an exception related to this. However, Reader doesn't define this type of exception in its interface, so what do you do? Furthermore, it doesn't make sense to add CupcakeException to the throws clause in the Reader interface, because this type of exception is specific to CupcakeReader. One way around this is to have Reader define read such that it throws some parent type, like Exception, but then you lose the context for the exception. What should you do in this situation? Thanks!
Another interesting situation that has been brought up involves an interface over which you have no control. In this case, what is the best way to indicate that a problem has occurred?
For illustrative purposes, here is another example:
public interface Reader
{
public abstract void read();
}
public class CupcakeReader implements Reader
{
public void read() throws CupcakeException {}
}
In this case, you cannot change Reader, but you want to indicate that a problem has occurred in CupcakeReader's read method.
You may have to create an exception of the expected type instead.
... catch(CupcakeException e) {
throw new IOException("The sky is falling", e);
}
Use something called ReaderException that will serve as the root interface of your exception hierarchy. ReaderException will also provides a link to other exceptions that get thrown due to lower level exceptions.
Exception is part of the interface. Define a generic parent for all your exceptions in the interface if you can redefine the interface.
You can also make CupcakeException a child of IOException.
Just don't use checked exceptions.
The example you showed is one of the reasons checked exceptions are bad.
The main reason though is that the user of your cupcake reader will have to handle your exception regardless of whether he is interested in it or not.
So instead of:
Value value = reader.read();
You are forcing him to do this:
Value value = null;
try {
value = reader.read();
} catch (Exception e) {
// now what??
}
value.doSomething(); // potential NPE here
Think which one is better, more readable and less error prone and just stop using checked exceptions.
EDIT:
I am surprised with the negative rating. Are there people who still think that checked exceptions are great? If so here are some references why you shouldn't use checked exceptions:
No modern framework uses checked exceptions (Spring, EJB3 etc)
Article with code examples here
StackOverflow topic
Effective Java (sections 58 and 59) - here
Perhaps you could make an abstract ReaderSpecificException class, put it in the Interface, and
subclass CupcakeException from this abstract class.
If you create a higher abstract exception that works as a base class for CupCakeException you don't bind the Reader Interface to a specific implementation like you would be doing if you added the CupCakeException to the Reader interface.
If you don't let one Exception inherit from another there is a constructor in the exception class that takes a throwable as second argument like Thorbjørn Ravn Andersen allready showed in his short code example. The enables you to generate a more abstract exception and every part of your code that needs to know more then just "there is an error" can look for the cause of the higher exception.