Erich Eichinger | SpringSource
Einführung in
Spring.NET
Erich Eichinger | SpringSource
About ...
• Erich Eichinger
– 15 Jahre kommerz. Softwareentwicklung
– 8 Jahre Leitung einer Entwicklungsabteilung
– 3 Jahre Core Committer Spring.NET
– seit 1.9. Senior Software Engineer bei
SpringSource
Agenda
• The who, what & why Spring.NET?
• Feature Overview
• Dependency Injection
• Data Access and Declarative Transaction
Management
• Aspect Orientierted Programming
• Spring.NET specific features
• Roadmap
Erich Eichinger | SpringSource
Spring for .NET
• Architectural concepts and patterns are
applicable to .NET
• .NET and Java share many of the same
technical „pain points‟
• Wouldn‟t a .NET port be of value…?
– In 2003 M.P. created minimal .NET port…
– started an open source project…
• "spiritual" port
Erich Eichinger | SpringSource
History
• Project started 2004
– v1.0 released 2005
– v1.1 released 2007
– v1.2 fall 2008
• in production
Erich Eichinger | SpringSource
Burton Group – July 2008 Analyst
Report
Erich Eichinger | SpringSource
“Organizations invested in .NET should similarly investigate Spring.NET;”
“Organizations using Active Server Pages for .NET (ASP.NET) should
likewise evaluate Spring.NET's web features.”
“Spring.NET can provide a consistent cross-platform programming
model for enterprises invested in both Java and .NET development, and
it is especially valuable to enterprises with developers cross-trained on
both platforms.
Spring.NET is also viewed favorably by Microsoft; its project lead was
named a Microsoft “Most Valued Professional” in 2007.”
Who uses Spring.NET?
• Mercado Electronico
– see Case Study in ".NET developer journal"
• Large UK Retailer
• Financial Services
• US Government
• Consulting Firms
• diamond:dogs
– sportnet.at, ...
• Risk Management
– Viz Risk Management
Erich Eichinger | SpringSource
Spring's "nature"
• Inversion of Control (IoC) container
– configure objects via Dependency Injection (DI)
• Aspect Orientierted Programming (AOP)
– Declaratively apply functionality to classes
• Support libraries to tame complex APIs
– Transaction Management, ADO.NET, ASP.NET
• Spring deals with the plumbing
– Address end-to-end requirements rather than one tier
– Can be one stop shop or just use certain sub-systems.
– Consistent programming model
Erich Eichinger | SpringSource
Spring.NET 1.1 Features
• If you are familiar with Spring Java you will feel right at
home
– <bean/> becomes <object/>
– class= becomes type=
• Spring.NET 1.1 ~= Spring Java 1.2 + custom schemas
– IoC Container
– AOP
– Testing (NUnit)
• Features with .NET adaptations
– Transaction Management
– ADO.NET, NHibernate
– Spring Services
Erich Eichinger | SpringSource
.NET-specific Features
• Spring.Web ASP.NET Framework
• Expression Language
– Powerful object navigation & more
• UI agnostic
– Data binding framework
– Validation framework
• Aspect Library
– Retry, Exception Translation, Caching
• Dynamic Reflection Library
• Remoting Support
Erich Eichinger | SpringSource
Agenda
• The who, what & why Spring.NET?
• Feature Overview
• Dependency Injection
• Data Access and Declarative Transaction
Management
• Aspect Orientierted Programming
• Spring.NET specific Features
• Roadmap
Erich Eichinger | SpringSource
Spring.NET's IoC Container
• Heart of Spring .NET
• Facilitates full stack plain object-based development
• Within any environment
– ASP.NET, WinForms/WPF, Web Services/WCF, COM+,
Console, Unit Tests, ...
• By providing
– A powerful object factory that manages the instantiation,
configuration, decoration, and assembly of your business objects
– Object Factory -> „Container‟
Erich Eichinger | SpringSource
Create the Container (1)
• Provide the configuration metadata
– Instructions on how create the object
– Constructor and/or setter injection?
– Singleton or new instance?
– Call custom lifecycle methods?
– Add additional behavior?
• Metadata formats
– Most common is XML (think XAML)
– Programmatic (C#)
– Attributes (Annotations)
Erich Eichinger | SpringSource
Create the Container (2)
• IApplicationContext
– The IoC container
• Create using „new‟ or configure via
App.config
Erich Eichinger | SpringSource
IApplicationContext context =
new XmlApplicationContext("assembly://MyAssembly/MyProject/objects.xml");
IBankService bankService = (IBankService) context.GetObject("bankService");
Create the Container (3)
Erich Eichinger | SpringSource
<configuration>
<configSections>
<sectionGroup name="spring">
<section name="context"
type="Spring.Context.Support.ContextHandler, Spring.Core"/>
</sectionGroup>
</configSections>
<spring>
<context>
<resource uri=“assembly://MyAssembly/MyProject/objects.xml"/>
</context>
</spring>
</configuration>
IApplicationContext context = ContextRegistry.GetContext();
IBankService bankService = (IBankService) context.GetObject("bankService");
Constructor Injection
Erich Eichinger | SpringSource
public class SimpleBankService : IBankService
{
private IAccountDao accountDao;
public SimpleBankService(IAccountDao accountDao)
{
this.accountDao = accountDao;
}
// business methods follow …
}
<object id="bankService" type="SimpleBankService, MyAssembly">
<constructor-arg name=“accountDao“ ref=“accountDao”/>
</object>
<object id="accountDao" type="SimpleAccountDao, MyDaoAssembly">
<property name="MaxResults" value="100" />
...
</object>
Property Injection
Erich Eichinger | SpringSource
public class SimpleBankService : IBankService
{
private IAccountDao accountDao;
public IAccountDao AccountDao
{
get { return accountDao; }
set { accountDao = value; }
}
// business methods follow …
}
<object id="bankService" type="SimpleBankService, MyAssembly"
lazy-init="true">
<property name="AccountDao" ref="accountDao" />
</object>
<object id="accountDao" type="SimpleAccountDao, MyDaoAssembly">
...
</object>
Demo
Erich Eichinger | SpringSource
IoC Container Summary
• 1st order as feature rich as Spring Java
• Container implementation similar enough to allow easy
migration of features
– Attribute based configuration
– Scripted objects (IronPython/IronRuby)
– Will sync some new features in future releases
• If nothing else, use DI to push your application in the
direction of following best practices!
– Loose coupling -> easier to test -> resiliency to change
Erich Eichinger | SpringSource
Agenda
• The who, what and why of Spring.NET?
• Feature Overview
• Dependency Injection
• Data Access and Declarative Transaction
Management
• Aspect Orientierted Programming
• Spring.NET specific Features
• Roadmap
Erich Eichinger | SpringSource
Spring.Data Goals
• Wide range of data access strategies and technologies
to choose from
– APIs tend to be complex and verbose
– Accounts for much of code in an application
– Multiple APIs for transaction management and quirks
• Provide simple and consistent approach to data access
across persistence technologies
– Simplify usage
– Logical, technology neutral exception hierarchy
– Transaction management abstraction
Erich Eichinger | SpringSource
Problems with traditional ADO.NET
• Results in redundant, error prone code
• Hard to write provider independent code
• Code is coupled to transaction API
• Verbose parameter management
Erich Eichinger | SpringSource
Redundant Code
Erich Eichinger | SpringSource
public IList FindAllPeople() {
IList personList = new ArrayList();
try
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
string sql = "select Name, Age from ...";
using (SqlCommand command = new SqlCommand(sql, connection))
{
connection.Open();
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
string name = reader.IsDBNull(0)
? string.Empty : reader.GetString(0);
int age = reader.IsDBNull(1) ? 0 : reader.GetInt32(1);
Person person = new Person(name, age);
personList.Add(person);
}
}
}
}
}
catch (Exception e) { //throw application exception }
return personList;
}
Redundant Code
Erich Eichinger | SpringSource
public IList FindAllPeople() {
IList personList = new ArrayList();
try
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
string sql = "select Name, Age from ...";
using (SqlCommand command = new SqlCommand(sql, connection))
{
connection.Open();
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
string name = reader.IsDBNull(0)
? string.Empty : reader.GetString(0);
int age = reader.IsDBNull(1) ? 0 : reader.GetInt32(1);
Person person = new Person(name, age);
personList.Add(person);
}
}
}
}
}
catch (Exception e) { //throw application exception }
return personList;
}
The bold matters - the rest is
boilerplate
Null values could
be handled
better
What about transaction
management?
AdoTemplate: Leightweight Mapping
Erich Eichinger | SpringSource
public class PersonDao : AdoDaoSupport {
private string cmdText = "select Name, Age from Person";
public virtual IList<Person> FindAllPeople() {
return AdoTemplate.QueryWithRowMapperDelegate<Account>(CommandType.Text,
cmdText,
delegate(IDataReader dataReader, int rowNum) {
Person person = new Person();
person.Name = dataReader.GetString(0);
person.Age = dataReader.GetInt32(1);
return person;
});
}
}
}
Specify the command
Do the work for each iteration
AdoTemplate in a Nutshell
int userCount = (int) adoTemplate.ExecuteScalar(
CommandType.Text,
"SELECT COUNT(0) FROM USER");
• Acquisition of the connection
• Creation of the command
• Participation in the transaction
• Execution of the statement
• Processing of the result set
• Handling of any exception
• Display or rollback on warnings
• Dispose of the reader, command
• Dispose of the connection
All handled by
the template
Erich Eichinger | SpringSource
DAO implementation - AdoTemplate
• Can still „fall-down‟ to lowest levelprivate string cmdText =
"select count(*) from Customers where PostalCode = @PostalCode";
public virtual int FindCountWithPostalCode(string postalCode)
{
return AdoTemplate.Execute<int>(delegate(DbCommand command)
{
command.CommandText = cmdText;
DbParameter p = command.CreateParameter();
p.ParameterName = "@PostalCode";
p.Value = postalCode;
command.Parameters.Add(p);
return (int) command.ExecuteScalar();
});
}
Erich Eichinger | SpringSource
Transaction Management
• How to satisfy the requirement
– “The service layer must be transactional”
• Adding boilerplate code in the service layer
(programmatic transaction management)
– Is prone to errors; of omission, cut-n-paste
– Ties implementation to transaction implementation
• The solution
– Declarative transaction management
– “Say what to do, not how to do it”
Erich Eichinger | SpringSource
* Promotion to distributed transaction for common designs
Always distributed for Oracle, Sybase, DB2, MySql
** Only for WCF services
Local Distributed Declarative
ADO.NET
EnterpriseServices
System.Transactions *
WCF** *
.NET Transaction Management
Erich Eichinger | SpringSource
Spring.NET Transaction Management
• Consistent model for different transaction APIs
• IPlatformTransactionManager
– AdoTransactionManager
– ServiceDomainPlatformTransactionManager
– TxScopePlatformTransactionManager
– HibernateTransactionManager
• Declarative transaction demarcation strategies
– XML or Attributes
• Using a different transaction manager is a change of
configuration, not code
Erich Eichinger | SpringSource
Declarative Transactions using
Attributes public class SimpleBankService : IBankService {
[Transaction()]
public Account Create(string name){
Account account = accountDao.Create(name)
if (RequiresSecurity(account)) {
securityDao.CreateCredentials(account);
}
return account;
}
. . .
}
<object id=“bankService" type=“MyServices.SimpleBankService, MyAssembly“>
<property name=“AccountDao” ref=“accountDao” /><property name=“SecurityDao” ref=“securityDao” />
</object>
<tx:attribute-driven/>
Declarative Transactions using XML<object id="bankService”
type=“MyServices.SimpleBankService, MyAssembly">
. . .
</object>
<tx:advice id="txAdvice">
<tx:attributes>
<tx:method name="Get*"
timeout="1000" isolation="RepeatableRead"
no-rollback-for="SillyException"/>
</tx:attributes>
</tx:advice>
<object id="serviceOperation“ type=“RegularExpressionPointcut">
<property name="pattern" value=“MyServices.*Service.*"/>
</object>
<aop:config>
<aop:advisor pointcut-ref="serviceOperation”
advice-ref="txAdvice"/>
</aop:config>
What to do…
Where to do it…
Tie them together
Demo
Erich Eichinger | SpringSource
Agenda
• The who, what and why of Spring.NET?
• Feature Overview
• Dependency Injection
• Data Access and Declarative Transaction
Management
• Aspect Orientierted Programming
• Spring.NET specific Features
• Roadmap
Erich Eichinger | SpringSource
Aspect Oriented Programming (AOP)
• Allows a software component to be decorated with
additional behavior
– In a generic, targeted manner
• The container is responsible for “weaving in” the
behavior
– Behavior is implemented in a single location (what)
– Specify where to apply behavior (where)
– An aspect encapsulates the where + what
• Complements Object-Oriented Programming
• Terminology
– „what‟ = advice
– „where‟ = pointcut
Erich Eichinger | SpringSource
AOP in Spring.NET
• No dynamic proxies provided by BCL
• Spring creates dynamic proxy using Reflection.Emit
• Methods non-virtual by default
– Interception for interfaces or virtual methods
• Future integration with PostSharp
– Compile time IL code weaver
– [Configurable] and [Aspect] support
• AOP schema for configuration
– No pointcut language
Erich Eichinger | SpringSource
Pointcuts
• Match attribute type
– <tx:attribute-driven/> is XML shorthand for this
• Match namespace or type via regular expression
• Match spring objects by „name‟
• Control flow
– Dynamic
– Match if execution is „beneath‟ a class in the call stack
• Custom
• Composable
Erich Eichinger | SpringSource
Agenda
• The who, what and why of Spring.NET?
• Feature Overview
• Dependency Injection
• Data Access and Declarative Transaction
Management
• Aspect Oriented Programming
• Spring.NET specific Features
• Roadmap
Erich Eichinger | SpringSource
Spring Expression Language (SpEL)
• Enables object graph navigation
– Properties, methods, aggregators . . .
• Motivation
– Adds significant value to IoC containers
– Fills in the cracks to script simple behavior
• Needed for
– Data binding, validation, aspect library . . .
• Forget hand-coded reflection
• Generally useful in any application
Erich Eichinger | SpringSource
SpEL Features
• Object graph navigation
• Method invocation
• Object construction
• Arithmetic operations
• Logical operations
• List projection and selection
• Collection aggregators and processors
• User defined functions (closures)
• Lambda functions
Erich Eichinger | SpringSource
SpEL Usage
• ExpressionEvaluator
– Simple to use
– Parses expression for each execution
– Useful for one-off evaluations
• Use Expression.Parse and IExpression for repeated
execution
Person aleks = new Person(“Aleks”, Gender.Male, 32);
ExpressionEvaluator.GetValue(aleks, “Name”); // Aleks
ExpressionEvaluator.GetValue(aleks, “Age”); // 32
ExpressionEvaluator.GetValue(aleks, “Gender == Gender.Male”); // true
ExpressionEvaluator.SetValue(aleks, “Name”, “Aleksandar”);
Erich Eichinger | SpringSource
IoC Container integration
• SpEL used to evaluate property name
• „ref‟, „value‟ and also „expression‟
<object id=“person” type=“Person, MyApp”>
<property name=“Children[0]” ref=“anotherChild”/>
<property name=“Address.City” value=“New York”/>
<property name=“FavoriteDate” expression=“DateTime.Today”/>
</object>
Erich Eichinger | SpringSource
Aspect Library
• Common use-cases
– Logging
– Transaction Management
– Caching
– Exception Translation
– Performance Monitoring
– Object Pooling
– Custom Business Rules
– Security
Erich Eichinger | SpringSource
Aspect Library
• Configure pre-built aspects
• Example: Exception Translation
– Configuration using DSL
• Other actions
– log
– translate
– replace
– return
– swallow
on exception name ArithmeticException
wrap MyServices.ServiceOperationException
Erich Eichinger | SpringSource
Aspect Library and Expression
Language
• A „Little Language‟
– Small but powerful
• Lets you add a little bit of glue code
• If writing more than a few lines
– Subclass advice and write C# based implementation
on exception
( #e is T(SqlException) &&
#e.Errors[0].Number in { 154, 165, 178 } )
translate
new DataAccessException(„Error in #method.Name‟, #e)
Erich Eichinger | SpringSource
Demo
Erich Eichinger | SpringSource
Retry Aspect
• Remote calls are unreliable
• If remote operation is idempotent, can
retry until achieve success
– Can apply advice based on attribute
[Idempotent]
• Similar approach as exception adviceon exception name ArithmeticException retry 3x delay 1s
Erich Eichinger | SpringSource
Retry Advice Configuration
• Leverage SpEL
– Specify formula for retry interval
– Specify exception to act upon
<object name="exceptionHandlingAdvice"
type="Spring.Aspects.RetryAdvice, Spring.Aop">
<property name="retryExpression"
value="on exception name ArithmeticException retry 3x delay 1s"/>
</object>
on exception name FaultException
retry 3x rate (1*#n + 0.5)
Erich Eichinger | SpringSource
Spring ASP.NET Framework Goals
• “Embrace and extend” ASP.NET
• Pain points with ASP.NET are addressed
– Pages depend on middle-tier services, how to obtain?
– Data binding is only in one direction and supported only by some
controls
– Need to manage data model supporting the page
– Lifecycle methods should be at higher level of abstraction
– Data validation is tied to the UI and is simplistic
• Simplify ASP.NET development as much as possible by
filling in the gaps
Erich Eichinger | SpringSource
DI for Pages, Controls, Modules, Providers
• DI features work with standard ASP.NET
page and controls
<object type="Login.aspx">
<property name="Title" value="Hello World"/>
<property name="Authenticator"
ref="authenticationService"/>
</object>
<object type="CustomControl.ascx">
<property name="Message" value=“Hello from Control"/>
</object>
Erich Eichinger | SpringSource
Handling form submission:
Without Spring.NET
public class MyPage : Page
{
public void ProcessBuyOrder(object sender, EventArgs args)
{
try
{
string stockSymbol = txtStockSymbol.Text;
int numberOfShares = int.Parse(txtNumberOfShares.Text);
BuyOrder order = new BuyOrder(stockSymbol, numberOfShares);
ITradingService tradingService = ServiceLocator.GetService(...);
OrderConfirmation confirmation = tradingService.ProcessOrder(order);
Context.Items["confirmation"] = confirmation;
Server.Transfer("BuyConfirmation.aspx");
}
catch (ParseException e)
{
// handle exception (sometimes this is difficult as well)
}
}
}
Erich Eichinger | SpringSource
Handling form submission:
With Spring.NET
public class MyPage : Spring.Web.UI.Page
{
private BuyOrder order;
private OrderConfirmation confirmation;
private ITradingService tradingService;
// properties omitted
protected override InitializeDataBindings()
{
BindingManager.AddBinding(“txtStockSymbol.Text”, “Order.StockSymbol”);
BindingManager.AddBinding(“txtNumberOfShares.Text”, “Order.NumberOfShares”)
.SetErrorMessage(“Invalid Number of Shares”, “errNumberOfShares”);
}
public void ProcessBuyOrder(object sender, EventArgs args)
{
if (ValidationErrors.IsEmpty && Validate(order, orderValidator))
{
confirmation = tradingService.ProcessOrder(order);
SetResult(“buyConfirmation”);
}
}
}
Erich Eichinger | SpringSource
Handling form submission with
Spring.NET's DataBindingPanel
// .aspx.cs
public class MyPage : Spring.Web.UI.Page {
public BuyOrder Order { get {...} }
public void ProcessBuyOrder(object sender, EventArgs args) {
if (ValidationErrors.IsEmpty && Validate(this.Order, orderValidator)) {
confirmation = tradingService.ProcessOrder(this.Order);
SetResult(“buyConfirmation”);
}
}
}
// .aspx
<spring:DataBindingPanel runat="server">
<asp:TextBox runat="server"
ID="txtNumberOfShares"
BindingTarget="Order.NumberOfShares"
MessageId=" Invalid Number of Shares"
ErrorProviders="errNumberOfShares" />
...
</spring:DataBindingPanel>
Spring ASP.NET Framework Summary
• DI enable ASP.NET
• Bi-directional data binding
• UI independent Data Validation
• Object scopes
– application, session, request
• Code becomes more business and less
infrastructure focused
– Data model management
Agenda
• Was, Woher & Warum Spring.NET?
• Feature Überblick
• Dependency Injection
• Data Access and Declarative Transaction
Management
• Aspektorientierte Programmierung
• Spring.NET spezifische Features
• Roadmap
Erich Eichinger | SpringSource
New Features 1.2
• Messaging – MSMQ
– NMS
– ActiveMQ
• WCF Integration
• Scheduling – Quartz.NET
Erich Eichinger | SpringSource
Spring.NET 2.0 roadmap
• DI feature set at Spring Java 2.5 level
• WCF binding for Messaging
• ASP.NET MVC Integration
• Support more unit testing frameworks
• REST
• Dynamic Language Integration
• Other projects
– JavaConfig -> #Config
– Spring Batch/Integration for .NET...
Erich Eichinger | SpringSource
Future Directions
• Ecosystem projects
– Spring.NET IDE
– Cache implementations
– Threading library (think java.util.concurrent)
– .... your ideas here ;-)
Erich Eichinger | SpringSource
Get Started
• Download from www.springframework.net
– Many samples and extensive reference manual
• Support, Training, Consulting available from
SpringSource
– www.springsource.com
• Upcoming German Training:
– 4.-6. Nov., München
Erich Eichinger | SpringSource
Q & A
Erich Eichinger | SpringSource