Re: Provide implicit objects to mapped service methods

View: New views
4 Messages — Rating Filter:   Alert me  

Parent Message unknown Re: Provide implicit objects to mapped service methods

by welo :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Joe,
 
thx for looking into this! I moved this thread to the dev list since implementing this feature will require some changes to dwr.
 
Yes, extending DefaultRemoter to allow defining a list of 'ignored'  types seems to be the best solution. Since there is an obvious tie between ignored classes and a correctly registered corresponding converter I wonder whether an additional interface for converters would make sense, something like:
 
public interface ContextConverter {
  void Class[] getContextTypes();
}
 
Not sure about the naming yet, the idea is that these values are not part of the RPC but make up the execution context of the method. This assumes that ServletConverter is usually used to retrieve values like locale, current user, user settings etc.
 
DefaultRemoter could query ConverterManager to get a list of all types defined by converters implementing this interface. Those type will not be exposed in the Javascript client interface (and use fake parameters as it is implemented now). This would also require a change to the ConverterManager interface.
 
What do you think?
 
I have also considered a solution that would omit fake parameters on the client side completely, by altering BaseMarshaller to reflect such server side generated parameters during binding. But the concept of 1:1 mapping of method signatures between client side and server side affects large parts of the code, and the feature is probably not important enough to justify a greater code change.
 
I will code my changes against the HEAD, I guess.
 
I'd appreciate any feedback,
 
 
Werner

 
On 6/8/07, Joe Walker <joe@...> wrote:

Hi,

Sorry for the slow reply.

I think that the easy solution is to create a UserContextConverter which uses the techniques demonstrated in ServletConverter to get access to the HttpServletRequest from which a UserContext object can be created and returned.

From the JS POV, you would just pass in 'null' in place of a UserContext, and the converter would 'convert' null to a valid object.

You could alter DefaultRemoter to use something other than LocalUtil.isServletClass() to get the 'ignored classes'.

Joe.


On 5/30/07, werner loibl <welo.fpw9@...> wrote:
Hi,

