What does java:comp/env/ do? - spring

I just spent too much time of my day trying to figure out some errors when hooking up some JNDI factory bean. The problem turned out to be that instead of this...
<bean id="someId" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/jdbc/loc"/>
</bean>
I had actually written this...
<bean id="someId" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="jdbc/loc"/>
</bean>
I infer that the java:comp/env/ perhaps references some environment variable and makes it so that, ultimately, my context file is looked at. The only difference is java:comp/env/. From an expert's mouth, what does that do?
Without the java:comp/env/ prefix in the value, I would get an error that said "Name jdbc is not bound in this Context".

Quoting https://web.archive.org/web/20140227201242/http://v1.dione.zcu.cz/java/docs/jndi-1.2/tutorial/beyond/misc/policy.html
At the root context of the namespace
is a binding with the name "comp",
which is bound to a subtree reserved
for component-related bindings. The
name "comp" is short for component.
There are no other bindings at the
root context. However, the root
context is reserved for the future
expansion of the policy, specifically
for naming resources that are tied not
to the component itself but to other
types of entities such as users or
departments. For example, future
policies might allow you to name users
and organizations/departments by using
names such as "java:user/alice" and
"java:org/engineering".
In the "comp" context, there are two
bindings: "env" and "UserTransaction".
The name "env" is bound to a subtree
that is reserved for the component's
environment-related bindings, as
defined by its deployment descriptor.
"env" is short for environment. The
J2EE recommends (but does not require)
the following structure for the "env"
namespace.
So the binding you did from spring or, for example, from a tomcat context descriptor go by default under java:comp/env/
For example, if your configuration is:
<bean id="someId" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="foo"/>
</bean>
Then you can access it directly using:
Context ctx = new InitialContext();
DataSource ds = (DataSource)ctx.lookup("java:comp/env/foo");
or you could make an intermediate step so you don't have to specify "java:comp/env" for every resource you retrieve:
Context ctx = new InitialContext();
Context envCtx = (Context)ctx.lookup("java:comp/env");
DataSource ds = (DataSource)envCtx.lookup("foo");

There is also a property resourceRef of JndiObjectFactoryBean that is, when set to true, used to automatically prepend the string java:comp/env/ if it is not already present.
<bean id="someId" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="jdbc/loc"/>
<property name="resourceRef" value="true"/>
</bean>

After several attempts and going deep in Tomcat's source code I found out that the simple property useNaming="false" did the trick!! Now Tomcat resolves names java:/liferay instead of java:comp/env/liferay

Related

How to define a PropertyPlaceholderConfigurer local to a specific bean?

I've been using org.springframework.beans.factory.config.PropertyPlaceholderConfigurer and in my experience ("citation needed" LOL) it sets the property values globally.
Is there a way to specify different PropertyPlaceholderConfigurer instances for different beans within the same application context xml?
My current code is similar to
<bean id="a" class="X">
<property name="foo" value="bar"/>
<property name="many" value="more"/>
</bean>
<bean id="b" class="X">
<property name="foo" value="baz"/>
<property name="number_of_properties" value="a zillion"/>
</bean>
I would like to do something like (pseudo-code below):
<bean id="a" class="X">
... parse the contents of "a.properties" here ...
</bean>
<bean id="b" class="X">
... parse the contents of "b.properties" here ...
</bean>
The above is non-working pseudo code to illustrate the concept; the point being, I want a different properties file to feed each bean.
WHY?
I want to have those specific properties in separate properties file and not in XML.
I think the following link can br helpful to you.
Reference Link
where #Value("${my.property.name}") annotation is used to bind the property file to a variable of type Properties which will reside in your bean class where you intend to use that properties file.
and you can define multiplte proprtiesplaceholder as below:
<bean id="myProperties"
class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="locations">
<list>
<value>classpath*:my.properties</value>
</list>
</property>
</bean>
and use the id as reference in your bean variable to initialize properties file to the bean.
And it will be handy to include with placeholder bean.
Kindly refer Importance of Unresolvable Placeholder link for detailed info regarding its usage.
Hope this was helpful.

