PDA

View Full Version : Configuration as embedded resources


Tom Whitner
11-23-2004, 02:22 PM
I know it may seem a little counterintuitive, but I think I would be great to be able to load configuration information from an embedded resource within the assembly. There are many activities which could capitalize on the configurable nature of Spring, however, once release should not be changed without recompile or testing. In these cases, binding the configuration data into the assembly would be desirable. Is this already possible? Or could an IApplicationContext implementation be added to perform this function?

Mark Pollack
11-23-2004, 05:23 PM
Hi Tom,

Aleks added this functionality recently, if you take the Movie Finder example and change the build action on the file movie.xml to embedded resource you can then use the following code to create an ApplicationContext


IApplicationContext ctx =
new FileSystemXmlApplicationContext("assembly://MovieFinder/Spring.Examples.MovieFinder.movie.xml");


"Spring" is the default namespace for that application. (I probably should change that...)

Implementation wise, AbstractApplicationContext now inherits from ConfigurableResourceLoader which provides support for protocol-to-resource mappings. The supported mappings are file, http, ftp, and assembly, just use a uri style notation to specify which protocol you want to use. You can add your own mappings as well. This abstraction for loading resources is directly exposed via the GetResource method on an ApplicationContext.

We will probably rename FileSystemXmlApplicationContext to XmlApplicatonContext since there is no longer any need for type specific subclasses, they can all be handled using 'uri' notation and the protocol-to-resource mapping

It is also very likely that this approach will get rolled back into the Spring.Java version.

Just as an aside, there is now also a WebApplicationContext in the Spring.Web project. Although this will not be in the 0.6.0 release, there shouldn't be any problems using it.

Cheers,
Mark

Tom Whitner
11-23-2004, 06:47 PM
That worked great although the syntax of the uri is a little messy.

assembly://<assemblyName>/<namespace>.<filename>

- Tom

Aleks Seovic
11-23-2004, 07:23 PM
Hi Tom,

I know it's not ideal, but what we are trying to do is allow for pluggable IResource implementations. This means that we need to have uniform way of identifying resources and URLs are perfect for that.

Protocol part of the name defines which resource implementation to use. Right now we have following implemented:

1. file -> FileSystemResource
2. http -> UrlResource
3. ftp -> UrlResource
4. assembly -> AssemblyResource
5. web -> WebResource (extends file by using Server.MapPath to resolve resource)

You can easily add your own implementations by implementing IResource interface and registering protocol name with ConfigurableResourceLoader (or any IApplicationContext implementation, as they derive from ConfigurableResourceLoader). Your resource implementation will receive complete URL as a constructor parameter and it's entirely up to you to parse it, pull information you need from it and use it to obtain InputStream for the resource.

This allows end users to define their own implementations that will read config files (or any other resources, for that matter) from the database, content management system, web service, etc. At the same time, it allows us to provide reasonable default implementations that should get the job done in vast majority of cases (Btw, default protocol for unqualified resources is 'file', except in WebApplicationContext, where it is 'web').

Keeping all of the above in mind, I believe that

assembly://<assemblyName>/<resourceName>

is the most natural URL for embedded assembly resources, as it follows logical progression from less specific (assembly itself) to more specific (actual resource name).

You need to specify namespace for the resource because that's what .Net manifest resource resolution requires. If you put your resource in the root of the assembly and don't define default namespace for the project, you will simply use file name without any namespace as your resource name, which will make URL simpler.

Hope this explains why we implemented it this way.

Regards,

Aleks

pazderak
12-10-2004, 03:30 PM
Hi all,
I am trying to play with the same thing, but it isn't working. I have simple GUI application with this main() method:


private static void Main() {
log = LogManager.GetLogger(typeof (MainForm));
DOMConfigurator.Configure();
if (log.IsDebugEnabled){
log.Debug("Application Spring test starting...");
}
appContext = new FileSystemXmlApplicationContext("assembly://TestApp/Aquasoft.Spring.TestApp.spring-config.xml");
Application.Run(new MainForm());
if (log.IsDebugEnabled)
log.Debug("Application Spring test ended...");
}

But when I start app debug, exception is thrown:


System.NotSupportedException: The URI prefix is not recognized.
at System.Net.WebRequest.Create(Uri requestUri, Boolean useUriBase)
at System.Net.WebRequest.Create(Uri requestUri)
at Spring.Core.IO.UrlResource.get_InputStream() in D:\Temp\Working\spring.net\src\Spring\Spring.Core\ Core\IO\UrlResource.cs:line 76
at Spring.Objects.Factory.Xml.XmlObjectDefinitionRead er.LoadObjectDefinitions(IResource resource) in D:\Temp\Working\spring.net\src\Spring\Spring.Core\ Objects\Factory\Xml\XmlObjectDefinitionReader.cs:l ine 209
at Spring.Context.Support.AbstractXmlApplicationConte xt.LoadObjectDefinitions(XmlObjectDefinitionReader objectDefinitionReader) in D:\Temp\Working\spring.net\src\Spring\Spring.Conte xt\Context\Support\AbstractXmlApplicationContext.c s:line 105
at Spring.Context.Support.AbstractXmlApplicationConte xt.RefreshObjectFactory() in D:\Temp\Working\spring.net\src\Spring\Spring.Conte xt\Context\Support\AbstractXmlApplicationContext.c s:line 73
at Spring.Context.Support.AbThe program '[1608] TestApp.exe' has exited with code 0 (0x0).
stractApplicationContext.Refresh() in D:\Temp\Working\spring.net\src\Spring\Spring.Conte xt\Context\Support\AbstractApplicationContext.cs:l ine 287
at Spring.Context.Support.FileSystemXmlApplicationCon text..ctor(String[] configurationLocations) in D:\Temp\Working\spring.net\src\Spring\Spring.Conte xt\Context\Support\FileSystemXmlApplicationContext .cs:line 63
at Spring.Context.Support.FileSystemXmlApplicationCon text..ctor(String configurationLocation) in D:\Temp\Working\spring.net\src\Spring\Spring.Conte xt\Context\Support\FileSystemXmlApplicationContext .cs:line 54
at Aquasoft.Spring.TestApp.MainForm.Main() in c:\documents and settings\karel\dokumenty\visual studio projects\spring\testapp\mainform.cs:line 76

Exception is thrown because prefix "assembly://" is not recognized, I think.
How can I resolve this?

Thank you for replies.

Karel

Mark Pollack
12-10-2004, 03:53 PM
Hi Karel,

Are you using the code in CVS? This feature is currently in CVS and not in the release candidate download. If you use the CVS code note that we have merged Collections and Context dll into a single Spring.Core.dll. This will most notabily affect the declaration of the config section handler in app.config.

We are going to make a new release in the coming week. If you would like me to send you the dlls instead of going to CVS, just email me directly, mark.pollack@codestreet.com

Cheers,
Mark

pazderak
12-10-2004, 04:05 PM
Hi Mark,

I am using downloaded RC version. New release this week is sufficient for me.

Many thanks

Karel