I would like to provide a mechanism similar to the one currently implemented in dwr that allows adding javax.servlet.http.* types (such as HttpServletRequest) as part of the method signature of a service. The current feature will pass the current request, response, etc in case the method signature defines the equivalent type.
I intend to define a UserContext type that allows querying the current user and other information on the execution context. Dwr should implicitly create a UserContext object if the method signature defines an argument of this type. Though this will actually be retrieved via the HttpServletRequest resp. HttpSession I want to decouple the service implementation from the javax.servlet API. This is to ease testing and to allow creating an API layer that is not tied to the servlet spec. (To be honest, I'm not absolutely sure whether this will work out or not, or will make sense in the end, but I have a good feeling about it ;) ).

Taking a look at ServletConverter and DefaultRemoter it seems that this behaviour is currently hard-wired in dwr. Whereas it is possible to define a Converter that will create the required UserContext object based on the current HttpServletRequest (that can be retrieved from the ThreadLocal WebContext attribute as done by ServletConverter), the DefaultRemoter does not allow extending this behaviour easily. DefaultRemoter will add a dummy variable (with value=false) for every javax.servlet.http type encountered when creating the Javascript service wrapper, but this behaviour is hard-wired and not extensible (see DefaultRemoter#getMethodJS, which is private). The dummy variable is required otherwise BaseCallMarshaller#findMethod will not find the correct service method since the number of arguments of the ajax call does not match the number of method parameters on the service bean.

Other solutions I came up with so far:
 * Create a wrapping layer around my services that will do the conversion and delegate to the service bean passing the created UserContext. This might be automated by using a custom Spring proxy.
 * Use a ThreadLocal to hold the SessionContext and use a custom AjaxFilter to create and bind the UserContext.

However, I would prefer to extend the dwr binding since it naturally belongs there IMHO.

I would like to hear the opinion of a dwr developer whether this can be accomplished in a different way, and whether this feature makes sense from a conceptual point of view.

Thx for your help and feedback!

Werner




Re: Re: Provide implicit objects to mapped service methods

by Joe Walker-3 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


There are lots of solutions to this problem, and I think it ought to be possible to support this without breaking backwards compatibility.

Since someone following your footsteps is going to be extending DWR anyway (at least the Converter interface), how about some smaller refactoring to DefaultRemoter that preserves backwards compatibility.

Are you aware that you can dynamically plug-in new interface implemetations?
http://getahead.org/dwr/server/servlet/plugin

So if DefaultRemoter simply has a method for getting the transparent types, and it works as a list, it would be easy for someone to augment the list:

class MyCustomRemoter extends DefaultRemoter {
  public List<Class> getTransparentTypes() {
    List<Class> transparent = super.getTransparentTypes();
    transparent.add(UserContext.class);
    return transparent;
  }
}

And in web.xml:

<init-param>
  <param-name>org.directwebremoting.extend.Remoter</param-name>
  <param-value>MyCustomRemoter</param-value>
</init-param>

What does everyone think?

Joe.

On 6/11/07, werner loibl <welo.fpw9@...> wrote:
Joe,
 
thx for looking into this! I moved this thread to the dev list since implementing this feature will require some changes to dwr.
 
Yes, extending DefaultRemoter to allow defining a list of 'ignored'  types seems to be the best solution. Since there is an obvious tie between ignored classes and a correctly registered corresponding converter I wonder whether an additional interface for converters would make sense, something like:
 
public interface ContextConverter {
  void Class[] getContextTypes();
}
 
Not sure about the naming yet, the idea is that these values are not part of the RPC but make up the execution context of the method. This assumes that ServletConverter is usually used to retrieve values like locale, current user, user settings etc.
 
DefaultRemoter could query ConverterManager to get a list of all types defined by converters implementing this interface. Those type will not be exposed in the Javascript client interface (and use fake parameters as it is implemented now). This would also require a change to the ConverterManager interface.
 
What do you think?
 
I have also considered a solution that would omit fake parameters on the client side completely, by altering BaseMarshaller to reflect such server side generated parameters during binding. But the concept of 1:1 mapping of method signatures between client side and server side affects large parts of the code, and the feature is probably not important enough to justify a greater code change.
 
I will code my changes against the HEAD, I guess.
 
I'd appreciate any feedback,
 
 
Werner

 
On 6/8/07, Joe Walker <joe@...> wrote:

Hi,

Sorry for the slow reply.

I think that the easy solution is to create a UserContextConverter which uses the techniques demonstrated in ServletConverter to get access to the HttpServletRequest from which a UserContext object can be created and returned.

From the JS POV, you would just pass in 'null' in place of a UserContext, and the converter would 'convert' null to a valid object.

You could alter DefaultRemoter to use something other than LocalUtil.isServletClass() to get the 'ignored classes'.

Joe.


On 5/30/07, werner loibl <welo.fpw9@...> wrote:
Hi,

I would like to provide a mechanism similar to the one currently implemented in dwr that allows adding javax.servlet.http.* types (such as HttpServletRequest) as part of the method signature of a service. The current feature will pass the current request, response, etc in case the method signature defines the equivalent type.
I intend to define a UserContext type that allows querying the current user and other information on the execution context. Dwr should implicitly create a UserContext object if the method signature defines an argument of this type. Though this will actually be retrieved via the HttpServletRequest resp. HttpSession I want to decouple the service implementation from the javax.servlet API. This is to ease testing and to allow creating an API layer that is not tied to the servlet spec. (To be honest, I'm not absolutely sure whether this will work out or not, or will make sense in the end, but I have a good feeling about it ;) ).

Taking a look at ServletConverter and DefaultRemoter it seems that this behaviour is currently hard-wired in dwr. Whereas it is possible to define a Converter that will create the required UserContext object based on the current HttpServletRequest (that can be retrieved from the ThreadLocal WebContext attribute as done by ServletConverter), the DefaultRemoter does not allow extending this behaviour easily. DefaultRemoter will add a dummy variable (with value=false) for every javax.servlet.http type encountered when creating the Javascript service wrapper, but this behaviour is hard-wired and not extensible (see DefaultRemoter#getMethodJS, which is private). The dummy variable is required otherwise BaseCallMarshaller#findMethod will not find the correct service method since the number of arguments of the ajax call does not match the number of method parameters on the service bean.

Other solutions I came up with so far:
 * Create a wrapping layer around my services that will do the conversion and delegate to the service bean passing the created UserContext. This might be automated by using a custom Spring proxy.
 * Use a ThreadLocal to hold the SessionContext and use a custom AjaxFilter to create and bind the UserContext.

However, I would prefer to extend the dwr binding since it naturally belongs there IMHO.

I would like to hear the opinion of a dwr developer whether this can be accomplished in a different way, and whether this feature makes sense from a conceptual point of view.

Thx for your help and feedback!

Werner





RE: Re: Provide implicit objects to mapped service methods

by mikewse :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

So if DefaultRemoter simply has a method for getting the transparent types, and it works as a list, it would be easy for someone to augment the list:

class MyCustomRemoter extends DefaultRemoter {
  public List<Class> getTransparentTypes() {
    List<Class> transparent = super.getTransparentTypes();
    transparent.add(UserContext.class);
    return transparent;
  }
} 
My "gut feeling" for this transparent type list is that it is something closely related to DWR's configuration (through dwr.xml or other means), so the best would be if all configuration data was exposed (and updated) in a consistent way, be it through dwr.xml, the FluentConfigurator, or a parsed bean structure.
 
Best regards
Mike

Re: Re: Provide implicit objects to mapped service methods

by Joe Walker-3 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message



On 6/12/07, Mike Wilson <mikewse@...> wrote:
So if DefaultRemoter simply has a method for getting the transparent types, and it works as a list, it would be easy for someone to augment the list:

class MyCustomRemoter extends DefaultRemoter {
  public List<Class> getTransparentTypes() {
    List<Class> transparent = super.getTransparentTypes();
    transparent.add(UserContext.class);
    return transparent;
  }
} 
My "gut feeling" for this transparent type list is that it is something closely related to DWR's configuration (through dwr.xml or other means), so the best would be if all configuration data was exposed (and updated) in a consistent way, be it through dwr.xml, the FluentConfigurator, or a parsed bean structure.

You're right - that's a much better idea. I was hung up on not changing things too much for what I saw as an edge case, but allowing DefaultRemoter to have a transparentClasses parameter isn't much more work, and is a lot easier to document and use.

Joe.