EduSpring Part 6: Crazy Error Messages and What to do about them
- The virtual path '/currentcontext.dummy' maps to another application, which is not allowed: This error message usually means you've deployed the application to a server, but forgotten to make the virtual directory an application in IIS. Spring performs a server.Transfer() call to "~/currentcontext.dummy" to get all the dependency wiring done correctly before another server.Transfer() brings the request back to the right place.
- no application context for virtual path: This error message tells you that there's no spring configuration setup at all.
- Resource handler for the 'web' protocol is not defined: This message tells you that the httpModule is not active. Add the spring.net HttpModule into the appropriate section of web.config (system.web for IIS6, system.webserver for IIS7).
- Could not load type from assembly: This may or may not have anything to do with Spring, so take a look a the stack trace. If you see Spring.Core (specifically Spring.Core.TypeResolution.TypeResolver.Resolve) in the trace, you can be fairly certain you misspelled a type name in the configuration.
- node cannot be resolved for the specified context: Spring tried to assign an object or value to a property, but the property doesn't exist on the object. It's likely you misspelled the property name, or maybe you refactored, removed the property, but forgot to update the spring configuration.
- Is your configuration binding the right type? For example, if your property is a string, and you're assigning a stringbuilder to it, Spring will just ignore the assignment.
- You're missing the object definition in the spring configuration.
- You're missing the property definition in the spring configuration.
- Did you commit the cardinal sin of DI? Do not use new MyType()!
Labels: EduSpring |
EduSpring Part 5: Spring.Net in an ASP.NET environment (including MVC)
This post is part of a series on Spring.NET. I recommend starting at the beginning if you haven't already. Also, I am walking through code in the accompanying GitHub project.
By now, you should have the basics of DI, IoC, and the benefits and drawbacks of the approach. Now, I'll introduce you to the architecture of Spring.NET in an ASP.NET environment. I'm sure a lot of other IoC frameworks operate in a similar manner. If not, you can add code to make them work that way. ;-)
If you look at the IocWithoutSpring project, you'll see this Main function:
static void Main(string[] args) { //These two lines are handled by the Spring.NET HttpModule var container = new IoCContainer(); container.Initialize(); // These two lines are also handled by the HttpModule by a special // syntax in the spring configuration var service = new DoSomeWork(); service.Worker = container.GetObject("myObject"); // This is what the ASP.NET Framework would do Console.WriteLine("The output is: " + service.DoTheWork()); }
Most of the time, creation of the IoC container itself is a single dependency that's particularly hard to get rid of without writing some reflection-style glue code. Ideally, we want our objects to be completely ignorant of this container, though. In ASP.NET, the web.config provides us with the concept of an HttpModule, which will look at every request coming from into the web server and have an opportunity to do something with it. Taking advantage of this feature, the Spring.Net team wrote an ASP.NET HttpModule that will do just that, so the first two lines of main (instantiation and initialization of the container) are handled by the ASP.NET framework. Awesome!
Now our Spring.Net dictionary is populated, assuming we have a valid configuration. I'll address more about the pain points of Spring configuration later, but this very early creation of lots of objects is one of the main frustrations of people who want to use Spring.Net. The next question is, what about setting up dependencies in ASPX pages?
Technically speaking, the ASP.NET framework parses an ASPX file (or MVC view) and code-generates a class. On each request, it creates an instance of this class and allows it to process the request, before destroying the object. Very stateless, but this creation and destruction of classes rubs against IoC's Dictionary<string,object> heart.
If you read this contract from the other side (a.k.a. how would I solve this problem if I were writing Spring.Net), you can imagine yourself writing a PageHandlerFactory that can deliver the aspx page class with dependencies already injected. There are two problems you have to solve, however:
- What name do you use to look up the object?
- How do you deal with request-specific data?
Labels: EduSpring |
EduSpring Part 4: What is so terribly broken with Dependency Injection?
Move all the CS BS to the side. This stuff doesn't work in the real world. And it's because of things that could have (and probably should have) been fixed by uber-geeks 10+ years ago with fancy CompSci PhDs. And I'm talking about .Net specifically here, although I can throw the same stones at Java. Most (but not all) other languages have the same problems I'll get on my soapbox about here.
To do DI correctly, you have one of two options:
- Your class has dependencies on properties/internal fields that implement Interfaces
- Your class has dependencies on properties/internal fields that implement base classes
- Do you assume anything about the return value? It might return what you expect, or might return null. Or, it could throw an exception. Generally, experience with DI will teach you good defensive coding, but it does take work...
- Can the method handle null input values? If it errors, is it going to return null or throw an exception? If it throws, what kind of exception will it generate?
- Is the method you're calling going to muck with the object you pass in? If it does alter properties, is that a problem? What if you're not in control of the object, and the property this dependency decides it's OK to muck with throws an exception during the set operation?
Labels: EduSpring |
EduSpring Part 3: What do we need an IoC for?
This post is part of a series on Spring.NET. I recommend starting at the beginning if you haven't already. Also, I am walking through code in the accompanying GitHub project.
Last time, I walked through why we might want to use dependency integration. Outside the authentication example, here are a few other examples:
- Authentication
- Authorization
- SMTP settings
- Payment gateways
- Business rules (rule engine style)
- Branding
class IoCContainer { private readonly IDictionary_allObjects = new Dictionary (); public T GetObject (string objectName) { return (T)_allObjects[objectName]; } public void Initialize() { // Wouldn't it be nice if we could configure this through // app.config or web.config? Spring does that! _allObjects.Add("myObject", new ClassA()); } }
Most IoC containers work in a similar manner. There's some sort of initialization function, and there's some sort of GetObject method. Internally, all it does is "new up" all the classes you've defined and shoves them in a global dictionary object. The rest, as they say, is window dressing. As you see in the comment, once you've built an IoC container, you can think of all kinds of cool things to do. It would be really nice if you could configure from web.config/app.config, or maybe a separate XML file, or maybe the database, or maybe all of them? What if you added the ability to set properties on the objects, not just create them? How about the ability to create an object based on the state of another object (Spring calls this a factory method). How about defining objects in one place, and values for properties in another? IoC containers have all this stuff, and it's built for you...there's no reason to reinvent the wheel.
But at the end of the day, remember: An IoC container, at its heart, is a Dictionary<string, object>. And that's all, folks. Another key thing to remember, especially in a stateless ASP.NET scenario, is that those objects exist during the lifetime of the application. This is a performance gain (no GC stepping in, no creation of multiple objects), and a bug factory if you assume your objects are going to be created, used once, and destroyed.
More goodies are in the main file if you read the comments, but I'll explore them more in depth in later posts.
Labels: EduSpring |
EduSpring Part 2: Simplifying dependencies
Last time, I introduced you to Spring, IoC, and Dependency Injection. If you haven't read that post, please do. This time, I'll start walking through some of the code in the accompanying GitHub project. The code is organized by project in order of these posts. Some conventions (specifically 1 class/file) have been ignored specifically to let the reader go through in a linear manner. All projects are setup as console applications.
This time, I'll tackle the first project, "0 - Advantages of DI". This is one of the few projects I that will have more than one file to peruse. The first file is a baseline...how we would solve a particular problem in a "traditional" procedural manner. I've simulated a program that calls a service (MyClass) that needs to authenticate the user prior to performing some work on behalf of the caller. If authentication fails, it will throw an exception. Here is the class:
////// Simulates a typical class /// public class MyClass { ////// Authentication provider. We can't change this out for the production version /// without changing source code and recompiling /// private readonly MyAuthenticationProvider authenticationProvider = new MyAuthenticationProvider(); // Comment the line above, uncomment and recompile for production. // // By recompiling, you won't know if you're testing the same // code that exists in production (did you just change this line, or something else too?) Versions might // be different, etc. //private readonly MyProductionAuthenticationProvider authenticationProvider = new MyProductionAuthenticationProvider(); public void DoWork(string user, SecureString password) { if(!authenticationProvider.Authenticate(user,password).Identity.IsAuthenticated) throw new SecurityException("Not authorized to perform this action"); Thread.Sleep(3000);// Simulate some work } }
You'll notice that when we move this class into production, we have to remember to swap out our authentication provider. In reality, the new authentication provider might now call a central authentication single-sign-on service through a web/rest service, might redirect the user in order to change password, or any number of crazy things. For these purposes, I just check that the password is "bar".
The main point here is that we have to remember to swap, and we'll have to recompile the application when we do that. If we forget, anyone can log in with anything and we'll happily give up the goods. Since everything has been "tested", it's likely we won't thoroughly check the service (indeed, if we're on a production system, and this service's purpose was to delete a bunch of accounts, we probably wouldn't test it). After deployment have two versions of the binary - one for production, and one outside production. Who is to say there aren't any other changes in this code. Now we have a maintenance problem too - we can't assume the code is identical, and every time we deploy we run the risk of missing this step. But, it's simpler when we're coding it, isn't it?
If we could just pass this dependency into MyClass, we'll be in much better shape. At the minimum we can centralize the changes, and in the best case we can move these changes out into a configuration file or some other mechanism that doesn't require code changes for this simple switch. Enter the next file in this project - "1 - WithDependencyInjection.cs". Here are the contents:
////// Simulates a typical class /// public class MyClassWithDependencyInjection { ////// Authentication provider. Because we use an interface, we no longer /// need to change this code after it's been tested /// private readonly IAuthenticate _authenticationProvider; ////// Constructor to establish this class' dependencies. Since the /// class is not "complete" (can't operate) without an authentication /// provider, we require an object up front. /// /// public MyClassWithDependencyInjection(IAuthenticate authProvider) { if (authProvider == null) throw new ArgumentNullException("authProvider"); _authenticationProvider = authProvider; } public void DoWork(string user, SecureString password) { if (!_authenticationProvider.Authenticate(user, password).Identity.IsAuthenticated) throw new SecurityException("Not authorized to perform this action"); Thread.Sleep(3000);// Simulate some work } } ////// New Interface introduced. Our two classes don't have a real-world inheritance relationship, /// but the authentication process is identical, so we build a contract /// public interface IAuthenticate { IPrincipal Authenticate(string user, SecureString password); } class TestingAuthenticationProvider : IAuthenticate { public IPrincipal Authenticate(string user, SecureString password) { // Implementation for development return new GenericPrincipal(new GenericIdentity(user), new string[] { }); } } class ProductionAuthenticationProvider : IAuthenticate { public IPrincipal Authenticate(string user, SecureString password) { if (user == "foo" && password.StringEquals("bar")) return new GenericPrincipal(new GenericIdentity(user), new string[] { }); return new GenericPrincipal(new GenericIdentity(""), new string[] { }); ; } }
Here, we've done the following things:
- Introduced an interface for authentication and marked both providers as implementing the interface. We could just as well have introduced a base class (concrete or abstract), but we have no default implementation, so an interface is probably best.
- Introduced a parameterized constructor for the main class. Now this class lets the world know that it can't do it's job without a way to authenticate. And it doesn't care how the authentication gets done, just that it can authenticate.
static void Main(string[] args) { // Without DI new MyClass().DoWork("foo", new SecureString().Append("bar")); // With DI var testSystemProvider = new TestingAuthenticationProvider(); var productionSystemProvider = new ProductionAuthenticationProvider(); // The choice of test/production is now made here, outside of the class. // The class shouldn't "care" who does the authentication work, it's job is to do other work // The new statement in the next line would be done through an IoC container (e.g. Spring) in a // real environment. new MyClassWithDependencyInjection(testSystemProvider).DoWork("foo", new SecureString().Append("bar")); // Switch the constructor (in Spring.NET, done through a config file change) and now we're running against // "production". No recompile necessary new MyClassWithDependencyInjection(productionSystemProvider).DoWork("foo", new SecureString().Append("bar")); // We can also do this without a container. Here, we'll get type information from the command line. // Change the provider type via project properties to see how this works. // The next line is basically what an IoC container would do var myAuthProvider = (IAuthenticate)Activator.CreateInstance(Type.GetType(args[0])); new MyClassWithDependencyInjection(myAuthProvider).DoWork("foo", new SecureString().Append("bar")); }
With dependency injection techniques, the caller can decide the authentication mechanism. Given a proper IoC container, this configuration will be centralized, but for now, we can do it manually by creating two objects, one of type TestingAuthenticationProvider and one of type ProductionAuthenticationProvider. These are passed into the constructor for the DI class, and voilĂ , we can change the way authentication works. In the last two lines, I show how we can even pass in the type name via the command line. Now, for the first time, we have the ability to change the way we authenticate without changing code.
...and that, folks, is all an IoC container is about.
Labels: EduSpring |
EduSpring Part 1: Introduction
I get quite a few questions about Spring.Net, so I thought I'd put together a VS Solution, presentation, and set of blog posts to provide some background and details about what it is, why/when to consider using it, and how to configure and debug the framework.
A lot of this material will not be specific to Spring.Net, but rather Dependency Injection generally. To understand Spring.Net, you must be familiar with Inversion of Control and Dependency Injection. You can read about them on Wikipedia, but here's a short summary:
Inversion of Control: Flow of control of a system is inverted in comparison to procedural programming
Dependency Injection: A specific technique to achieve inversion of control with respect to dependencies
What this means in layman's terms is that instead of a program:
- Starts up
- Creating new services for whatever needs to be done
- Using the services/doing the work
- Disposing of the services and returning the results
- Starts up
- Uses services that have been configured for its use/does the work
- Returns the results
Labels: EduSpring |