Register | Login

Stacking Code

public interface IBlog { string Dump(Stream consciousness); }

Configuring Spring

Friday, 3 December, 2010 @ 8:21 PM < Adam Boddington
Tags: Building Neno, Inversion of Control, NHibernate, Spring

This is post #10 in the Building Neno series. Please click here for a description of the Building Neno project and instructions on how to access the source code for this post.

It's Friday already -- where did the week go? Time to kick back and do something fun... like configure Spring!

... wait, wut? - me, just now

My Container

I'll configure my container first since it's pretty straight forward. Define the section, then fill the section out with a type pointing to the Spring provider I made earlier.

<configuration>
    <configSections>
        <section name="inversionOfControl" type="StackingCode.Moja.InversionOfControl.Configuration.InversionOfControlSection, StackingCode.Moja" />
    </configSections>
    <inversionOfControl>
        <containerProvider type="StackingCode.Moja.InversionOfControl.Spring.ContainerProvider, StackingCode.Moja.InversionOfControl.Spring" />
    </inversionOfControl>
</configuration>

Spring Has Sprung

Spring starts out the same way, by defining a section (or two).

<configuration>
    <configSections>
        <sectionGroup name="spring">
            <section name="context" type="Spring.Context.Support.WebContextHandler, Spring.Web" />
            <section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core" />
        </sectionGroup>
    </configSections>
</configuration>

The context section is responsible for the container -- in this case I want a web context so that I have access to the request scope. (The default Spring context only has singleton and instance available.) The objects section is where I define all the objects I want in the container.

In order for Spring to give me the request scope, it needs a module defined. I'll define it twice to cover all the flavours of IIS.

<configuration>
    <system.web>
        <httpModules>
            <add name="Spring" type="Spring.Context.Support.WebSupportModule, Spring.Web" />
        </httpModules>
    </system.web>
    <system.webServer>
        <modules>
            <add name="Spring" type="Spring.Context.Support.WebSupportModule, Spring.Web" />
        </modules>
    <system.webServer>
</configuration>

Now I can define some of my objects. The resource element in the context section tells the context where to look for my object definitions. It's possible to specify other XML files, but I prefer to keep it all in the application's .config file.

<configuration>
    <spring>
        <context>
            <resource uri="config://spring/objects" />
        </context>
        <objects xmlns="http://www.springframework.net">
            <!-- Services -->
            <!-- Repositories -->
            <!-- Moja -->
        </objects>
    </spring>
</configuration>

Spring can do all sorts of automatic goodness with NHibernate and controllers. However, at this stage I'm more comfortable with just using Spring as a service locator from inside my UI. I think it's a bit clearer to the developer (me!) what is actually going on. At and below the service layer, however, automatic dependency injection everywhere.

<!-- Services -->
<object name="PostService" type="StackingCode.Neno.Services.PostService, StackingCode.Neno" scope="request">
    <property name="Context" ref="Context" />
    <property name="PostRepository" ref="PostRepository" />
    <property name="CommentRepository" ref="CommentRepository" />
</object>
<!-- Repositories -->
<object name="CommentRepository" type="StackingCode.Neno.Repositories.NHibernate.CommentRepository, StackingCode.Neno.Repositories.NHibernate" scope="request">
    <property name="Context" ref="Context" />
    <property name="Session" ref="Session" />
</object>
<object name="PostRepository" type="StackingCode.Neno.Repositories.NHibernate.PostRepository, StackingCode.Neno.Repositories.NHibernate" scope="request">
    <property name="Context" ref="Context" />
    <property name="Session" ref="Session" />
</object>
<!-- Moja -->
<object name="Context" type="StackingCode.Moja.Repositories.NHibernate.Context, StackingCode.Moja.Repositories.NHibernate" scope="request">
    <property name="Session" ref="Session" />
</object>
<object name="Session" factory-object="SessionFactory" factory-method="OpenSession" scope="request" />
<object name="SessionFactory" type="StackingCode.Moja.Repositories.NHibernate.SessionFactoryWrapper, StackingCode.Moja.Repositories.NHibernate" />

