OSGi DS: Why are exceptions thrown by binding methods only logged? - osgi

Why is it spec to only log an exception thrown from a binding method?
I would expect that the component would not activate in this case.
How should exceptions thrown from binding methods be handled to ensure the component is set up correctly?

Just because the binding of a service reference throws an exception does not necessarily mean the component cannot be activated. Since the component is aware of the exception (after all, it's the binding method that threw it), it can be implemented in such a way that it can still be activated, e.g. by falling back on a default value or by providing limited services.
Binding methods should not throw any exception anyway, unlike activation methods that can make the activation fail.
Reference:
OSGi 112.5.7: "If a bind method throws an exception, SCR must log an error message containing the exception with the Log Service, if present, but the activation of the component configuration does not fail."

Related

Elmah logger not working in Web API with Simple Injector

In an ASP.NET Web API project, if you are using Simple Injector for dependency injection, it will register all controllers with this line of code:
container.RegisterWebApiControllers(
System.Web.Http.GlobalConfiguration.Configuration);
If you have Elmah logger in the same project, to access the logger you just use http://yourapp.com/elmah as shown here.
The problem is that Simple Injector thinks elmah is a controller and produces this error:
No registration for type ElmahController could be found.
I thought to configure Simple Injector to avoid construction if the type has elmah but I cannot figure out how.
What do I need to do to fix this?
Here is the full error:
No registration for type ElmahController could be found. Make sure ElmahController is registered, for instance by calling 'Container.Register();' during the registration phase. An implicit registration could not be made because Container.Options.ResolveUnregisteredConcreteTypes is set to 'false', which is now the default setting in v5. This disallows the container to construct this unregistered concrete type. For more information on why resolving unregistered concrete types is now disallowed by default, and what possible fixes you can apply, see https://simpleinjector.org/ructd.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: SimpleInjector.ActivationException: No registration for type ElmahController could be found. Make sure ElmahController is registered, for instance by calling 'Container.Register();' during the registration phase. An implicit registration could not be made because Container.Options.ResolveUnregisteredConcreteTypes is set to 'false', which is now the default setting in v5. This disallows the container to construct this unregistered concrete type. For more information on why resolving unregistered concrete types is now disallowed by default, and what possible fixes you can apply, see https://simpleinjector.org/ructd.
Source Error:
An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.
Stack Trace:
[ActivationException: No registration for type ElmahController could be found. Make sure ElmahController is registered, for instance by calling 'Container.Register();' during the registration phase. An implicit registration could not be made because Container.Options.ResolveUnregisteredConcreteTypes is set to 'false', which is now the default setting in v5. This disallows the container to construct this unregistered concrete type. For more information on why resolving unregistered concrete types is now disallowed by default, and what possible fixes you can apply, see https://simpleinjector.org/ructd. ]
SimpleInjector.Container.ThrowNotConstructableException(Type concreteType) +138
SimpleInjector.Container.ThrowMissingInstanceProducerException(Type type) +88
SimpleInjector.Container.GetInstanceForRootType(Type serviceType) +186
SimpleInjector.Container.GetInstance(Type serviceType) +82
System.Web.Mvc.DefaultControllerActivator.Create(RequestContext requestContext, Type controllerType) +64
[InvalidOperationException: An error occurred when trying to create a controller of type 'Elmah.Mvc.ElmahController'. Make sure that the controller has a parameterless public constructor.]
System.Web.Mvc.DefaultControllerActivator.Create(RequestContext requestContext, Type controllerType) +245
System.Web.Mvc.MvcHandler.ProcessRequestInit(HttpContextBase httpContext, IController& controller, IControllerFactory& factory) +267
System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object state) +77
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +970
System.Web.HttpApplication.ExecuteStepImpl(IExecutionStep step) +75
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +158
Ok I think I figured it out.
Some Notes
Since I have configured the container's lifestyle like this:
container.Options.DefaultScopedLifestyle = new AsyncScopedLifestyle();
I cannot use LifeStyle.Scoped when registering the ElmahController. The 2 other options are LifeStyle.Singleton and LifeStyle.Transient. We don't want LifeStyle.Singleton because numerous instances are needed, thus we have one option left which is LifeStyle.Transcient.
Solution
You need to register it with Simple Injector:
container.Register<Elmah.Mvc.ElmahController>(Lifestyle.Transient);
The line above will result in a different error:
The configuration is invalid. The following diagnostic warnings were reported:
-[Disposable Transient Component] ElmahController is registered as transient, but implements IDisposable.
To get rid of that error, I first checked to see if the Dispose method for ElmahController has anything useful. It turns out it simply derives from System.Web.Mvc.Controller and here is the Dispose method:
public void Dispose()
{
Dispose(true /* disposing */);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
}
Since it does nothing useful, it is fine if it is not called. Thus the following code is enough:
container.GetRegistration(typeof(Elmah.Mvc.ElmahController)).Registration
.SuppressDiagnosticWarning(
DiagnosticType.DisposableTransientComponent,
"No need to call dispose because it does nothing useful.");
The RegisterWebApiControllers extension method uses ASP.NET Web API's IAssembliesResolver abstraction to get the list of assemblies to look for Controller instances.
Apparently the ElmahController lives in an assembly that is not returned by IAssembliesResolver.GetAssemblies(). To fix this you can do two things:
Call the RegisterWebApiControllers overload that accepts a list of Assembly instances and pass in the application assemblies that contain your controllers + the ELMAH assembly that contains your assembly
Customize Web API's controller discovery mechanism as described here
Especially the first solution is simpler compared to manually registering the controller, because under the covers RegisterWebApiControllers ensures the false-positive diagnostic warning for disposable components is suppressed.

Undeclared Throwable Exception when using Spring Boot AOP controller advice with join points matching jpa repository functions

Problem:
Spring boot service using MVCS architecture. I am using Spring AOP advice (around advice) for all functions present in any class in repository directory. So for example when jpa save method is called, the around advice is triggered.
Now, Here is how things get called when no exception occurs.
CONTROLLER -> SERVICE LAYER -> call to repository layer function triggers advice function which allows join point to proceed -> REPOSITORY LAYER -> around advice -> and everything executes fine.
Now, Here is the flow when exception is thrown by the controller advice function.
CONTROLLER -> SERVICE LAYER -> call to repository layer function triggers advice function which allows join point to proceed -> REPOSITORY LAYER -> some DB exception occurs (for example trying to set a database attribute with NON NULL constraint to NULL) -> back to controller advice, it catches the exception then throws a custom checked exception to service layer and than going through service layer and then controller where the exception is handled.
The problem is that service layer doesn't know about controller advice (it acts like a proxy) and thinks that repository layer won't throw any exception since it doesn't declare throws in its methods signature (for example the default save method).
So the exception that reaches the controller is not the one which is thrown by the controller advice functions. In fact Java wraps that exception inside UndeclaredThrowableException.
One way to deal with this situation is to check ex.getCause() and get the exception which java wrapped in UndeclaredThrowableException.
Another is to declare throws in the repository methods signature so that the service layers can know about the repository function throwing exception. (But this is not possible for default implementation provided by jpa - like the save function - atleast not without overriding the save function) and this I don't want to do because there are a lot of jpa inbuilt functions to override.
Any elegant solution/suggestion to the problem ?
You cannot magically violate JVM restrictions about throwing undeclared checked exceptions. Therefore, you will have to
throw a checked exception which has actually been declared in the intercepted target method, or
throw a runtime exception instead, optionally wrapping it around the checked exception you want to throw.
Sorry, I cannot change the JVM for you. You need to play by its rules.

Handling exception when using HibernateDaoSupport

I am using Spring Hibernate integration in my application and DAO classes are extending HibernateDaoSupport.
Suppose I save some object using the code
getHibernateTemplate().save(object);
As Spring Hibernate integration doesn't mandate to write try-catch block, but suppose if any exception is thwron while saving that object.
Then what is the best way to handle it? I means should I catch it in the service layer and wrap it in some user defined excpetions.
Do I need to write try-catch in DAO layer method itself in case I want to log which method in DAO throws exception?
I have never used HibernateDaoSupport or Hibernate Template before so ignorant about exception handling. Please provide me your valuable inputs
The idea behind Spring using RuntimeException is that generally there are different types of exception:
Exceptions that you want to recover from (such as a DuplicateKeyException if a record that you're trying to insert already exists or the more general DataIntegrityViolationException if there was a DB constraint that was violated as a result of user input)
Exceptions that you can't recover from (the database is down)
For the first case, you may well handle the exception (either through a custom business exception, so that the view layer can redirect to the input page and provide a meaningful message)
For the second case, it would be easier to let the exception bubble up and have it handled by a generic exception handler that then displays a generic error page to the user. For this scenario it doesn't make sense to wrap the exception in a custom exception as you won't be able to recover. A blown up DB tends to be fatal.
So what I would do:
try {
getHibernateTemplate().save(object);
} catch (DataIntegrityViolationException dive) {
throw new BusinessValidationException(dive, "You've got the data wrong");
}
Spring exception hierarchy is well documented.
Usually you can't do much if you have a data access exception, because in the working system this may be caused by the shortage of diskspace on the DB server, or network connection problems etc.
Such exceptions are usually need to be logged and investigated as soon as possible.
There some recoverable errors, they can be handled with spring exception hierarchy, but imho most of them should be avoided during the developing phase, so your web server should validate as many things as possible, before it goes to the db.
If you want to set the exception logging see the similar questions:
Exception handler in Spring MVC
Spring MVC Best Practice Handling Unrecoverable Exceptions In Controller

Server side Exception or error to be propagated to JSP in Spring

I am trying to show an custom error message on any occurrence of exception or error in my business layer. I am catching the exception in my controller and I would like to display it in my JSP.
This exception or error is not associated with any field in the screen, it's a pure server exception. I am also using an Annotated Controller. I am using Prototype for making AJAX requests to my controller.
In Spring you can register a HandlerExceptionResolver which will catch exceptions thrown by your Spring MVC controllers and forward them to the view layer for rendering. These are described in the Spring docs here. Start with the SimpleMappingExceptionResolver (see javadoc) which gives a simple mechanism for mapping exception types to views.
However, if the exception occurs outside if your Spring controller, for whatever reason, then you'll need a more generic fall-back solution, which involves configuring error pages in your web.xml file. This is not Spring-specific. See here for an example of how to do it.

How to configure spring HandlerExceptionResolver to handle NullPointerException thrown in jsp?

From a jsp is thrown a NullPointerException for example using <% null.toString(); %>
This exception is not handled by the HandlerExceptionResolver, but thrown to the web container(tomcat) and converted into a code 500 error.
How can I configure spring to get that error in my HandlerExceptionResolver ?
Details:
Spring can be configured to handle exceptions thrown inside Controllers, but not exceptions thrown by view.
Of course i can resolve the NullPointerException, but i want to design a solution that will gracefully resolve any possible problem on the web application in order to display a user friendly message to the user.
See the HandlerInterceptor interface instead. You'll want the afterCompletion method. You can then intercept the response and then set the appropriate header information to redirect to a container-configured error web page. You're right that Spring doesn't have this functionality, this is going to have to be specified by the web.xml which determines which codes map to which pages.
I have not worked with this particular bit of the spring framework, but the docs say
"Interface to be implemented by objects than can resolve exceptions thrown during handler mapping or execution, in the typical case to error views. Implementors are typically registered as beans in the application context.
Error views are analogous to the error page JSPs, but can be used with any kind of exception including any checked exception, with potentially fine-granular mappings for specific handlers."
so I'd imagine that given that NullPointer extends RuntimeException the framework isn't designed to catch it. Is there a reason the exception(s) can't be handled in the controller directly?

Resources