When you import another msbuild file, what is the order of evaluation? - msbuild-4.0

I have a shared properties file shared.properties.proj
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<SharedAssemblySearch>$(MSBuildProjectDirectory)\..\Shared Assemblies</SharedAssemblySearch>
<ParentDir>..</ParentDir>
<SharedAssemblySearch Condition="!Exists('$(SharedAssemblySearch)')">$(ParentDir)\$(SharedAssemblySearch)</SharedAssemblySearch>
<SharedAssemblySearch Condition="!Exists('$(SharedAssemblySearch)')">$(ParentDir)\$(SharedAssemblySearch)</SharedAssemblySearch>
<SharedAssemblySearch Condition="!Exists('$(SharedAssemblySearch)')">$(ParentDir)\$(SharedAssemblySearch)</SharedAssemblySearch>
<SharedAssemblySearch Condition="!Exists('$(SharedAssemblySearch)')">$(ParentDir)\$(SharedAssemblySearch)</SharedAssemblySearch>
<SharedAssemblySearch Condition="!Exists('$(SharedAssemblySearch)')">$(ParentDir)\$(SharedAssemblySearch)</SharedAssemblySearch>
<SharedAssemblySearch Condition="!Exists('$(SharedAssemblySearch)')">$(ParentDir)\$(SharedAssemblySearch)</SharedAssemblySearch>
<SharedAssemblyPath Condition="Exists('$(SharedAssemblySearch)')">$(SharedAssemblySearch)</SharedAssemblyPath>
<SharedAssemblySearch Condition="!Exists('$(SharedAssemblySearch)')">..\SharedAssemblies</SharedAssemblySearch>
<SharedAssemblySearch Condition="!Exists('$(SharedAssemblySearch)')">$(ParentDir)\$(SharedAssemblySearch)</SharedAssemblySearch>
<SharedAssemblySearch Condition="!Exists('$(SharedAssemblySearch)')">$(ParentDir)\$(SharedAssemblySearch)</SharedAssemblySearch>
<SharedAssemblySearch Condition="!Exists('$(SharedAssemblySearch)')">$(ParentDir)\$(SharedAssemblySearch)</SharedAssemblySearch>
<SharedAssemblySearch Condition="!Exists('$(SharedAssemblySearch)')">$(ParentDir)\$(SharedAssemblySearch)</SharedAssemblySearch>
<SharedAssemblyPath Condition="Exists('$(SharedAssemblySearch)')">$(SharedAssemblySearch)</SharedAssemblyPath>
</PropertyGroup>
</project>
I am searching for whatever level parent directory contains the directory named Shared Assemblies. or alternatively SharedAssemblies
I'd like to put this code in a central location for the sln, so that all the projects can just import it. projects in the sln are not all at the same hierarchy level.
Sample .csproj
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), Shared.Properties.proj))\Shared.Properties.proj"
Condition=" '$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), Shared.Properties.proj))' != '' "/>
<ItemGroup>
<Reference Include="EntityFramework">
<HintPath>$(SharedAssemblyPath)\NuGet\EntityFramework.4.3.0\lib\net40\EntityFramework.dll</HintPath>
</Reference>
</ItemGroup>
<Target Name="CheckReferencePaths" BeforeTargets="ResolveAssemblyReferences">
<Message Importance="high" Text="Doing CheckReferencePaths" />
<ItemGroup>
<SharedAssemblyPathItem Include="$(SharedAssemblyPath)" />
</ItemGroup>
<Warning Condition="!Exists('#(SharedAssemblyPathItem)')" Text="SharedAssemblyPath not found at '#(SharedAssemblyPathItem)'" />
<Warning Condition="!Exists('#(SharedAssemblyPathItem)')" Text="SharedAssemblyPath not found at '#(SharedAssemblyPathItem->'%(FullPath)')'" />
<Message Condition="!Exists('%(Reference.HintPath)')" Text="FullPath=%(Reference.HintPath)" Importance="high" />
I have this working in the main project without pushing the property group out to a satellite file that I import, but now want to make it reusable between other projects that could have shared references.
The BeforeTargets target shows this on the new attempt that is not working:
CheckReferencePaths:
Doing CheckReferencePaths
D:\projects\Team\Project\Adapters\DbAdapter\dbadapter.csproj(103,5):
warning : SharedAssemblyPath not found at ''
D:\projects\Team\Project\Adapters\DbAdapter\dbadapter.csproj(104,5):
warning : SharedAssemblyPath not found at ''
FullPath=\NuGet\EntityFramework.4.3.0\lib\net40\EntityFramework.dll
FullPath=
How can I get the project file that imports the shared to evaluate the imported project's properties before it evaluates the item groups' hintpaths. Or is the evaluation order proper, but something else in my construction is incorrect?