Difference b/w primary and autowire-candidate attribute of bean tag in spring

I am new to spring. When i am going through auto wiring byType i came to know about these attributes primary and autowire-candidate.
I didn't get the exact difference b/w these two as setting these parameter to false will make the other bean a candidate for autowiring.
Can anybody help me in understanding these two.
Thanks
Let say there is interface
interface Translator { String translate(String word);}
Your application use the translator widely to translate from English to Polish. However, is some specific case you want to use dedicated translator, because vocabulary is specific. For example, string always means "sequence of characters" but never "underwear".
Sample configuration:
<bean class="EnglishToPolishTranslator" />
<bean class="ComputerScienceEnglishToPolishTranslator" autowire-candidate="false"/>
Everywhere EnglishToPolishTranslator will be autowired except some concrete place where ComputerScienceEnglishToPolishTranslator will be injected by reference.
Some day next customer arrive with requirement: use simpler words. The requirement is achieved by class SimpleEnglishToPolishTranslator. But computer science translator should remain unchanged: it is too costly to modify it.
Your company want keep product easy to maintain. Base application will not be modified, but for the customer the product will extended with extra library configured:
<bean class="SimpleEnglishToPolishTranslator" primary="true"/>
In result, everywhere SimpleEnglishToPolishTranslator will be used except computer science area.
Maybe it is overcomplicated, but shows a difference I found between autowire-candidate and primary
BTW, "autowire-candidate" doesn't have corresponding annotation. It looks to me that "autowire-candidate" is dead end in Spring evolution
if we configure bean for more than one time with different ids then IOC will throw an Exception. To overcome this duplicate beans problem, we can use autowire-candidate=”false” or primanry="true"
Example: i have two classes Mobile and Processor
Case -1: autowire-candidate=”false”
<bean id="mobile" class="com.Mobile" autowire="byType">
<property name="mobileName" value="Redmi"></property>
<property name="mobileModel" value="Note 5"></property>
</bean>
<bean id="process1" class="com.Processor"
autowire-candidate="false">
<property name="process" value="2GHz"></property>
<property name="ram" value="4GB"></property>
</bean>
<bean id="process2" class="com.Processor">
<property name="process" value="1GHz"></property>
<property name="ram" value="3GB"></property>
</bean>
As per above configuration, process1 bean will be ignored and process2 bean will be injected.
Case -2: primanry="true"
<bean id="mobile" class="com.Mobile" autowire="byType">
<property name="mobileName" value="Redmi"></property>
<property name="mobileModel" value="Note 5"></property>
</bean>
<bean id="process1" class="com.Processor" primary="true">
<property name="process" value="2GHz"></property>
<property name="ram" value="4GB"></property>
</bean>
<bean id="process2" class="com.Processor">
<property name="process" value="1GHz"></property>
<property name="ram" value="3GB"></property>
</bean>
As per above configuration, process2 bean will be ignored and process1 bean will be injected.

Spring Configuration Query

I have one spring configuration file with entry like below...
<bean id="beanId" class="a.b.c.d.MyBean">
<property name="firstProperty" value="report_{date}.xls"/>
</bean>
Somewhere in my java code, I am fetching this bean and then its property "firstProperty" later.
I am little curious, when I get the value of property "firstProperty" I get report_.xls i.e report_20130307.xls
I have searched all my code including bundles, xmls but not clear that where we are setting {date} with todays timestamp.
Do you have any clue where we can do this?
Thanks
Jai
It is the property-placeholder mechanism.
Read more on http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/xsd-config.html#xsd-config-body-schemas-context-pphc.
In most of the cases, the values to property are set from properties file using expression language. Like
<bean id="dataSource" class="a.b.c.d.DataSource">
<property name="databaseUrl" value="{db.url}"/>
</bean>
Or if the property is a ref to another bean, e.g. Object B is member variable of Object A.
<bean id="refA" class="a.b.c.d.A">
<property name="b" ref="refB"/>
</bean>
<bean id="refB" class="a.b.c.d.B">
</bean>
Its quite simple guys...as we know setter are called for each property. So same in my case,
In bean we are setting variable "firstProperty" + today timestamp like below.
public void setfirstProperty(String firstProperty) {
this.firstProperty = firstProperty + <methodToReplaceDateStringWithTimeStamp>;
}
Thanks
Jai

