log4j2 how to read property variable from file into log4j2 - java

Background: As usual we have various life cycles like dev. stage, lt, prod all these are picked at deploy time from environment variable ${lifecycle}.
So JNDI setting we stores in ${lifecycle}.properties as variable datasource.jndi.name=jdbc/xxx. As other beans are also using this properties file, it is verified that such variable is loaded & file is in classpath, but somehow I am not able to consume this variable in log4j2.xml in below JDBC Appender.
<JDBC name="DBAppender" tableName="V1_QUERY_LOG" bufferSize="4" ignoreExceptions="false">
<DataSource jndiName="${sys:datasource.jndi.name}" />
<Column name="event_date" isUnicode="false" isEventTimestamp="true" />
<Column name="log_level" isUnicode="false" pattern="%level" />
<Column name="logger" isUnicode="false" pattern="%logger" />
<Column name="message" isUnicode="false" pattern="%message" />
<Column name="exception_msg" isUnicode="false" pattern="%ex{full}" />
</JDBC>
I have tried some option like "${datasource.jndi.name}" too, or is there any way I can fit the solution in
<Properties>
<Property name="datasource.jndi.name">get datasource.jndi.name from {lifecycle}.properties</property>
</Properties>

If you are not using java system properties, but environment variables, you should not use the ${sys:variable} prefix, but the ${env:variable} prefix instead. See also http://logging.apache.org/log4j/2.x/manual/lookups.html#EnvironmentLookup

In general the placeholders that work in Spring bean configuration files do not work in Log4j configuration. They look the same, but the syntax and underlying discovery mechanism are completely different.
For instance ${sys:something} attempts to resolve a Java system property. System properties are usually passed to JVM as command line arguments in format -Dkey=value and not stored in property files.
You can try to use Resource bundle syntax ${bundle:MyProperties:MyKey} however this will load from that specific file and will not perform any additional Spring substitutions.
See also:
http://logging.apache.org/log4j/2.x/manual/configuration.html#PropertySubstitution

Related

Ant Multiple Property Values with the Same Name

I am working on an ant build script. How do i set the two property value with the same name:
<property name="java.src.dir" location="src" />
<property name="java.src.dir" location="src/java" />
In my application some of the directories are src/java and some are src. I need to make it flexible enough to work on both.

What is the equivalent of System.setProperty (java) in Google Application Engine (in java again)

I got an exception at System.setProperty in Java when I've tried to deploy the application in GAE. Any ideas what can be wrong?
You can set Java system properties or environment variables for App Engine applications in the respective appengine-web.xml configuration file.
<system-properties>
<property name="property1" value="value1" />
<property name="property2" value="value2" />
</system-properties>
You can find more details in App Engine documentation.

Using/converting an XML file to a Spring bean definition

I have defined a Spring application context xml which will be edited by end users to add new beans.Something like:
<bean name="myBeanName1" class="com.xxx.Yyy">
<property name="type" value="type1" />
<property name="name" value="name1" />
<property name="arguments" value="arg1" />
</bean>
<bean name="myBeanName2" class="com.xxx.Yyy">
<property name="type" value="type2" />
<property name="name" value="name2" />
<property name="arguments" value="arg2" />
</bean>
.
.
.
Now I am asked to change this to a normal xml so that users wont be bothered by bean property and class names:
<def name="Name1">
<type>type1</type>
<argument>arg1</argument
</def>
<def name="Name2">
<type>type2</type>
<argument>arg2</argument
</def>
As my code is using the bean, how can I use the new xml with minimal code change so that it is converted to a bean definition as earlier and things work as before?.
I dont know if Spring has a solution for this out of the box. What I thought was applying stylesheet to the new xml to create my older bean. Any other better/elegant solution for this?
Edit: Now that user input is not inside the bean anymore, is it possible to use the new xml to inject to a #Component class?
Spring supports creating custom tags. You need to create xsd schema, NamespaceHandlerm, implement BeanDefinitionParsers and make spring aware of these by creating spring.handlers & spring.schemas special files.
Have a look at Extensible XML authoring
Example:
<beans xmlns declaration goes here>
<yournamespace:yourcustomtag id="some id">
<yournamespace:some_other_tag your-custom-attribute="some value" />
</yournamespace:yourcustomtag>
</beans>

Duke Fast Deduplication: java.lang.UnsupportedOperationException: Operation not yet supported?