Your question lead me to find this valuable info on MSDN. I'm posting it here for keeping the answer self-contained.
Order of Evaluation
When MSBuild reaches an Import element, the imported project is effectively inserted into the importing project at the location of the Import element. Therefore, the location of the Import element can affect the values of properties and items. It is important to understand the properties and items that are set by the imported project, and the properties and items that the imported project uses.
When the project builds, all properties are evaluated first, followed by items. For example, the following XML defines the imported project file MyCommon.targets:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Name>MyCommon</Name>
</PropertyGroup>
<Target Name="Go">
<Message Text="Name='$(Name)'"/>
</Target>
</Project>
The following XML defines MyApp.proj, which imports MyCommon.targets:
<Project
DefaultTargets="Go"
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Name>MyApp</Name>
</PropertyGroup>
<Import Project="MyCommon.targets"/>
</Project>
When the project builds, the following message is displayed:
Name="MyCommon"
Because the project is imported after the property Name has been defined in MyApp.proj, the definition of Name in MyCommon.targets overrides the definition in MyApp.proj. If, the project is imported before the property Name is defined, the build would display the following message:
Name="MyApp"
Use the following approach when importing projects
Define, in the project file, all properties and items that are used
as parameters for properties and items in the imported project.
Import the project.
Define in the project file all properties and items that must
override default definitions of properties and items in the imported
project.
Example
The following code example shows the MyCommon.targets file that the second code example imports. The .targets file evaluates properties from the importing project to configure the build.
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Flavor Condition="'$(Flavor)'==''">DEBUG</Flavor>
<Optimize Condition="'$(Flavor)'=='RETAIL'">yes</Optimize>
<appname>$(MSBuildProjectName)</appname>
<PropertyGroup>
<Target Name="Build">
<Csc Sources="hello.cs"
Optimize="$(Optimize)"
OutputAssembly="$(appname).exe"/>
</Target>
</Project>
The following code example imports the MyCommon.targets file.
<Project DefaultTargets="Build"
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Flavor>RETAIL</Flavor>
</PropertyGroup>
<Import Project="MyCommon.targets"/>
</Project>

Try to use inline task instead of shared.properties.proj file. Check my answer on this question. It was about searching for some file is the parent directories. You can adapt it to search for a parent directory.

Related

Composite Persistence Unit using a single JAR file

