PDA

View Full Version : Noob with Framework


charly
06-09-2005, 03:47 PM
Greetings,
I know Spring from the Java implementation but can't manage top make it work under Dotnet :(.
So :
I have an asp.net (index.aspx) page with a code-behind class. This class has a property that I want to set through spring.
protected string texte
{
get{return texte;}
set{texte = value;}

}
and my webConf :
<spring>
<context type="Spring.Context.Support.WebApplicationContext, Spring.Web">
<resource uri="config://spring/objects"/>
</context>

<objects xmlns="http://www.springframework.net" >

<object type="index.aspx">
<property name="texte">
<value>hello from Spring.</value>
</property>
</object>

</objects>
</spring>

So I want to put that string in the "texte" property : no great deal ;).

Error Msg follows :
Exception Details: Spring.Objects.NotWritablePropertyException: Property 'texte' is not writable in object class [ASP.index_aspx]

NotWritablePropertyException: Property 'texte' is not writable in object class [ASP.index_aspx]]
Spring.Objects.ObjectWrapper.SetPropertyValues(IPr opertyValues propertyValues, Boolean ignoreUnknown)
Spring.Objects.ObjectWrapper.SetPropertyValues(IPr opertyValues pvs)
Spring.Objects.Factory.Support.AbstractAutowireCap ableObjectFactory.ApplyPropertyValues(String name, RootObjectDefinition definition, IObjectWrapper wrapper, IPropertyValues properties)

[ObjectCreationException: Error creating object with name 'index' defined in 'config [objects] line 20' : Error setting property values: Property 'texte' is not writable in object class [ASP.index_aspx]]
Spring.Objects.Factory.Support.AbstractAutowireCap ableObjectFactory.CreateObject(String name, RootObjectDefinition definition, Object[] arguments, Boolean allowEagerCaching)
Spring.Objects.Factory.Support.AbstractAutowireCap ableObjectFactory.CreateObject(String name, RootObjectDefinition definition, Object[] arguments)
Spring.Objects.Factory.Support.AbstractObjectFacto ry.GetObject(String name, Type requiredType, Object[] arguments)
Spring.Objects.Factory.Support.AbstractObjectFacto ry.GetObject(String name, Object[] arguments)
Spring.Objects.Factory.Support.AbstractObjectFacto ry.GetObject(String name)
Spring.Context.Support.AbstractApplicationContext. GetObject(String name)
Spring.Web.Support.PageHandler.ProcessRequest(Http Context context)
System.Web.CallHandlerExecutionStep.System.Web.Htt pApplication+IExecutionStep.Execute()
System.Web.HttpApplication.ExecuteStep(IExecutionS tep step, Boolean& completedSynchronously) +87

This must be stupid but I have read the http://opensource.atlassian.com/confluence/spring/display/NET/Spring.Web but didn't manage.

Any help would be much appreciated :)

thank you in advance.

Rick Evans
06-09-2005, 05:12 PM
Hiya

Short answer... change the access modifier on the 'texte' property from 'protected' to 'public'.

Ciao

Rick

Aleks Seovic
06-09-2005, 05:37 PM
Actually, how does your index.aspx even compile? I don't see a field backing your "texte" property, and you assign/get value from the property itself, not to/from the backing field!?

I'm assuming that was just a typo, in which case Rick's suggestion should do the job.

Regards,

Aleks

Rick Evans
06-09-2005, 05:45 PM
Hiya

Long answer... well, I guess I'll be answering this question (and forgive me if I'm preaching to the choir), namely...

'So properties have to be public?'

Yeah... I know, it looks wrong on the face of it. Whatever happened to information hiding, encapsulating the inner workings of a class, and exposing only the barest minimum public interface on one's class?

The particular example of an ASP.NET page is perhaps not the best example I can go with here (there not being a corresponding IPage interface), so what about we go with, mmm, something Peelable, something Kissable? :D Only kidding, how about a good old fashioned DAO example...


public interface IUserDao
{
void Save(User user);
}

public class ADOUserDao : IUserDao
{
public void Save(User foo)
{
// implementation elided for clarity...
}

public IConnectionFactory ConnectionFactory
{
get { return _connFactory; }
get { _connFactory = value; }
}

private IConnectionFactory _connFactory;
}


The public interface for the IUserDao doesn't have any public properties at all (plainly). However, Spring.NET's IoC container works with the concrete ADOUserDao implementation of the IUserDao interface, and it is this implementation class that gets wired up and injected into collaborating objects, collaborators that have a dependency on the IUserDao interface. So collaborators, ones that only have a reference to an IUserDao, don't see or even have access to the public IConnectionFactory property that the underlying implementation exposes... so there's no problem of losing all that good OO information hiding stuff.

Hopefully that explains why the container only looks for public properties (by default). Mmm, you know, I've written this long post justifying the decision to only wire up public properties, but my brain has just dragged up a mailing list issue from some months back that addresses this very issue. Dang! I think the outcome was to support protected properties too. Mmm, I wonder how this issue got lost... I'll go bang in a JIRA issue right now. Maybe its already there. :|

The point still holds though... if you're programming against interfaces, bang those public properties in without a care in the world. I do. If you're programming against concrete classes, well, maybe not then. Public properties make classes nice and easy to test too... one just bangs one's mocks and stubs right on in. Of course, you can always use constructor injection if you so wish, which sidesteps the issue nicely... ctor injection is not really an option with ASP.NET pages though, 'cos Spring.NET's IoC container doesn't actually instantiate the Page, it merely configures it.

Hope this roundabout longest-ever-post has helped. I'll update this post when I investigate the (dis)appearance of the missing feature request for providing suport for protected properties.

Ciao
Rick

charly
06-09-2005, 08:24 PM
Greetings all and fthx for the input.
I'll answer here for everyone :) :

I wanted to have my index.aspx.cs possess a property not corresponding to some field. Isn't this allowed in dotnet ? (I'm just beginning with asp.net).

Whatever, I then tried with another object, a simple "bean" as we say in java : class Article with a private property _title and the public accessors. didn't work either :( :
<object id="Article" type="firstWebApp.Article">
<property name="title">
<value>The Spring framework.</value>
</property>
</object>

[InvalidCastException: Specified cast is not valid.]
Spring.Web.DataModel.DataModelManager.get_DataMode l()
Spring.Web.DataModel.DataModelManager.InitializeDa taModel()
Spring.Web.DataModel.DataModelManager..ctor(IFeatu resAware target)
Spring.Web.UI.Page.OnInit(EventArgs e)
firstWebApp.Index.OnInit(EventArgs e) in c:\home\wwwroot\firstwebapp\index.aspx.cs:39
System.Web.UI.Control.InitRecursive(Control namingContainer)
System.Web.UI.Page.ProcessRequestMain()


As for programming against interfaces, I do not see your point here : the property of the class implementing the interface is private and the accessors are public so everything is fine I guess :)

Thank you all for your input, I'll continue to tweak my configuration :)