I have an MVC3 app with a simple Log service. All my services are invoked using Microsoft's Unity Dependency Injection container.
For most methods, I ignore exceptions; they're caught in a top-level error handler, which categorizes them and decides whether or not to log them, generates the HTTP response I desire and calls an action method on the error controller to return my custiom error page.
Sometimes, tho, I don't want to do that; I want to handle the exception where it happens, e.g. in my controller. In that case, I want to log the error before substituting an appropriate default value and continuing with the controller's logic.
I did that in one place: in my controller, I added:
var logService = DependencyResolver.Current.GetService<ILogService>();
try { /* something indeterminate */ }
catch ( Exception ex ) {
logService.LogException(category, ex);
/* do something else instead */
}
Now I want to do it a second time in that controller (as it happens, later in the same method). As soon as I do this again, I see it's time to refactor, as I'm repeating myself.
What's the best way to make my logger available to my controllers? My controllers all inherit from a custom ControllerBase; my first thought is to add it to the ControllerBase's constructor. BUT:
currently I don't have a constructor in the ControllerBase,
I'm a bit worried that referencing the DI container in the
controller breaks the isolation of the controller, negating the
value of DI to begin with, and
I don't think I can pass the
logger in to the ControllerBase's constructor, because (as I
understand it, pls correct me if 'm wrong) controllers can only have
parameterless constructors, so there's no way to pass anything to
them.
Where's the proper place to make the service available to all my controllers?
Place it in your constructor. You can even place it in a BaseController.
Ideally, you will use Dependency Injection and have it come in on your controller. Controllers can have parameters if your IoC container supports it.
private readonly ILogService logService;
public MyController(ILogService logService)
{
this.logService = logService;
}
I wouldn't add it to the base controller for the sole reason that it sounds as if you only use it sporadically. I would add it as Daniel White suggests in the constructor of the controller. If it's looking as though you use it in most controllers, then I'd consider moving it to the base.
Related
I've built some code that can rebuild expression trees so I can avoid triggering the no supported translation to SQL exception and it works fine as long as I call my function to replace the iqueryable. The problem is that I'd like it to automatically be applied to all queries in my project without having to worry about calling this function on each one separately. Is there any way that I can intercept everything?
I've tried using Reflection.Emit to create a wrapping provider and using reflection to replace it on the data context and it turns out that even with Reflection.Emit I can't implement the internal IProvider interface.
I've also tried replacing the provider with a RealProxy based class and that works for non-compiled queries, but the CompiledQuery.Execute method is throwing an exception because it won't cast to the SqlProvider class. I tried replacing the response to the Compile method on the provider with another proxy so I could intercept the Execute call, but that failed a check on the return type being correct.
I'm open to any other ideas or ways of using what I've already tried?
It's hard to tell whether this is an applicable solution without seeing your code, but if you have a DI-friendly app architecture you can implement an interceptor and have your favorite IoC container emit the appropriate type for you, at run-time.
Esoteric? A little. Consider an interface like this:
public interface ISomeService
{
IEnumerable<SomeEntity> GetSomeEntities();
// ...
}
This interface might be implemented like this:
public class SomeService : ISomeService
{
private readonly DbContext _context // this is a dependency!
private readonly IQueryTweaker _tweaker; // this is a dependency!
public SomeService(DbContext context, IQueryTweaker tweaker) // this is constructor injection!
{
_context = context;
_tweaker = tweaker;
}
public IEnumerable<SomeEntity> GetSomeEntities()
{
return _tweaker.TweakTheQuery(_context.SomeEntities).ToList();
}
}
Every time you implement a method of the ISomeService interface, there's always a call to _tweaker.TweakTheQuery() that wraps the IQueryable, and that not only gets boring, it also feels like something is missing a feature - the same feeling you'd get by wrapping every one of these calls inside a try/catch block, or if you're familiar with MVVM in WPF, by raising this annoying PropertyChanged event for every single property setter in your ViewModel.
With DI Interception, you factor this requirement out of your "normal" code and into an "interceptor": you basically tell the IoC container that instead of binding ISomeService directly to the SomeService implementation, you're going to be decorating it with an interceptor, and emit another type, perhaps SomeInterceptedService (the name is irrelevant, the actual type only exists at run-time) which "injects" the desired behavior into the desired methods. Simple? Not exactly.
If you haven't designed your code with DI in mind (are your dependencies "injected" into your classes' constructor?), it could mean a major refactoring.
The first step breaks your code: remove the IQueryTweaker dependency and all the TweakTheQuery calls from all ISomeService implementations, to make them look like this - notice the virtualness of the method to be intercepted:
public class SomeService : ISomeService
{
private readonly DbContext _context
public SomeService(DbContext context)
{
_context = context;
}
public virtual IEnumerable<SomeEntity> GetSomeEntities()
{
return _context.SomeEntities.ToList();
}
}
The next step is to configure the IoC container so that it knows to inject the SomeService implementation whenever a type's constructor requires an ISomeService:
_kernel.Bind<ISomeService>().To<SomeService>();
At that point you're ready to configure the interception - if using Ninject this could help.
But before jumping into that rabbit's hole you should read this article which shows how decorator and interceptor are related.
The key point is, you're not intercepting anything that's internal to LINQ to SQL or the .NET framework itself - you're intercepting your own method calls, wrapping them with your own code, and with a little bit of help from any decent IoC container, you'll be intercepting the calls to methods that call upon Linq to SQL, rather than the direct calls to Linq to SQL itself. Essentially the IQueryTweaker dependency becomes a dependency of your interceptor class, and you'll only code its usage once.
An interesting thing about DI interception, is that interceptors can be combined, so you can have a ExecutionTimerServiceInterceptor on top of a AuditServiceInterceptor, on top of a CircuitBreakerServiceInterceptor... and the best part is that you can configure your IoC container so that you can completely forget it exists and, as you add more service classes to the application, all you need to do is follow a naming convention you've defined and voilà, you've just written a service that not only accomplishes all the strictly data-related tasks you've just coded, but also a service that will disable itself for 3 minutes if the database server is down, and will remain disabled until it's back up; that service also logs all inserts, updates and deletes, and stores its execution time in a database for performance analysis. The term automagical seems appropriate.
This technique - interception - can be used to address cross-cutting concerns; another way to address those is through AOP, although some articles (and Mark Seeman's excellent Dependency Injection in .NET) clearly demonstrate how AOP frameworks are a less ideal solution over DI interception.
I have created a custom scope in my application that implements org.springframework.beans.factory.config.Scope.
As part of this, i have to implement the method below so that the PreDestroy method gets correctly invoked on my custom scoped beans.
public void registerDestructionCallback(String name, Runnable callback) {
}
The javadocs on the method are not that clear and I seem to be lost about what code i should write in that method.
Can someone please help?
It depends on what your custom scope actually does and if you are using this scope for DisposableBean, beans with destroy-method, and DestructionAwareBeanPostProcessor.
In simplest case you don't need to do anything or just log a warning that callback is not supported.
In more complex case, you need to handle object destruction that is outside of regular custom scope life cycle. Eg. when object is destroyed, based on its expiration or something similar (unlike explicit call to Scope.remove(String name) method).
For example, for session-scoped beans, this callback is hooked up to HttpSessionListener.sessionDestroyed(..) event. See sources for org.springframework.web.context.request.SessionScope class.
I'm using Google's Preconditions class to validate user's input data.
But I'm worried about where is the best point of checking user's input data using Preconditions class.
First, I wrote validation check code in Controller like below:
#Controller
...
public void register(ProductInfo data) {
Preconditions.checkArgument(StringUtils.hasText(data.getName()),
"Empty name parameter.");
productService.register(data);
}
#Service
...
public void register(ProductInfo data) {
productDao.register(data);
}
But I thought that register method in Service layer would be using another Controller method like below:
#Controller
...
public void register(ProductInfo data) {
productService.register(data);
}
public void anotherRegister(ProductInfo data) {
productService.register(data);
}
#Service
...
public void register(ProductInfo data) {
Preconditions.checkArgument(StringUtils.hasText(data.getName()),
"Empty name parameter.");
productDao.register(data);
}
On the other hand, the method of service layer would be used in just one controller.
I was confused. Which is the better way of checking preconditions in controller or service?
Thanks in advance.
Ideally you would do it in both places. But you are confusing two different things:
Validation (with error handling)
Defensivie Programming (aka assertions, aka design by contract).
You absolutely should do validation in the controller and defensive programming in your service. And here is why.
You need to validate for forms and REST requests so that you can send a sensible error back to the client. This includes what fields are bad and then doing localization of the error messages, etc... (your current example would send me a horrible 500 error message with a stack trace if ProductInfo.name property was null).
Spring has a solution for validating objects in the controller.
Defensive programming is done in the service layer BUT NOT validation because you don't have access to locale to generate proper error messages. Some people do but Spring doesn't really help you there.
The other reason why validation is not done in the service layer is that the ORM already typically does this through the JSR Bean Validation spec (hibernate) but it doesn't generate sensible error messages.
One strategy people do is to create their own preconditions utils library that throws custom derived RuntimeExceptions instead of guava's (and commons lang) IllegalArgumentException and IllegalStateException and then try...catch the exceptions in the controller converting them to validation error messages.
There is no "better" way. If you think that the service is going to be used by multiple controllers (or other pieces of code), then it may well make sense to do the checks there. If it's important to your application to check invalid requests while they're still in the controller, it may well make sense to do the checks there. These two, as you have noticed, are not mutually exclusive. You might have to check twice to cover both scenarios.
Another possible solution: use Bean Validation (JSR-303) to put the checks (preconditions) onto the ProductInfo bean itself. That way you only specify the checks once, and anything that needs to can quickly validate the bean.
Preconditions, validations, whether simple or business should be handled at the filter layer or by interceptors, even before reaching the controller or service layer.
The danger if you check it in your controller layer, you are violating the single responsibility principle of a controller, whose sole purpose is to delegate request and response.
Putting preconditions in service layer is introducing cross cutting concerns to the core business.
Filter or inceptor is built for this purpose. Putting preconditions at the filter layer or in interceptors also allow you to “pick and match” rules you can place in the stack for each servlet request, thus not confining a particular rule to only one servlet request or introduce duplication.
I think in your special case you need to to check it on Service layer and return exception to Controller in case of data integrity error.
#controller
public class MyController{
#ExceptionHandler(MyDataIntegrityExcpetion.class)
public String handleException(MyDataIntegrityExcpetion ex, HttpServletRequest request) {
//do someting on exception or return some view.
}
}
It also depend on what you are doing in controller. whether you return View or just using #ResponseBody Annotation. Spring MVC has nice "out of the box" solution for input/dat validation I recommend you to check this libraries out.
http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/validation.html
I want to call a method on another controller. The problem is that in my project, all controllers are created using Windsor castle and Windsor castle resolve the dependencies. This means that I cannot instantiate a controller by using new as then it needs its dependents. How can ask MVC to instantiate a controller and then call a method on it (which returns an object)?
I'm going to tell you two things: 1) First, I'll show you how you'll most likely be able to accomplish what you want, and 2) Then I'll recomment you achieve your goal in another way :)
1: When using auto-wiring, the way to get stuff from the container is to declare the dependency by adding it as a constructor argument - e.g. (assuming the container knows how to resolve controllers by their concrete types):
public class HomeController
{
readonly AccountController accountController;
public HomeController(AccountController accountController)
{
this.accountController = accountController;
}
}
This will most likely allow you to do what you want with AccountController from withing HomeController. However, this is not very pretty.
2: Injecting one controller into another is probably not what you (really) want. I'm guessing that you really want to move whatever logic you have in your controller's action method into a dedicated service, e.g. DoSomethingInteresting which happens to implement IDoStuff, and then let both of your controllers depend on IDoStuff. Does this make sense to you?
I would love to use the #NotNull annotation (or #Required or anything) for my own methods. While this works quite well in Controller and Model classes I cant get it to work in my own. This probably is more of a net.sf.oval question then play framework. But it might be connected, I don't know.
I have a class like:
#net.sf.oval.guard.Guarded
public class SimulatorWrapper {
public SimulatorWrapper setRedCode(#play.data.validation.Required #net.sf.oval.constraint.NotNull final String redCode) {
// just gessing here:
if(Validation.hasErrors()) throw new RuntimeException("invalid argument");
if(redCode == null) throw new RuntimeException("null");
// do stuff
return this;
}
}
When I call this method with a null parameter the if throws my exception, but #NotNull and #Required seem to do nothing at all. What am I doing wrong?
The play framework project came with oval 1.5, I downloaded 1.8 and added it to the classpath in eclipse just in case the old one had problems.
I'm starting the server with "play test my-server" and then I navigate to my website (not a test yet, just simple site) with my browser.
Thanks, Alex
P.S. I know the "null is evil" discussion, but I dont have access to the rest of the code so I cant change that.
The validation class is invoked to check the validation annotations by the Play framework only when a controller action is called.
Since you're not in a controller, the Validation on annotation won't be executed and the Required annotion won't be in Validation.hasErrors()
Instead of using annotation, you could use methods like:
Validation.required(redCode); //It'll check for null
And after that, call Validation.hasErrors() and it should work.
However, I don't think you should do this because the errors from Validation.hasError() should come from Validation on the controller action invocation and it can cause you side effects.
If you want to do something like your example, you should not rely on the play Validation class.
Are you sure you're using validation at the right places ?
In case anyone still needs this.
You can do validation with Play annotations in all classes exactly the same way as in controllers.
Just use validate plugin.