I have searched the web and this site already for an answer. Although I found one link through a Google search, I subsequently lost the link and can't find it again.
I have been working on an e-commerce web site running on Glassfish 4.1.1 that originally had a single database (DB) using EclipseLink 2.6.4, but it now requires three that will reside on multiple servers (in order to keep customer data secure). The site worked fine with the single DB. I split the data from the single DB into three. The entities and JPA controllers defined in the J2EE code are all the same (I preserved the code so I wouldn't have to rewrite everything, only make minor changes such as annotations, etc.), but they are now located in three different MySQL databases. The three databases have relationships to one another.
In theory (and according the the link I saw and lost) a composite persistence unit (PU) can be defined to incorporate all three PU's for the three different data sources all within a single JAR file and using tags for the entity-PU mappings. Most of the examples (and the Eclipselink and Oracle Persistence API documentation) use a Composite PU with multiple JAR files (e.g.: https://github.com/forgemo/eclipselink-composite-persistence-unit-example).
Can anyone point me in the right direction as to how to create a composite PU without having to use a separate JAR file for each database PU?
My current persistence.xml file (musltiple PUs but not a composite) is as follows:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1"
xmlns="http://xmlns.jcp.org/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"
>
<persistence-unit name="PU1" transaction-type="JTA">
<jta-data-source>java:app/jdbc/db1</jta-data-source>
<class>com.mysite.myproject.Database.Items</class>
<class>com.mysite.myproject.Database.Manufacturer</class>
<class>com.mysite.myproject.Database.Category</class>
<class>com.mysite.myproject.Database.Cart</class>
<class>com.mysite.myproject.Database.AuditTable</class>
<class>com.mysite.myproject.Database.Images</class>
<class>com.mysite.myproject.Database.Procedures</class>
<class>com.mysite.myproject.Database.Warehouse</class>
<class>com.mysite.myproject.Database.Wishlist</class>
<class>com.mysite.myproject.Database.Purchases</class>
<class>com.mysite.myproject.Database.TaxTables</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<property name="javax.persistence.schema-generation.database.action" value="drop-and-create"/>
<property name="eclipselink.logging.level" value="FINE"/>
</properties>
</persistence-unit>
<persistence-unit name="PU2" transaction-type="JTA">
<jta-data-source>java:app/jdbc/db2</jta-data-source>
<class>com.mysite.myproject.Database.AccessList</class>
<class>com.mysite.myproject.Database.Users</class>
<class>com.mysite.myproject.Database.Customer</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<property name="javax.persistence.schema-generation.database.action" value="drop-and-create"/>
<property name="eclipselink.logging.level" value="FINE"/>
</properties>
</persistence-unit>
<persistence-unit name="PU3" transaction-type="JTA">
<jta-data-source>java:app/jdbc/db3</jta-data-source>
<class>com.mysite.myproject.Database.Key1</class>
<class>com.mysite.myproject.Database.Key2</class>
<class>com.mysite.myproject.Database.Key3</class>
<class>com.mysite.myproject.Database.Key4</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<property name="javax.persistence.schema-generation.database.action" value="create"/>
<property name="eclipselink.logging.level" value="FINE"/>
</properties>
</persistence-unit>
The above persistence.xml works fine as long as there are no relationships between data sources (e.g. - relationship between Wishlist and Customer tables results in "[class com.mysite.myproject.Database.Wishlist] uses a non-entity [class com.mysite.myproject.Database.Customer] as target entity in the relationship attribute [field customer]" at deployment).
As it turns out, it seems a composite persistence unit is not needed (which probably explains why nobody can answer the question and there is little documentation about them).
After finding many, many bugs in Glassfish, Geronimo, WebLogic, and Ecplipselink, and NetBeans, I was finally able to get the system working using multiple persistence units (PU) without using a composite PU. JTA is able to persist all entities including their references to entities outside their own PU. One key factor to making this work is to make sure classes not part of a PU are NOT excluded by adding this to your PU definition in persistence.xml:
<exclude-unlisted-classes>false</exclude-unlisted-classes>
as in the following complete PU example (one of the three I use in my project):
<persistence-unit name="DHWPU" transaction-type="JTA">
<jta-data-source>jdbc/dhw</jta-data-source>
<class>Database.AuditTable</class>
<class>Database.Cart</class>
<class>Database.Category</class>
<class>Database.Images</class>
<class>Database.Items</class>
<class>Database.Manufacturer</class>
<class>Database.Procedures</class>
<class>Database.Purchases</class>
<class>Database.TaxTables</class>
<class>Database.Warehouse</class>
<class>Database.Wishlist</class>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
<property name="javax.persistence.schema-generation.database.action" value="none"/>
<property name="eclipselink.logging.level" value="FINE"/>
</properties>
</persistence-unit>

JSF : java.util.MissingResourceException: Can't find bundle for base : Only if context root is changed

I have read a lot of threads with the MissingResourceException problem.
I'm using Primefaces 5.1.3
In my case I have the error :
java.util.MissingResourceException: Can't find bundle for base [...], locale
In face-config.xml :
<message-bundle>message.erreur.MsgErreurPrimefaces</message-bundle>
And in my sources :
The war is packed in an EAR. It works fine when I keep the default context root but if I change the context root, I get the message.
The file is present in the war's WEB-INF folder under :
WEB-INF/classes/message/erreur/MsgErreurPrimefaces_fr_FR.properties
Thanks
I have encountered this kind of error before and my problem has been corrected by editing as below. First of all, I would recommend you to add and test the MsgErreurPrimefaces.properties file.
<?xml version='1.0' encoding='UTF-8'?>
<faces-config version="2.2"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_2.xsd">
<application>
<resource-bundle>
<base-name>message.erreur.MsgErreurPrimefaces</base-name>
<var>myBundle</var>
</resource-bundle>
</application>
<application>
<message-bundle>message.erreur.MsgErreurPrimefaces</message-bundle>
<locale-config>
<default-locale>fr_FR</default-locale>
<supported-locale>fr_FR</supported-locale>
<supported-locale>en_US</supported-locale>
</locale-config>
</application>
</faces-config>

how to add configuration for log4net (or any other 3rd party library) in ASP.NET 5.0

I was reading Scott Gu's blog on ASP.NET 5.0 features and one of the new feature mentioned in the blog is to use json file as configuration and elimination of Web.config file.
I have few questions around that feature.
Assume I have following log4net configuration which was previously added to Web.Config in previous version of ASP.NET
Config file
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
<log4net debug="true">
<appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
<file value="C:\\TestProj\\TestLog.txt" />
<appendToFile value="true" />
<rollingStyle value="Size" />
<maxSizeRollBackups value="10" />
<maximumFileSize value="10MB" />
<staticLogFileName value="true" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%-5p %d %5rms %-22.22c{1} %-18.18M - %m%n" />
</layout>
</appender>
<root>
<level value="DEBUG" />
<appender-ref ref="RollingLogFileAppender" />
</root>
</log4net>
How would one add sections in config.json ?
How would one convert above xml and add it to config.json?
Does 3rd Party library ( In my example log4net ) or users of the library have to add some type of custom conversion api to support json based configuration, in order to take advantage of new configuration feature provided in ASP.NET 5.0?
Recently I had the same problem with log4net. I managed to do it working as following:
Create log4net.xml file containing the configuration section for log4net
<?xml version="1.0" encoding="utf-8" ?>
<log4net>
...
</log4net>
You can put the file in the project root folder.
And in the Startup.Startup() method you can configure the log4net providing the xml as a configuration:
public Startup(IApplicationEnvironment appEnv)
{
// ...
XmlConfigurator.Configure(new FileInfo(Path.Combine(appEnv.ApplicationBasePath, "log4net.xml")));
}
I hope this helps.
Current versions of log4net don't support Json projects, so the config needs to be in a separate xml file.

CAstle Windsor: How to reference a second xml config file that is an embedded resource?

We have one xml configuration file that we use in production. We also have a little test app that has a couple of additional needs. What I'd like to do is create a second, testing-only xml config file that references the embedded production configuration file. Is there any way to do this?
I'm aware of the "include" element, but am not sure where in the file it is supposed to be placed--in the castle node? The components node?
I feel like the answer is here but I'm too dense to figure it out.
Thanks for any help you can provide.
UPDATE
This is how our production config file is set up:
<?xml version="1.0" encoding="utf-8"?>
<OurCompany>
<Framework>
<castle>
<installers>
<!-- some installers-->
<installers>
<components>
<!--some components-->
<components>
<castle>
<Framework>
<OurCompany>
My most recent attempt at a non-production config file looks like this:
<?xml version="1.0" encoding="utf-8"?>
<OurCompany>
<Framework>
<castle>
<include uri="assembly://AssemblyContainingEmbeddedXml/MyEmbeddedConfig.xml" />
<components>
<!--components I only want registered with container when running in non-production environment-->
<components>
<castle>
<Framework>
<OurCompany>
The exception I get reads:
Configuration parser encountered Framework, but it was expecting to find installers, facilities or components. There might be either a typo on or you might have forgotten to nest it properly.
(In the actual message, "Framework," "installers," "facilities," and "components" are enclosed in angle brackets.)
The bottom of the page you reference has an example of loading from an embedded resourced:
IResource resource = new AssemblyResource("assembly://Acme.Crm.Data/Configuration/services.xml");
container = new WindsorContainer(new XmlInterpreter(resource));

Inject App Settings using Windsor

How can I inject the value of an appSettings entry (from app.config or web.config) into a service using the Windsor container? If I wanted to inject the value of a Windsor property into a service, I would do something like this:
<properties>
<importantIntegerProperty>666</importantIntegerProperty>
</properties>
<component
id="myComponent"
service="MyApp.IService, MyApp"
type="MyApp.Service, MyApp"
>
<parameters>
<importantInteger>#{importantIntegerProperty}</importantInteger>
</parameters>
</component>
However, what I'd really like to do is take the value represented by #{importantIntegerProperty} from an app settings variable which might be defined like this:
<appSettings>
<add key="importantInteger" value="666"/>
</appSettings>
EDIT: To clarify; I realise that this is not natively possible with Windsor and the David Hayden article that sliderhouserules refers to is actually about his own (David Hayden's) IoC container, not Windsor.
I'm surely not the first person to have this problem so what I'd like to know is how have other people solved this issue?
I came up with a solution for this eventually based on hints from various sources on the web. The end result though involved pretty much copying three classes from Windsor verbatim and modifying them just a little bit. The end result is up on codeplex for your enjoyment.
http://windsorappcfgprops.codeplex.com/
I originally wrote this code quite some time ago so it's based on Windsor 1.0.3 - yes, it took me that long to get around to publishing the result!
The code allows you to have this in your app.config (or web.config, obviously):
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="theAnswer" value="42"/>
</appSettings>
</configuration>
...and access it from your Windsor XML config file like this:
<?xml version="1.0" encoding="utf-8" ?>
<castle>
<components>
<component
id="answerProvider"
service="Acme.IAnswerProvider, Acme"
type="Acme.AnswerProvider, Acme"
>
<parameters>
<theAnswer>#{AppSetting.theAnswer}</theAnswer>
</parameters>
</component>
</components>
</castle>
There's a working example in the solution.
I wrote a post about a similar case a couple of months ago. It uses a SubDependencyResolver to inject the appropriate parameters. In your case, you can just change DynamicConfigurationSettings for ConfigurationManager.