At this stage I've only defined the post service, with all of its dependencies, as an example. Everything is in the request scope except for the session factory, which is a singleton. All the NHibernate configuration takes place in the SessionFactoryWrapper class and only needs to happen once per application.

Spring instantiates everything itself as needed, except for NHibernate sessions. I've told Spring to create those using a method on the session factory singleton instead.

Spring to Action

I'll throw a couple of lines into HomeController to see if it all works.

var postService = Container.Get<IPostService>();
IQueryable<Post> posts = postService.GetPosts();

foreach (Post post in posts)
    Response.Write(string.Format("Title: {0}<br />Text: {1}<br />", post.Title, post.Text));

return new EmptyResult();

Running the application shows I'm missing a whole bunch of references which I'll have to add.

  • StackingCode.Moja.InversionOfControl.Spring for my container.
  • Common.Logging for Spring.
  • NHibernate.ByteCode.Castle for NHibernate.
  • NHibernate.Caches.SysCache for NHibernate.
  • Remotion.Data.Linq for NHibernate.
  • Antlr3.Runtime for NHibernate.

I also get an error.

Cannot find matching factory method 'OpenSession on Type [StackingCode.Moja.Repositories.NHibernate.SessionFactoryWrapper].

I forgot, Spring doesn't like params in methods or constructors. Remember this?

public ISession OpenSession(params IInterceptor[] interceptors)
{
    var interceptorAdapter = new InterceptorAdapter(interceptors);
    ISession session = SessionFactory.OpenSession(interceptorAdapter);
    session.FlushMode = FlushMode.Commit;

    return session;
}

I'll have to make two methods instead.

public ISession OpenSession()
{
    return OpenSession(new IInterceptor[0]);
}

public ISession OpenSession(IInterceptor[] interceptors)
{
    var interceptorAdapter = new InterceptorAdapter(interceptors);
    ISession session = SessionFactory.OpenSession(interceptorAdapter);
    session.FlushMode = FlushMode.Commit;

    return session;
}

Running again, another error.

IUserService is not defined in Spring objects.

I forgot, the post service calls User.Current. Well that's not fully implemented yet, so I'll comment the filter out for now.

Running again...

Title: Fred Text: Fred was here.

Finally, success. Neno can now talk to the database! Before I can get rid of posts.xml, however, I need to sort a few more things out.

There are 0 comments.


Comments

Leave a Comment

Please register or login to leave a comment.


Older
The Database

Newer
Simple Messages in ASP.NET MVC

Older
The Database

Newer
Simple Messages in ASP.NET MVC

browse with Pivot


About


Projects

Building Neno


RSS
Recent Posts

Codility Nitrogenium Challenge
OS X Lock
HACT '13
Codility Challenges
Priority Queue


Tags

Architecture (13)
ASP.NET (2)
ASP.NET MVC (13)
Brisbane Flood (1)
Building Neno (38)
C# (4)
Challenges (3)
Collections (1)
Communicator (1)
Concurrency Control (2)
Configuration (1)
CSS (5)
DataAnnotations (2)
Database (1)
DotNetOpenAuth (2)
Entity Framework (1)
FluentNHibernate (2)
Inversion of Control (5)
JavaScript (1)
jQuery (4)
Kata (2)
Linq (7)
Markdown (4)
Mercurial (5)
NHibernate (20)
Ninject (2)
OpenID (3)
OS X (1)
Pivot (6)
PowerShell (8)
Prettify (2)
RSS (1)
Spring (3)
SQL Server (5)
T-SQL (2)
Validation (2)
Vim (1)
Visual Studio (2)
Windows Forms (3)
Windows Service (1)


Archives


Powered by Neno, ASP.NET MVC, NHibernate, and small furry mammals. Copyright 2010 - 2011 Adam Boddington.
Version 1.0 Alpha (d9e7e4b68c07), Build Date Sunday, 30 January, 2011 @ 11:37 AM