Results 1 to 6 of 6

Thread: Exporting a class with introductions

  1. #1
    Join Date
    Jun 2008
    Posts
    2

    Unhappy Exporting a class with introductions

    I seem to be having difficulties exporting a web service based on a class with aop introductions. Here's a sample config XML:

    Code:
    <object id="Mixin" type="PG.Service.Mixin, PG.Service"/>
    <object id="PaGERService" type="Spring.Aop.Framework.ProxyFactoryObject, Spring.Aop">
      <property name="Target">
        <object type="PG.Service.PaGER, PG.Service"/>
      </property>
      <property name="IntroductionNames">
        <list>
          <value>Mixin</value>
        </list>
      </property>
    </object>
    <object id="PaGERWebService" type="Spring.Web.Services.WebServiceExporter, Spring.Web">
      <property name="TargetName" value="PaGERService"/>
      <property name="Namespace" value="(cannot post urls yet)"/>
    </object>
    I've tried it as above, with the target object separately-defined and referenced by ID, and via ObjectNameAutoProxyCreator (with the introduction named in the "InterceptorNames" list). In all cases, I get the same result at context load time:

    Code:
    [NotSupportedException: Cannot serialize interface Spring.Aop.Framework.IAopProxy.]
       System.Xml.Serialization.TypeDesc.CheckSupported() +76
       System.Xml.Serialization.TypeScope.GetTypeDesc(Type type, MemberInfo source, Boolean directReference, Boolean throwOnError) +308
       System.Xml.Serialization.TypeScope.GetTypeDesc(Type type) +36
       System.Xml.Serialization.XmlReflectionImporter.ImportMemberMapping(XmlReflectionMember xmlReflectionMember, String ns, XmlReflectionMember[] xmlReflectionMembers, Boolean rpc, Boolean openModel) +168
       System.Xml.Serialization.XmlReflectionImporter.ImportMembersMapping(XmlReflectionMember[] xmlReflectionMembers, String ns, Boolean hasWrapperElement, Boolean rpc, Boolean openModel) +291
    
    [InvalidOperationException: There was an error reflecting 'value'.]
       System.Xml.Serialization.XmlReflectionImporter.ImportMembersMapping(XmlReflectionMember[] xmlReflectionMembers, String ns, Boolean hasWrapperElement, Boolean rpc, Boolean openModel) +1042
       System.Xml.Serialization.XmlReflectionImporter.ImportMembersMapping(String elementName, String ns, XmlReflectionMember[] members, Boolean hasWrapperElement, Boolean rpc, Boolean openModel, XmlMappingAccess access) +183
       System.Web.Services.Protocols.SoapReflector.ImportMembersMapping(XmlReflectionImporter xmlImporter, SoapReflectionImporter soapImporter, Boolean serviceDefaultIsEncoded, Boolean rpc, SoapBindingUse use, SoapParameterStyle paramStyle, String elementName, String elementNamespace, Boolean nsIsDefault, XmlReflectionMember[] members, Boolean validate, Boolean openModel, String key, Boolean writeAccess) +765
       System.Web.Services.Protocols.SoapReflector.ReflectMethod(LogicalMethodInfo methodInfo, Boolean client, XmlReflectionImporter xmlImporter, SoapReflectionImporter soapImporter, String defaultNs) +4263
    
    [InvalidOperationException: Method PaGERWebService.Spring.Aop.Framework.ITargetAware.set_TargetProxy can not be reflected.]
       System.Web.Services.Protocols.SoapReflector.ReflectMethod(LogicalMethodInfo methodInfo, Boolean client, XmlReflectionImporter xmlImporter, SoapReflectionImporter soapImporter, String defaultNs) +10259
       System.Web.Services.Description.SoapProtocolReflector.ReflectMethod() +149
       System.Web.Services.Description.ProtocolReflector.ReflectBinding(ReflectedBinding reflectedBinding) +1980
       System.Web.Services.Description.ProtocolReflector.Reflect() +736
       System.Web.Services.Description.ServiceDescriptionReflector.ReflectInternal(ProtocolReflector[] reflectors) +501
       System.Web.Services.Description.ServiceDescriptionReflector.Reflect(Type type, String url) +165
       System.Web.Services.Protocols.DocumentationServerType..ctor(Type type, String uri) +213
       System.Web.Services.Protocols.DocumentationServerProtocol.Initialize() +390
       System.Web.Services.Protocols.ServerProtocol.SetContext(Type type, HttpContext context, HttpRequest request, HttpResponse response) +70
       System.Web.Services.Protocols.ServerProtocolFactory.Create(Type type, HttpContext context, HttpRequest request, HttpResponse response, Boolean& abortProcessing) +104
    
    [InvalidOperationException: Unable to handle request.]
       System.Web.Services.Protocols.ServerProtocolFactory.Create(Type type, HttpContext context, HttpRequest request, HttpResponse response, Boolean& abortProcessing) +337
       System.Web.Services.Protocols.WebServiceHandlerFactory.CoreGetHandler(Type type, HttpContext context, HttpRequest request, HttpResponse response) +236
    
    [InvalidOperationException: Failed to handle request.]
       System.Web.Services.Protocols.WebServiceHandlerFactory.CoreGetHandler(Type type, HttpContext context, HttpRequest request, HttpResponse response) +431
    
    [TargetInvocationException: Exception has been thrown by the target of an invocation.]
       System.RuntimeMethodHandle._InvokeMethodFast(Object target, Object[] arguments, SignatureStruct& sig, MethodAttributes methodAttributes, RuntimeTypeHandle typeOwner) +0
       System.RuntimeMethodHandle.InvokeMethodFast(Object target, Object[] arguments, Signature sig, MethodAttributes methodAttributes, RuntimeTypeHandle typeOwner) +72
       System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks) +371
       System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) +29
       System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters) +17
       Spring.Web.Services.WebServiceHandlerFactory.System.Web.IHttpHandlerFactory.GetHandler(HttpContext context, String requestType, String url, String path) in l:\projects\Spring.Net\src\Spring\Spring.Web\Web\Services\WebServiceHandlerFactory.cs:105
       System.Web.HttpApplication.MapHttpHandler(HttpContext context, String requestType, VirtualPath path, String pathTranslated, Boolean useAppConfig) +401
       System.Web.MapHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +183
       System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +191
    Any thoughts? I guess I could understand if the introduced interface is not added to the public web service (though that would be great). But the mixin I'm using is only for internal use within the service implementation, so even if it's not exported I'd be happy.

  2. #2
    Mark Pollack is offline Spring.NET Co-Lead Spring TeamSpring User
    Join Date
    Sep 2004
    Location
    New York, NY
    Posts
    1,683

    Default

    Hi,

    Not sure what is going on here off the top of my head, but you can explicitly list the list of interfaces in the exporter. That might help. See below.

    Code:
    <object id="PaGERWebService" type="Spring.Web.Services.WebServiceExporter, Spring.Web">
      <property name="TargetName" value="PaGERService"/>
      <property name="Namespace" value="(cannot post urls yet)"/>
      <property name=“Interfaces">
        <list> 
          <value>IPaGER, PG.Services.Interfaces</value>
        </list>
      </property>
    </object>
    


    There is also an JIRA issue to make many of the AOP classes serializable, so that might be related, I'll need to investigate more.

    Cheers,
    Mark



  3. #3
    Join Date
    Oct 2005
    Location
    Toulouse, France
    Posts
    1,409

    Default

    Hi,

    Which version of Spring.NET are you using.
    Anyway, like Mark said, explicitly list the list of interfaces in the exporter should work.

    - Bruno
    My english is as poor as my taylor is rich

  4. #4
    Join Date
    Jun 2008
    Posts
    2

    Default

    I feel like I'm closer now, thanks for the tip on listing out the interfaces. However, now that the full web service list is showing up, I'm having two new, distinct problems. Here's a concise version of my new XML:

    Code:
      <object id="ServiceStatsAccumulator" type="PG.Service.ServiceStatsAccumulator, PG.Service"/>
      <object id="ServiceStatsReporter" type="PG.Service.ServiceStatsMixin, PG.Service"/>
    
      <object id="PaGERService" type="Spring.Aop.Framework.ProxyFactoryObject, Spring.Aop">
        <property name="Target">
          <object type="PG.Service.PaGER, PG.Service"/>
        </property>
        <property name="InterceptorNames">
          <list>
            <value>ServiceStatsAccumulator</value>
          </list>
        </property>
        <property name="IntroductionNames">
          <list>
            <value>ServiceStatsReporter</value>
          </list>
        </property>
      </object>
    
      <object id="PaGERWebService" type="Spring.Web.Services.WebServiceExporter, Spring.Web">
        <property name="TargetName" value="PaGERService"/>
        <property name="Namespace" value="..."/>
        <property name="Interfaces">
          <list>
            <value>PG.Contract.IPaGER, PG.Contract</value>
            <value>PG.Contract.IServiceStats, PG.Contract</value>
          </list>
        </property>
      </object>
    When I hit any method that has not been introduced by IServiceStats (the "normal" methods of IPager), the accumulator fires correctly and attempts to cast the invocation.Target to IServiceStatsAdvice. Assuming the introduction has succeeded, I believe the cast should work (ServiceStatsMixin implements this interface), but I'm getting an InvalidCastException.

    Second, when I hit the "GetServiceStats" method and try to access the mixed-in method to report on my accumulated stats, I get an error that reads "The HTTP verb POST used to access path '/PG.Web/PaGERWebService.asmx/PG.Contract.IServiceStats.GetServiceStats' is not allowed". Here it would appear that the method did indeed get introduced, but did not get wrapped as a web service method. Any idea what I'm doing wrong here?

    For reference, I have tried wrapping the mixin class in a DefaultIntroductionAdvisor-inherited class. I have also tried listing the two interfaces in the "ProxyInterfaces" property of ProxyFactoryObject. I get the same results in all cases.

  5. #5
    Join Date
    Oct 2005
    Location
    Toulouse, France
    Posts
    1,409

    Default

    Hi,

    I reproduced your pb, I'm investigating...

    - Bruno
    My english is as poor as my taylor is rich

  6. #6
    Join Date
    Oct 2005
    Location
    Toulouse, France
    Posts
    1,409

    Default

    Quote Originally Posted by ShadyG View Post
    When I hit any method that has not been introduced by IServiceStats (the "normal" methods of IPager), the accumulator fires correctly and attempts to cast the invocation.Target to IServiceStatsAdvice. Assuming the introduction has succeeded, I believe the cast should work (ServiceStatsMixin implements this interface), but I'm getting an InvalidCastException.
    invocation.Target returns the target object, here the instance of 'PG.Service.PaGER'. Use invocation.Proxy instead, you should be able to cast it as IServiceStatsAdvice.

    Quote Originally Posted by ShadyG View Post
    Second, when I hit the "GetServiceStats" method and try to access the mixed-in method to report on my accumulated stats, I get an error that reads "The HTTP verb POST used to access path '/PG.Web/PaGERWebService.asmx/PG.Contract.IServiceStats.GetServiceStats' is not allowed". Here it would appear that the method did indeed get introduced, but did not get wrapped as a web service method. Any idea what I'm doing wrong here?
    The proxy generated explicitly implements the introduction interface, that's why you got a method name prefixed by the full interface type name.
    It seems the asmx web interface does not handle it very well, but if you create another project and reference it as a web reference, you will be able to call it.
    Dots will be removed from the name. Method will be named 'PGContractIServiceStatsGetServiceStats'.

    Anyway, if you still want to use the asmx interface, you can use the WebMethodAttribute and MessageName property :
    Code:
    <object id="PaGERWebService" type="Spring.Web.Services.WebServiceExporter, Spring.Web">
       <property name="TargetName" value="PaGERService"/>
       <property name="Namespace" value="..."/>
       <property name="MemberAttributes">
          <dictionary>
             <entry key="PG.Contract.IServiceStats.GetServiceStats">
                <object type="System.Web.Services.WebMethodAttribute, System.Web.Services">
                   <property name="MessageName" value="GetServiceStats"/>
                </object>
            </entry>
          </dictionary>
       </property>
    </object>

    Cheers,
    Bruno
    My english is as poor as my taylor is rich

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •