vanccurtis
03-13-2007, 02:43 PM
I have web services using .NET's HttpSessionState, and I'd like to AOP some logging at the web service level (as opposed to lower layers). I seem to be able to do Web Services and Sessions, or Web Services and AOP, but not both together. As soon as I add the I don't think I've seen anywhere in the documentation or examples which actually explicitly says that you can do both, so I'm wondering if I'm trying to do something unsupported or just really backwards! I'm still relatively new to .NET and Spring so I apologize in advance for the newbie-ness of the question.
I've included the web.config file and the mock session service C# code. It's in a standard VS2005 Web Service project, and the only other code dependency I'm using is the ConsoleLoggingAroundAdvice provided in the Spring examples (except I changed the output from the console to a Spring log4Net logger). I'm running my tests using Microsoft's development server from within VS2005. See more notes after files.
* web.config file (note that I've snipped the logging stuff and replaced w/ "..."):
-----------------------------------------------------------------------
<?xml version="1.0"?>
<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
<configSections>
<sectionGroup name="common">
<section name="logging"
type="Common.Logging.ConfigurationSectionHandler,
Common.Logging" />
</sectionGroup>
<sectionGroup name="spring">
<section name="context"
type="Spring.Context.Support.WebContextHandler, Spring.Web"/>
<section name="objects"
type="Spring.Context.Support.DefaultSectionHandler,
Spring.Core" />
</sectionGroup>
<section name="log4net"
type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"
/>
</configSections>
<system.web>
<httpModules>
<!-- need the WebSupportModule if you're using Spring's WebContextHandler
as opposed to just a ContextHandler above -->
<add name="Spring"
type="Spring.Context.Support.WebSupportModule, Spring.Web"/>
</httpModules>
<httpHandlers>
<add verb="*" path="*.asmx"
type="Spring.Web.Services.WebServiceHandlerFactory, Spring.Web"/>
</httpHandlers>
<webServices>
<protocols>
<add name="HttpGet"/>
<add name="HttpPost"/>
</protocols>
</webServices>
<compilation debug="true">
<assemblies>
<add assembly="nunit.framework, Version=2.2.9.0, Culture=neutral,
PublicKeyToken=96D09A1EB7F44A77"/>
<add assembly="System.Transactions, Version=2.0.0.0, Culture=neutral,
PublicKeyToken=B77A5C561934E089"/>
</assemblies>
</compilation>
<authentication mode="Windows" />
</system.web>
<common>
<logging>...</logging>
</common>
<spring>
<context type="Spring.Context.Support.WebApplicationContext, Spring.Web">
<!-- using section in App.config -->
<resource uri="config://spring/objects"/>
</context>
<objects xmlns="http://www.springframework.net" >
<description>Spring Web Services</description>
<object id="mockVwsSessionServiceTarget"
type="gov.va.medora.vws.facades.MockVwsSessionService">
</object>
<object id="mockVwsSessionServiceProxy"
type="Spring.Aop.Framework.ProxyFactoryObject">
<property name="TargetName" value="MockVwsSessionServiceTarget" />
<property name="InterceptorNames">
<list>
<value>aroundAdvice</value>
</list>
</property>
</object>
<object id="MockVwsSessionService"
type="Spring.Web.Services.WebServiceExporter, Spring.Web">
<property name="TargetName" value="mockVwsSessionServiceProxy"/>
<property name="Interfaces" value="gov.va.medora.vws.facades.IMockVwsSessionService" />
<property name="Namespace" value="http://vws.medora.va.gov"/>
<property name="Description" value="Sprung Mock Vws Service"/>
</object>
<object id="mockVwsSessionServiceTargetTwo"
type="gov.va.medora.vws.facades.MockVwsSessionService">
</object>
<object id="MockVwsSessionServiceTwo"
type="Spring.Web.Services.WebServiceExporter, Spring.Web">
<property name="TargetName" value="mockVwsSessionServiceTargetTwo"/>
<property name="Interfaces" value="gov.va.medora.vws.facades.IMockVwsSessionService" />
<property name="Namespace" value="http://vws.medora.va.gov"/>
<property name="Description" value="Sprung Mock Vws Service"/>
</object>
<!-- aroundAdvice just logs around any command -->
<object id="aroundAdvice"
type="gov.va.medora.vws.ConsoleLoggingAroundAdvice" />
</objects>
</spring>
<log4net>...
</log4net>
</configuration>
-----------------------------------------------------------
* MockVwsSessionServices
------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Text;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using Common.Logging;
using Spring.Context;
using Spring.Context.Support;
namespace gov.va.medora.vws.facades
{
/// <summary>
/// Revisiting Sessions and Web Services and Spring
/// </summary>
/// <remarks> This first attempt uses MS's WebMethod attributs</remarks>
[WebService(Namespace = "http://vws.medora.va.gov")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class MockVwsSessionService : System.Web.Services.WebService, IMockVwsSessionService
{
private static readonly ILog LOG = LogManager.GetLogger(System.Reflection.MethodBase. GetCurrentMethod().DeclaringType);
Boolean connected;
string connectionId;
public MockVwsSessionService()
{
}
/// <summary>
/// Basically create a fake connected state and store it some how...
/// </summary>
/// <param name="someConnection"></param>
/// <returns></returns>
[WebMethod(EnableSession = true)]
public string connect(string someConnection)
{
Session["connection"]="yes";
connectionId = someConnection;
Session["connectionId"] = connectionId;
Connected = true;
return ("Session " + someConnection + " has connection: " + (string)Session["connection"] + " and is Connected: " + Connected);
}
/// <summary>
/// Disconnects from our fake connected state
/// </summary>
/// <returns></returns>
[WebMethod(EnableSession = true)]
public string disconnect()
{
Session["connection"]="no";
Connected = false;
return ("Session " + (string)Session["connectionId"] + " has connection: " + (string)Session["connection"] + " and is Connected: " + Connected);
}
public Boolean Connected
{
[WebMethod(EnableSession = true)]
get { return connected; }
[WebMethod(EnableSession = true)]
set { connected = value; }
}
[WebMethod(EnableSession = true)]
public string isConnected()
{
return ("Session " + (string)Session["connectionId"] + ": Connected: " + Connected + " and has Session: " + (string)Session["connection"]);
}
}
public interface IMockVwsSessionService
{
string connect(string someConnection);
string disconnect();
string isConnected();
Boolean Connected {get; set; }
}
}
-------------------------------------------------------------
When I use the generated pages to look at the target service (i.e. MockVwsSessionServiceTarget) directly, I don't have any problems reading or writing from HttpSessionState in the connect() and disconnect() methods. When I point to the WebServiceExporter (i.e. MockVwsSessionService) then the HttpSessionState breaks. This is the case whether I go through the AOP proxy or not -- see MockVwsSessionService vs. MockVwsSessionServiceTwo.
I'm not using Spring's IApplicationContext in the example above, but it looks like I can only retrieve objects wired in the Spring config file, not actually put objects back into the application context -- true?
Also, using Spring's configuration with MemberAttributes doesn't seem to make a difference.
So, to restate, my goal is to have web services w/ sessions and be able to AOP those web services for logging or other cross-cutting concerns. Any help will be greatly appreciated.
thanks,
van.
I've included the web.config file and the mock session service C# code. It's in a standard VS2005 Web Service project, and the only other code dependency I'm using is the ConsoleLoggingAroundAdvice provided in the Spring examples (except I changed the output from the console to a Spring log4Net logger). I'm running my tests using Microsoft's development server from within VS2005. See more notes after files.
* web.config file (note that I've snipped the logging stuff and replaced w/ "..."):
-----------------------------------------------------------------------
<?xml version="1.0"?>
<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
<configSections>
<sectionGroup name="common">
<section name="logging"
type="Common.Logging.ConfigurationSectionHandler,
Common.Logging" />
</sectionGroup>
<sectionGroup name="spring">
<section name="context"
type="Spring.Context.Support.WebContextHandler, Spring.Web"/>
<section name="objects"
type="Spring.Context.Support.DefaultSectionHandler,
Spring.Core" />
</sectionGroup>
<section name="log4net"
type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"
/>
</configSections>
<system.web>
<httpModules>
<!-- need the WebSupportModule if you're using Spring's WebContextHandler
as opposed to just a ContextHandler above -->
<add name="Spring"
type="Spring.Context.Support.WebSupportModule, Spring.Web"/>
</httpModules>
<httpHandlers>
<add verb="*" path="*.asmx"
type="Spring.Web.Services.WebServiceHandlerFactory, Spring.Web"/>
</httpHandlers>
<webServices>
<protocols>
<add name="HttpGet"/>
<add name="HttpPost"/>
</protocols>
</webServices>
<compilation debug="true">
<assemblies>
<add assembly="nunit.framework, Version=2.2.9.0, Culture=neutral,
PublicKeyToken=96D09A1EB7F44A77"/>
<add assembly="System.Transactions, Version=2.0.0.0, Culture=neutral,
PublicKeyToken=B77A5C561934E089"/>
</assemblies>
</compilation>
<authentication mode="Windows" />
</system.web>
<common>
<logging>...</logging>
</common>
<spring>
<context type="Spring.Context.Support.WebApplicationContext, Spring.Web">
<!-- using section in App.config -->
<resource uri="config://spring/objects"/>
</context>
<objects xmlns="http://www.springframework.net" >
<description>Spring Web Services</description>
<object id="mockVwsSessionServiceTarget"
type="gov.va.medora.vws.facades.MockVwsSessionService">
</object>
<object id="mockVwsSessionServiceProxy"
type="Spring.Aop.Framework.ProxyFactoryObject">
<property name="TargetName" value="MockVwsSessionServiceTarget" />
<property name="InterceptorNames">
<list>
<value>aroundAdvice</value>
</list>
</property>
</object>
<object id="MockVwsSessionService"
type="Spring.Web.Services.WebServiceExporter, Spring.Web">
<property name="TargetName" value="mockVwsSessionServiceProxy"/>
<property name="Interfaces" value="gov.va.medora.vws.facades.IMockVwsSessionService" />
<property name="Namespace" value="http://vws.medora.va.gov"/>
<property name="Description" value="Sprung Mock Vws Service"/>
</object>
<object id="mockVwsSessionServiceTargetTwo"
type="gov.va.medora.vws.facades.MockVwsSessionService">
</object>
<object id="MockVwsSessionServiceTwo"
type="Spring.Web.Services.WebServiceExporter, Spring.Web">
<property name="TargetName" value="mockVwsSessionServiceTargetTwo"/>
<property name="Interfaces" value="gov.va.medora.vws.facades.IMockVwsSessionService" />
<property name="Namespace" value="http://vws.medora.va.gov"/>
<property name="Description" value="Sprung Mock Vws Service"/>
</object>
<!-- aroundAdvice just logs around any command -->
<object id="aroundAdvice"
type="gov.va.medora.vws.ConsoleLoggingAroundAdvice" />
</objects>
</spring>
<log4net>...
</log4net>
</configuration>
-----------------------------------------------------------
* MockVwsSessionServices
------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Text;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using Common.Logging;
using Spring.Context;
using Spring.Context.Support;
namespace gov.va.medora.vws.facades
{
/// <summary>
/// Revisiting Sessions and Web Services and Spring
/// </summary>
/// <remarks> This first attempt uses MS's WebMethod attributs</remarks>
[WebService(Namespace = "http://vws.medora.va.gov")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class MockVwsSessionService : System.Web.Services.WebService, IMockVwsSessionService
{
private static readonly ILog LOG = LogManager.GetLogger(System.Reflection.MethodBase. GetCurrentMethod().DeclaringType);
Boolean connected;
string connectionId;
public MockVwsSessionService()
{
}
/// <summary>
/// Basically create a fake connected state and store it some how...
/// </summary>
/// <param name="someConnection"></param>
/// <returns></returns>
[WebMethod(EnableSession = true)]
public string connect(string someConnection)
{
Session["connection"]="yes";
connectionId = someConnection;
Session["connectionId"] = connectionId;
Connected = true;
return ("Session " + someConnection + " has connection: " + (string)Session["connection"] + " and is Connected: " + Connected);
}
/// <summary>
/// Disconnects from our fake connected state
/// </summary>
/// <returns></returns>
[WebMethod(EnableSession = true)]
public string disconnect()
{
Session["connection"]="no";
Connected = false;
return ("Session " + (string)Session["connectionId"] + " has connection: " + (string)Session["connection"] + " and is Connected: " + Connected);
}
public Boolean Connected
{
[WebMethod(EnableSession = true)]
get { return connected; }
[WebMethod(EnableSession = true)]
set { connected = value; }
}
[WebMethod(EnableSession = true)]
public string isConnected()
{
return ("Session " + (string)Session["connectionId"] + ": Connected: " + Connected + " and has Session: " + (string)Session["connection"]);
}
}
public interface IMockVwsSessionService
{
string connect(string someConnection);
string disconnect();
string isConnected();
Boolean Connected {get; set; }
}
}
-------------------------------------------------------------
When I use the generated pages to look at the target service (i.e. MockVwsSessionServiceTarget) directly, I don't have any problems reading or writing from HttpSessionState in the connect() and disconnect() methods. When I point to the WebServiceExporter (i.e. MockVwsSessionService) then the HttpSessionState breaks. This is the case whether I go through the AOP proxy or not -- see MockVwsSessionService vs. MockVwsSessionServiceTwo.
I'm not using Spring's IApplicationContext in the example above, but it looks like I can only retrieve objects wired in the Spring config file, not actually put objects back into the application context -- true?
Also, using Spring's configuration with MemberAttributes doesn't seem to make a difference.
So, to restate, my goal is to have web services w/ sessions and be able to AOP those web services for logging or other cross-cutting concerns. Any help will be greatly appreciated.
thanks,
van.