I'm trying to use the Duke Fast Deduplication Engine to search for some duplicate records in the database at the company where I work.
I run it from the command line like this:
java -cp "C:\utils\duke-0.6\duke-0.6.jar;C:\utils\duke-0.6\lucene-core-3.6.1.jar" no.priv.garshol.duke.Duke --showmatches --verbose .\config.xml
But I get an error:
Exception in thread "main" java.lang.UnsupportedOperationException: Operation no
t yet supported
at sun.jdbc.odbc.JdbcOdbcResultSet.isClosed(Unknown Source)
at no.priv.garshol.duke.datasources.JDBCDataSource$JDBCIterator.close(JD
BCDataSource.java:115)
at no.priv.garshol.duke.Processor.deduplicate(Processor.java:152)
at no.priv.garshol.duke.Duke.main_(Duke.java:135)
at no.priv.garshol.duke.Duke.main(Duke.java:38)
My configuration file looks like this:
<duke>
<schema>
<threshold>0.82</threshold>
<maybe-threshold>0.80</maybe-threshold>
<path>test</path>
<property type="id">
<name>ID</name>
</property>
<property>
<name>LNAME</name>
<comparator>no.priv.garshol.duke.comparators.ExactComparator</comparator>
<low>0.6</low>
<high>0.8</high>
</property>
<property>
<name>FNAME</name>
<comparator>no.priv.garshol.duke.comparators.ExactComparator</comparator>
<low>0.6</low>
<high>0.8</high>
</property>
<property>
<name>MNAME</name>
<comparator>no.priv.garshol.duke.comparators.ExactComparator</comparator>
<low>0.3</low>
<high>0.5</high>
</property>
<property>
<name>SSN</name>
<comparator>no.priv.garshol.duke.comparators.ExactComparator</comparator>
<low>0.0</low>
<high>1.0</high>
</property>
</schema>
<jdbc>
<param name="driver-class" value="sun.jdbc.odbc.JdbcOdbcDriver" />
<param name="connection-string" value="jdbc:odbc:VT_DeDupe" />
<param name="user-name" value="aleer" />
<param name="password" value="**" />
<param name="query" value="select SocialSecurityNumber, LastName, FirstName, MiddleName, empssn from T_Employees" />
<column name="SocialSecurityNumber" property="ID" />
<column name="LastName" property="LNAME" />
<column name="FirstName" property="FNAME" />
<column name="MiddleName" property="MNAME" />
<column name="empssn" property="SSN" />
</jdbc>
</duke>
It doesn't really tell me what is unsupported...I'm just trying it out, nothing serious with the configuration yet.
As mbonaci says, the problem is that the JDBC driver's isClosed() method is not implemented. This even though implementing it would be no harder than simply writing "return closed".
I added an ugly workaround for this issue now. Please do an "hg pull" and try again.
Which Java version are you using?
sun.jdbc.odbc.JdbcOdbcResultSet.isClosed first appeared in Java 1.6. and it still looks like this in v1.7 (I haven't checked in Java 8):
public boolean isClosed() throws SQLException {
throw new UnsupportedOperationException("Operation not yet supported");
}
So simply don't call that method. Use some other way of checking whether resultset is closed.
Or if you cannot change the code ask the project's authors for help (I see there was an effort to solve exception when closing RS).

finding a property using Spring and Webapp properties placeholder

This is a "simple" problem and I am seeking both a how-to and/or a you're-dumb-don't-do-that. I am open to both.
I am building a war file and want the structure to be:
WEB-INF/
properties/
<my properties files>
classes/
...
spring/
<my spring files>
Is that dumb? I know that I can access the properties files though the property-placeholder but I'd rather not nest the properties in the classes section - it doesn't make sense to me.
So the Spring file looks like this:
<context:property-placeholder location="classpath:properties/*.properties" />
if I want to access them in the classes area. I thought that
<context:property-placeholder location="properties/*.properties" />
would let me just put the directory under WEB-INF directly...am I wrong (ps I think I am :) ).
Any advice?
This should work
<context:property-placeholder location="WEB-INF/properties/*.properties" />
WEB-INF is not the root of the of the web-app, so you need to add WEB-INF to the path.
spring-context-3.1.xsd
<xsd:attribute name="location" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
<![CDATA[
The location of the properties file to resolve placeholders against, as a Spring
resource location: a URL, a "classpath:" pseudo URL, or a relative file path.
Multiple locations may be specified, separated by commas. If neither location nor properties-ref is
specified, placeholders will be resolved against system properties.
]]>
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
You can't do it the way you want since the classpath for the Classloader will be the /classes directory and any jars in the /lib directory. This is the standard configuration for a war file.
Wars and ears have specific configurations which you have to follow for the files to be valid. If you think about it, it would make it difficult to have different vendors provide web containers that could deploy the same war file if there was no standard format. There is a pretty informative page here.
To achieve something similar to what you want, you can simply have directories of /classes/properties and /classes/spring and look them up appropriately from your classpath ("classpath:properties/myfile.properties).
I am not sure what you want to achieve. Here the method I use to inject the properties from a basic properties file to a bean:
In the spring files (XML bean definitions), I add the reference to my property file (myfile.properties):
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:myfile.properties" />
</bean>
and then I add my references to the properties (db.url is the URL address for my database connection, I kept only the bean properties referenced in my property file).
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<!-- results in a setDriverClassName(String) call -->
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url"><value>${db.url}</value></property>
<property name="username"><value>${db.login}</value></property>
<property name="password"><value>${db.password}</value></property>
</bean>
By default, if the property is not defined in the property file, Spring uses the System Properties (this behaviour can be changed).

Categories