Is it possible to set a resource property value inside applicationcontext?

In an applicationcontext.xml, is it possible to set a value which can be used later in SPEL expressions?
For example is there a way to do this?:
<setProperty name="foo" value="someval" />
<bean id="beanId" name="beanName" class="SomeClass">
<property name="someVal" value="blah_${foo}"/>
</bean>
The actual reason I want to do this is that I use statements to create entity managers which are used in many different application contexts. The problem is that the entity managers require a unique name which is used by Bitronix to create a local file which breaks if multiple unit tests run at the same time using the same name for that field. To set that unique name I currently have a separate properties file for each application context and import it to get a unique name from it.
Rather than doing that nonsense I'd rather just do this:
<setProperty name="uniqueName" value="someUniqueName" />
<import resource="classpath*:shared/db/fooDb.xml" />
You can do this using Spring-el and util namespace:
<util:properties id="myprops">
<prop key="foo">someval</prop>
</util:properties>
<bean id="beanId" name="beanName" class="SomeClass">
<property name="someVal" value="blah_#{myprops.foo}"/>
</bean>

injecting a spring bean property different values according to its context

I have a spring bean my_bean with a property my_map, and I want to inject it with the value "X" or with the value "Y". The bean:
<bean id="my_bean">
<property name="my_map">
<map>
<entry key="p" value="X" />
</map>
</property>
</bean>
It's referenced in a very deep hierarchy by the bean root_a:
<bean id="root_a">
<ref bean="root_a_a"/>
</bean>
<bean id="root_a_a">
<ref bean="root_a_a_a"/>
</bean>
<bean id="root_a_a_a">
<ref bean="my_bean"/>
</bean>
and this entire deep hierarchy is referenced again from the bean root_b. In the ref of my_bean from this hierarchy I would the property to be injected with the value "Y", but I would not like to duplicate the entire hierarchy twice.
<bean id="root_b">
<ref bean="root_a_a"/>
</bean>
How do I do this in the spring XML? can you think of a clever spring EL solution? something else? I prefer all my configuration to be done in the XML and no Java code...
By default Spring beans are singletons, which means that once bean="my_bean" is created it is shared between other components e.g. shared between A => bean id="root_a_a_a" and B => bean id="root_b_b_b"
The answer to your question depends on what exactly you are trying to achieve.
Two Beans
If bean="my_bean" does not need to be shared between A and B, then create two beans:
inject this one to A
<bean id="myBeanX" class="My">
<property name="culprit" value="X"/>
</bean>
and this one to B
<bean id="myBeanY" class="My">
<property name="culprit" value="Y"/>
</bean>
notice they both are instances of the same class.
You can also inline them into collaborators (A / B) if you don't need them for anything else:
<bean id="root_a_a_a">
<constructor-arg>
<bean class="My">
<property name="culprit" value="X"/>
</bean>
</constructor-arg>
</bean>
You can also have a factory bean that creates root_a_a_a given the property for a class My, but that would be an overkill.
Single Bean
In case A and B needs to share the exact same reference to bean="my_bean", the question is: are you ok with A and B changing my_bean's state after my_bean is created? Probably not.
If you are, which would be 0.41172% chance, you can change my_bean's value to whatever you need in A's or B's constructors => would not recommend
Hence you either would go with the Two Bean approach (which is most likely what you want), or you would need to refactor a property for "X" and "Y" into another e.g. myConfig component.
EDIT after the question was edited
If root_a and root_b will not be used together in the same instance of the context,you can use Spring Profiles (example), or SpEL / Property Based solutions (example)
e.g.
<bean id="my_bean">
<property name="my_map">
<map>
<entry key="p" value="${ENV_SYSTEM:X}" />
</map>
</property>
</bean>
It will set it to X by default, unless a ENV_SYSTEM system variable is set (e.g. to Y).

Resources