My Spring.NET configuration is using the following type syntax and is working ok.
<object id="JohnUsingVariableSource"
type="XmlConfig.StringInjection.Person, XmlConfig">
<property name="Name" value="${JohnsFullName}" />
</object>
Values for the ${JohnsFullName} placeholder are configured in the app.config file. My requirements have changed and I know need to get the name from the database at startup. How is it possible to overwrite the value in the app.config file ? Can I do it in code without opening the app.config (as here App.Config change value), does spring.NET have a way of doing this ?
Yes, you can do that without modifying the app.config file. Simply implement a custom IVariableSource:
public interface IVariableSource
{
string ResolveVariable(string name);
}
In the ResolveVariable method you read from the db.
The first variable source configured in your config will be the one used by the spring config, if I recall correctly.
Related
After creating .dtsConfig file using Package Configurations, I want to assign connection string value in XML file to the package level variable using expression.
Can anyone tell me what is the expression to get the conn string value from XML file.
If you stored the connection string in a XML config file you should have something like this:
<?xml version="1.0"?>
<DTSConfiguration>
<DTSConfigurationHeading>
<DTSConfigurationFileInfo GeneratedBy="user.name" GeneratedFromPackageName="your package" GeneratedFromPackageID="{DCA17C6E-F7BD-4084-8DCA-69806C89FB71}" GeneratedDate="4/10/2014 1:18:15 PM"/>
</DTSConfigurationHeading>
<Configuration ConfiguredType="Property" Path="\Package.Connections[AW].Properties[ConnectionString]" ValueType="String">
<ConfiguredValue>Data Source=localhost;Initial Catalog=AdventureWorks2012;Provider=SQLNCLI11.1;Integrated Security=SSPI;Auto Translate=False;</ConfiguredValue>
</Configuration>
</DTSConfiguration>
If you created the file using the package configuration wizard, you donĀ“t need to assigned the value of the connection string using a expression. It is assigned automatically when you open the package.
Other way to configure your connection string is creating a variable with Data type String. In the Package Configurations store the value of the variable in the config file. Then you can map the variables to the connection string property of the connection using the Expressions attribute in the properties windows. Everything depens on what you really want to do.
If you have any questions just ask again.
Kind Regards,
Paul
I am developping J2EE application with appfuse that have default settings with mySQL
<!-- Database settings -->
<dbunit.dataTypeFactoryName>org.dbunit.ext.mysql.MySqlDataTypeFactory</dbunit.dataTypeFactoryName>
<dbunit.operation.type>CLEAN_INSERT</dbunit.operation.type>
<hibernate.dialect>org.hibernate.dialect.MySQL5InnoDBDialect</hibernate.dialect>
<jdbc.groupId>mysql</jdbc.groupId>
<jdbc.artifactId>mysql-connector-java</jdbc.artifactId>
<jdbc.version>5.1.27</jdbc.version>
<jdbc.driverClassName>com.mysql.jdbc.Driver</jdbc.driverClassName>
<jdbc.url>jdbc:mysql://localhost/${db.name}?createDatabaseIfNotExist=true&useUnicode=true&characterEncoding=utf-8&autoReconnect=true</jdbc.url>
<jdbc.username>root</jdbc.username>
<jdbc.password></jdbc.password>
<jdbc.validationQuery>SELECT 1 + 1</jdbc.validationQuery>
But i need to connect my application with external database (SQL QERVER)to retreive some data.
I need help to configure maven to use two different database (mysql +sql server)
maven will help you out with loading of the driver jar files. You would be creating two data source / session factory to achieve this.
I think this can be achieved quite easily in a brief guideline as follows:
Create a second "dataSource" bean definition in applicationContext-resources.xml with MSSQL specific values such as driver class, url etc. Give it a different bean id, "dataSourceMSSQL" perhaps. Bind them up to different properties file if you don't want to hard coded property values. For simplicity you can just hard coded it (not recommended). If you chose otherwise, you need to create another properties file to store mssql connection properties, perhaps jdbc-mssql.properties and add it into propertyConfigurer list. This also require you to make changes to your pom file to include custom settings under <!-- Database settings --> section. This can be a bit complicated.
Create another "sessionFactory" bean definition in applicationContext-dao.xml with MSSQL specific values such as hibernate dialect etc. and binds it to "dataSourceMSSQL" as dataSource property ref. Give it a different bean id perhaps, "sessionFactoryMSSQL".
Wire your DAOs which require the new sessionFactory i.e.:
#Autowired private SessionFactory sessionFactoryMSSQL;
Hope that will work for you.
I am using the EntLib in an environment where database connection strings are retrieved from a separate library call that decrypts a proprietary config file. I have no say over this practice or the format of the config file.
I want to do EntLib exception logging to the database in this setting. I therefore need to set up a EntLib database configuration instance with the name of the database, with the connection string. Since I can't get the connection string until run time, but EntLib does allow run-time configuration, I use the following code, as described in this:
builder.ConfigureData()
.ForDatabaseNamed("Ann")
.ThatIs.ASqlDatabase()
.WithConnectionString(connectionString)
.AsDefault();
The parameter connectionString is the one I've retrieved from the separate library.
The sample code goes on to merge the created configuration info with an empty DictionaryConfigurationSource. I, however, need to merge it with the rest of the configuration code from the app.config. So I do this:
var configSource = new SystemConfigurationSource();
builder.UpdateConfigurationWithReplace(configSource);
EnterpriseLibraryContainer.Current
= EnterpriseLibraryContainer.CreateDefaultContainer(configSource);
... which is based very closely on the sample code.
But: I get an internal error in Microsoft.Practices.EnterpriseLibrary.Common.Configuration.SystemConfigurationSource.Save. The failing code is this:
var fileMap = new ExeConfigurationFileMap { ExeConfigFilename = ConfigurationFilePath };
var config = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
config.Sections.Remove(section);
config.Sections.Add(section, configurationSection);
config.Save();
... where 'section' is "connectionStrings". The code fails on the Add method call, saying that you can't add a duplicate section. Inspection shows that the connectionStrings section is still there even after the Remove.
I know from experience that there's always a default entry under connectionStrings when the configuration files are actually read and interpreted, inherited from the machine.config. So perhaps you can never really remove the connectionStrings section.
That would appear to leave me out of luck, though, unless I want to modify the EntLib source, which I do not.
I could perhaps build all the configuration information for the EntLib at run time, using the fluent API. But I'd rather not. The users want their Operations staff to be able to make small changes to the logging without having to involve a developer.
So my question, in several parts: is there a nice simple workaround for this? Does it require a change to the EntLib source? Or have I missed something really simple that would do away with the problem?
I found a workaround, thanks to this post. Rather than taking the system configuration source and attempting to update it from the builder, I copy the sections I set up in app.config into the builder, and then do an UpdateConfigurationWithReplace on an empty dummy configuration source object in order to create a ConfigurationSource that can be used to create the default container.
var builder = new ConfigurationSourceBuilder();
var configSource = new SystemConfigurationSource();
CopyConfigSettings("loggingConfiguration", builder, configSource);
CopyConfigSettings("exceptionHandling", builder, configSource);
// Manually configure the database settings
builder.ConfigureData()
.ForDatabaseNamed("Ann")
.ThatIs.ASqlDatabase()
.WithConnectionString(connectionString)
.AsDefault();
// Update a dummy, empty ConfigSource object with the settings we have built up.
// Remember, this is a config settings object for the EntLib, not for the entire program.
// So it doesn't need all 24 sections or however many you can set in the app.config.
DictionaryConfigurationSource dummySource = new DictionaryConfigurationSource();
builder.UpdateConfigurationWithReplace(dummySource);
// Create the default container using our new ConfigurationSource object.
EnterpriseLibraryContainer.Current
= EnterpriseLibraryContainer.CreateDefaultContainer(dummySource);
The key is this subroutine:
/// <summary>
/// Copies a configuration section from the SystemConfigurationSource to the ConfigurationSourceBuilder.
/// </summary>
/// <param name="sectionName"></param>
/// <param name="builder"></param>
/// <param name="configSource"></param>
private static void CopyConfigSettings(string sectionName, ConfigurationSourceBuilder builder, SystemConfigurationSource configSource)
{
ConfigurationSection section = configSource.GetSection(sectionName);
builder.AddSection(sectionName, section);
}
I have the following three components defined in the Caste-Windsor XML configuration for my application:
<component id="StringFactory"
service="IStringFactory, MyApp"
type="DefaultStringFactory, MyApp"
lifestyle="singleton"
/>
<component id="TheString"
type="System.String"
factoryId="StringFactory"
factoryCreate="CreateString"
>
<parameters>
<name>SomeString</name>
</parameters>
</component>
<component id="TheTarget"
service="ITarget, MyApp"
type="TheTarget, MyApp"
lifestyle="transient"
>
<parameters>
<aString>${TheString}</aString>
</parameters>
</component>
And the following facility defined:
<facility id="factory.support"
type="Castle.Facilities.FactorySupport.FactorySupportFacility, Castle.MicroKernel"
/>
When I run the application and set a breakpoint in the constructor of the TheObject class, the value passed in as the aString parameter is "${TheString}" when I expect it to resolve to the value of the component with that name.
Also, I have a breakpoint in the StringFactory constructor and CreateString method, neither of which are hit. I know the configuration is being used as other components are resolving correctly.
What am I missing or doing wrong here?
UPDATE
In light of the huge tangient this topic has taken, I've refactored the code above to remove anything to do with connection strings. The original intent of this post was about injecting a property with the value returned from a method on another object. Somehow that point was lost in a discussion about why I'm using XML versus code-based configuration and if this is a good way to inject a connection string.
The above approach is far from an original idea and it was pulled from several other discussions on this topic and our requirements are what they are. I'd like help understanding why the configuration as it is in place (whether the right approach or not) isn't working as expected.
I did verify that the first two components are being instantiated correctly. When I call Container.Resolve("TheString"), I get the correct value back. For whatever reason, The parameter syntax is not working correctly.
Any ideas?
While not a definitive solution to what I need to do in my application, I believe I've figured out what is wrong with the code. Or at least I've found a way to make it work which hints at the original problem.
I replaced the String type for TheString with a custom class. That's it. Once I did that, everything worked fine.
My guess is that it has something to do with the fact that I was trying to use a ValueType (primitive) as a component. I guess Castle doesn't support it.
So, knowing that's the case, I can now move on to figuring out if this approach is really going to work or if we need to change direction.
UPDATE
For the sake of completeness, I thought I'd go ahead and explain what I did to solve my problem AND satisfy my requirements.
As before, I have access to my configuration settings through an IConfigurationService defined as:
<component id="ConfigurationService"
service="MyApp.IConfigurationService, MyApp"
type="MyApp.RuntimeConfigurationService, MyApp"
lifestyle="singleton"
/>
This is automatically injected into my (new) IConnectionFactory which is responsible for generating IDbConnection objects based on the connection strings defined in the application's configuration file. The factory is declared as:
<component id="ConnectionFactory"
service="MyApp.Factories.IConnectionFactory, MyApp"
type="MyApp.Factories.DefaultConnectionFactory, MyApp"
lifestyle="singleton"
/>
In order to resolve what connection is used by my repository, I declare each connection as a component using the ConnectionFactory to create each instance:
<component id="MyDbConnection"
type="System.Data.IDbConnection,
System.Data, Version=2.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089"
factoryId="ConnectionFactory"
factoryCreate="CreateConnection"
lifestyle="transient"
>
<parameters>
<connectionStringName>MyDB</connectionStringName>
</parameters>
</component>
Notice the fully described reference to System.Data. I found this is necessary whenever referencing assemblies in the GAC.
Finally, my repository is defined as:
<component id="MyRepository"
service="MyApp.Repositories.IMyRepository, MyApp"
type="MyApp.Sql.SqlMyRepository, MyApp.Sql"
lifestyle="transient"
>
<parameters>
<connection>${MyDbConnection}</connection>
</parameters>
</component>
Now everything resolves correctly and I don't have ANY hard-coded strings compiled into my code. No connection string names, app setting keys or whatever. The app is completely reconfigurable from the XML files which is a requirement I must satisfy. Plus, other devs that will be working with the solution can manage the actual connection strings in the way they are used to. Win-win.
Hope this helps anyone else that runs into a similar scenario.
You don't really need XML registrations here, since you probably don't need to swap components or change the method used without recompiling. Writing a configurable app does not imply having to use XML registrations.
The problem with this particular XML registration you posted is that the connection string is a parameter, but it's treated like a service.
Doing this with code registrations is much easier, e.g.:
var container = new WindsorContainer();
container.Register(Component.For<IConfigurationService>().ImplementedBy<RuntimeConfigurationService>());
container.Register(Component.For<ITheRepository>().ImplementedBy<TheRepository>()
.LifeStyle.Transient
.DynamicParameters((k, d) => {
var cfg = k.Resolve<IConfigurationService>();
d["connectionString"] = cfg.GetConnectionString();
k.ReleaseComponent(cfg);
}));
Or if you don't want to depend on IConfigurationService, you could do something like:
container.Register(Component.For<ITheRepository>().ImplementedBy<TheRepository>()
.LifeStyle.Transient
.DependsOn(Property.ForKey("connectionString")
.Is(ConfigurationManager.ConnectionStrings[ConfigurationManager.AppSettings["connName"]].ConnectionString))
I have a class
public class Broker
{
public Broker(string[] hosts, string endPoint, string port, Type remoteType)
{
}
}
Which I want to configure using Unity XML Configuration, I can configure it using code in C# as follows already, where "container" is my Unity container
container.Configure<InjectedMembers>()
.ConfigureInjectionFor<Broker>("myBroker",
new InjectionConstructor(hosts, endPoint, port, new InjectionParameter(typeof(IMyBrokeredObject))));
and it will happly resolve using the normal unity calls
container.Resolve("myBroker");
But currently my xml cannot resolve the final parameter IMyBrokeredObject, I get a resolution exception, as Unity is trying to resolve the type insted of simply injecting the type, as it does in the code above.
Any Ideas?
Have you defined the type in the configuration file:
<unity>
<typeAliases>
<typeAlias alias="IMyBrokeredObject" type="MyAssembly.IMyBrokeredObject, MyAssembly" />
</typeAliases>
<containers>
<container>
<types>
<!-- Views -->
<type type="IMyBrokeredObject" mapTo="MyAssembly.MyBrokeredObjectImplementation, MyAssembly" />
But my problem is that there is no implementation available for the IMyBrokeredObject, what is actually happening in the background of this is that the broker provides remote objects given an interface, the actual implementation is somewhere else.
In code I can get the container to provide an broker by giving an "InjectionParameter", I cannot find out how to do this in the xml configuration.
its tricky because I dont want the container to give an instance of the interface but to actually pass the interface as is, the "InjectionParameter" is a store for a value, the stored value is handed in when the object is created by the container, as is. What I am looking for is the required configuration xml to create the InjectionParameter and give it the value, if that is at all possible?