I am trying to change a log file name after deploying, so transform this:
<log4net>
...
<appender name="GeneralAppender" type="log4net.Appender.RollingFileAppender, log4net">
<file value="c:\logs\Co.App.log" />
...
</appender>
</log4net>
to this:
<log4net>
...
<appender name="GeneralAppender" type="log4net.Appender.RollingFileAppender, log4net">
<file value="c:\logs\Co.App.localhost.log" />
...
</appender>
</log4net>
the actual file node doesn't have any attributes, so I am trying to locate it by parent node
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<log4net>
<appender >
<file value="c:\logs\Co.App.localhost.log" xdt:Transform="Replace" xdt:Locator="XPath(../appender[#name='GeneralAppender'])" />
</appender>
</log4net>
</assemblyBinding>
</runtime>
i've also tried all permutations of absolute and relative xpath's but i don't see it having any effect in transform preview.
i tried:
xdt:Locator="XPath(//appender[#name='GeneralAppender']/file)"
and even:
xdt:Transform="Remove" xdt:Locator="XPath(//file)"
found it!
<file value="c:\logs\Co.App.local.log" xdt:Transform="Replace" xdt:Locator="Condition(../#name='GeneralAppender')" />
Slight extension:
If the parent node has TWO (or more children), then the above solution is not enough.
This is the case in log4net, when the EventLogAppend is used, which has:
<appender name="EventLogAppender" type="log4net.Appender.EventLogAppender" >
...
<param name="LogName" value="MyLog"/>
<param name="ApplicationName" value="MyApplication"/>
...
Then you need to use an 'and' + an atribute more to hit the right node:,
like xdt:Locator="Condition(../#name='EventLogAppender' and #name='LogName')
Example for the EventLogAppender, where both the params are replaced:
<param name="LogName" value="MyNewLog" xdt:Transform="Replace" xdt:Locator="Condition(../#name='EventLogAppender' and #name='LogName')" />
<param name="ApplicationName" value="MyNewApplication" xdt:Transform="Replace" xdt:Locator="Condition(../#name='EventLogAppender' and #name='ApplicationName')" />
The MSDN documentation mentions that if you use XPath, then it's going to append the expression that you pass to the current context in the transform file. So XPath is good for cases where you want to modify the current element or one of it's predecessors.
Where as if you want to traverse to parents in a relative manner, there is no XPath expression that does that. XPath starts with a parent and allows you to traverse the descendants and not ascendants. That's when condition works.
I tried to use xdt:Locator="XPath(.)" and it worked perfectly to replace the current element, and if needed it's descendants. But it doesn't for ascendants.
Related
I am new to Confluence. I am playing decorators and CSS.
This is my atlassian-plugin.xml:
<plugin-info>
<description>${project.description}</description>
<version>${project.version}</version>
<vendor name="${project.organization.name}" url="${project.organization.url}" />
<param name="plugin-icon">images/ohanaFavicon.png</param>
<param name="plugin-logo">images/ohanaPluginLogo.gif</param>
</plugin-info>
<resource type="i18n" name="i18n" location="mysite" />
<web-resource key="mysite-resources" name="mysite Web Resources">
<dependency>com.atlassian.auiplugin:ajs</dependency>
<context>mysite</context>
</web-resource>
<theme key="mysiteheme" name="Mysite Theme" class="com.atlassian.confluence.themes.BasicTheme">
<description>A theme for tests</description>
<param name="includeClassicStyles" value="false" />
<resource type="download" name="default-theme.css" location="/includes/css/default-theme.css">
<param name="source" value="webContext" />
</resource>
<resource type="download" name="mysite.css" location="/theme-mysite/css/mysite.css" />
<resource type="download" name="mysite.js" location="/theme-mysite/js/mysite.js" />
<resource type="download" key="images" name="images/" location="/theme-mysite/images"/>
<layout key="${atlassian.plugin.key}:main" />
</theme>
<layout key="main" name="Main Decorator" overrides="/decorators/main.vmd" class="com.atlassian.confluence.themes.VelocityDecorator">
<resource type="velocity" name="decorator" location="/theme-mysite/decorators/main.vmd" />
</layout>
In mysite.css, I have the following CSS rule:
background: url(images/header-bkgd.png) 5px -115px;
However, I am not able to see the display of the background image. What is missing in what I did? The "images" directory is under "theme-mysite" directory, which is under the "resources" directory.
A broader question: I have read the book <> and did quite online search. But I am still not able to find any sample or tutorial explaining how to refer background images in a CSS file. Where to acquire such knowledge?
Best.
Update
I tried this:
background: url(../images/header-bkgd.png)
When looking at the change in Confluence, Chrome shows 404 for the image and the path to it is:
http://localhost:1990/confluence/s/en_GB/6441/NOCACHE/1.0.0-SNAPSHOT/_/download/resources/images/header-bkgd.png
I also tried
background: url(../theme-mysite/images/header-bkgd.png);
The generated path in Chrome is:
http://localhost:1990/confluence/s/en_GB/6441/NOCACHE/1.0.0-SNAPSHOT/_/download/resources/theme-mysite/images/header-bkgd.png
The image does not exist either.
You try to change like this
background: url(../images/header-bkgd.png) 5px -115px;
Finally got it resolved myself. I need to add this:
<resource type="download" key="images" name="images/" location="/theme-mysite/images"/>
outside '...'
I'd like to set up a RollingFileAppender in log4net such that the current (i.e. today's) log file always has a static name (like app.log), but upon roll over at the end of the day, it should be renamed to app.<date>.log. Here's as close as I've got so far (note that I'm using every-minute rollover rather than every-day rollover since this is easier to debug):
<appender name="applog" type="log4net.Appender.RollingFileAppender">
<file value="app.log" />
<staticLogFileName value="false" />
<datePattern value=".yyyy-MM-dd-hh-mm" />
<preserveLogFileNameExtension value="true" />
<appendToFile value="true" />
<rollingStyle value="Date" />
<maxSizeRollBackups value="5" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger - %message%newline" />
</layout>
</appender>
The problem with this is that I see the following when a request begins:
app.2016-02-01-05-00.log
And by the time the request ends, I have these files:
app.2016-02-01-05-00.log
app.2016-02-01-05-00.log.2016-02-01-05-00.log
Notice that the minute hasn't rolled over yet, but it appears to have created a rollover file of some kind anyway. Also, today's file isn't ever called just 'app.log' as I want, it always starts with the timestamp in the name. Lastly, it doesn't appear to honor my maxSizeRollBackups of 5, as far as I can tell the backups grow indefinitely without ever getting deleted.
I tried removing the staticLogFileName tag, and that makes today's name 'app.log' like I want, but then it rolls over in place, overwriting itself and not creating backup files.
After breaking down and downloading the source code, it turns out to be a permission issue with the rollover's System.IO.File.Move() call. I needed to set the folder's Modify permission to true as well, not just Read and Write (which is strange, because isn't a move technically a write operation?).
I also discovered that you should NOT set staticLogFileName to false, so I had to remove that element from the xml.
I am trying to parse problem section in CCD using MDHT. The XML code I am trying to parse is:
<entry>
<act classCode="ACT" moodCode="EVN">
<templateId root="2.16.840.1.113883.10.20.22.4.3" />
<id root="2.16.840.1.113883.3.441" extension="85cec11c26ff475fac469cc9fa7a040c" />
<code code="CONC" codeSystem="2.16.840.1.113883.5.6" />
<statusCode code="active" />
<effectiveTime nullFlavor="UNK">
<low value="20110925000000" />
<high nullFlavor="UNK" />
</effectiveTime>
<entryRelationship typeCode="SUBJ" inversionInd="false">
<observation classCode="OBS" moodCode="EVN" negationInd="false">
<templateId root="2.16.840.1.113883.10.20.22.4.4" />
<id root="2.16.840.1.113883.3.441.1.50.300011.51.26604.61" extension="1348" />
<code nullFlavor="NA" />
<text>Asthma<reference value="#ref_d910f32f622b4615970569407d739ca6_problem_name_1" />
</text>
<statusCode code="completed" />
<effectiveTime nullFlavor="UNK">
<low value="20110925000000" />
<high nullFlavor="UNK" />
</effectiveTime>
<value xsi:type="CD" nullFlavor="UNK">
<translation code="195967001" displayName="Asthma" codeSystem="2.16.840.1.113883.6.96" codeSystemName="SNOMED CT">
<originalText>
<reference value="#ref_d910f32f622b4615970569407d739ca6_problem_name_1" />
</originalText>
</translation>
</value>
I want to read the translation tag (displayName="Asthma"). I want to read asthma, its code value and code system.
But in MDHT I can't get translation tag inside value tag. I am doing get as:
entry.getAct().getEntryRelationships().get(0).getObservation().getValues().get(0) //no translation tag.
One of the advantages of using MDHT versus other JAVA/XML generations is we generate domain specific classes to help you navigate the document a bit more effectively
You should avoid using specific get() and generic getObservation because the underlying CDA standard constrains what is required but producers are able to place any sort of observation etc within the document. Here is a sample snippet to walk the problem section
The observation class itself and as such the problem observation value is a collection of ANY which need to properly cast to get to the CD type which in turn would have the translation property you are looking for.
hth
Sean
ProblemSection ps = ...
for (ProblemConcernAct cpc : ps.getConsolProblemConcerns()) {
for (ProblemObservation pos : cpc.getProblemObservations()) {
for (ANY any : pos.getValues()) {
if (any instanceof CD) {
CD code = (CD) any;
for (CD translationCode : code.getTranslations()) {
System.out.println(translationCode.getCode());
}
}
}
}
}
I'm quite new to Spring Framework. Could someone please help me understand the spring configuration below?
<?xml version="1.0"?>
<configuration>
<spring>
<context>
<resource uri="config://spring/objects" />
</context>
<objects xmlns="http://www.springframework.net">
<object type="Test.aspx">
<property name="AService" ref="AService" />
<property name="BService" ref="BService" />
</object>
</objects>
</spring>
</configuration>
Basically questions in my mind are:
What does this line means:
<resource uri="config://spring/objects" />
and this:
<object type="Test.aspx">
<property name="AService" ref="AService" />
<property name="BService" ref="BService" />
</object>
Does config: means configuration file?
Does ref means Classes in C#?
<resource uri="config://spring/objects" /> means that the spring container should read a configuration section from an application configuration file (app.config or web.config).
<object ... is an object definition; this defines an object in your container. An object can have dependencies. In your case, the Test.aspx page has properties named AService and BService. The container will set these properties to the objects defined elsewhere in your container.
What might be a bit confusing here is the double usage of ="AService" in <property name="AService" ref="AService" />:
name=: refers to the name of the property on your class Test, there is a property defined as public IMyService AService { get; set; }
ref= : refers to another object defined in your container, there is an object definition like <object id="AService" type="MyNamespace.MyClass, MyAssembly" /> somewhere in your configuration.
The "Instantiating the container" section of the spring docs does a good job of explaining this further.
Is there anyway to get Spring.Net to log what it's doing as it constructs objects? Something on the order of
Constructing Object A
Constructing Object B
etc etc.....
I need to resolve a circular dependency within my application, and seeing the order in which Spring is creating the objects could be a huge help.
This can easily be done. Spring uses Common.Logging. You can grab logging output from Spring.Objects.Factory.* classes and look for ... Creating instance of Object 'your-id-here' ... messages.
Note that you have to log at DEBUG level, which means you'll see quite a lot of other information too.
The following app.config would log creation calls to the console, using log4net:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<sectionGroup name="common">
<section name="logging" type="Common.Logging.ConfigurationSectionHandler, Common.Logging" />
</sectionGroup>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
</configSections>
<common>
<logging>
<factoryAdapter type="Common.Logging.Log4Net.Log4NetLoggerFactoryAdapter, Common.Logging.Log4Net">
<arg key="configType" value="INLINE" />
</factoryAdapter>
</logging>
</common>
<log4net>
<appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger %ndc - %message%newline" />
</layout>
</appender>
<!-- this logger will catch creation messages -->
<logger name="Spring.Objects.Factory">
<level value="DEBUG" />
<appender-ref ref="ConsoleAppender" />
</logger>
</log4net>
</configuration>
So most of this is boiler-plate Common.Logging and log4net configuration, which is well documented on the Common.Logging website. If you want to append to a file or something else, see the log4net docs.