How to configure address in JAX-WS CXF Client using JNDI lookup - spring

I am looking up my JNDI value of endpoint (properties file is not an option) on server like this
<jee:jndi-lookup id="MyEndpoint" jndi-name="endpoint.url" />
I would like to use the above looked up value in the place of address.
<jaxws:client id="helloClient"
serviceClass="demo.spring.HelloWorld"
address="http://localhost:9002/HelloWorld" />
I tried address="${MyEndpoint}". Did n't work. Looks like I have to use another bean, which uses jndi value and use its method to return as string i.e. address="#{MyBean.geyMyEndpoint()}". Doesn't look clean that way. Any suggestions?

You should be able to use Spring Expression Language to get the behavior you want, without using another bean. The following works for me in Tomcat 7:
<jee:jndi-lookup id="MyEndpoint" jndi-name="java:comp/env/MyEndpoint" />
<jaxws:client id="helloClient"
serviceClass="demo.spring.HelloWorld"
address="#{MyEndpoint}" />

Also on another note from Spring 3.1 - Spring has unified property management. so instead of the above solution you can do this
<jaxws:client id="helloClient" serviceClass="demo.spring.HelloWorld" address="${endpoint.url}" />
endpoint.url could be any property(system, environment etc) and it will automatically resolve the property. so no need to do separate JNDI lookup and your code looks clean.

Related

context:property-placeholder comma-separated list of resources don't work with system property placeholder

I can't entirely configure property-placeholder from system property because I can't give comma-separated list of resources.
I'm trying to do like:
<context:property-placeholder location="${config-location}" />
I use system property to configure this. It works if I give one location only, like "classpath:main.properties", but it does not if I'm trying this: "classpath:main1.properties,classpath:main2.properties".
If I use this latter exact value directly in xml configuration it works fine. I guess it resolves comma-separation earlier than placeholders. It should be the other way around.
P.S : version 4.3.4
Another possible worth tryout would be,
<context:property-placeholder location="#{systemProperties['config-location']}" />
how to read System environment variable in Spring applicationContext

Spring customised PropertyPlaceholderConfigurer

I have config xml based spring application for which I have moved proprties required at start up time in database. It was very difficult to manage hundreds in property file and that is why database is introduced. To read properties a spring restful service is developed to return a map of all properties required at start up time.
I want to know how to replace properties reading from a map to spring context file e.g. ${config.service.url} should be polulated from a map read via web service.
One option I considered is to upgrade to Annotation based and start using MapPropertySource and Environment interface as environment.getRequiredProperty("config.service.url"). However upgrading to Annotation based is a big impact on project and is no at this time.
Second option that I am looking forward is to have a customised PropertyPlaceholderConfigurer.
Any pointer/help on this will be great.
Cheers,
Amber
You could define a PropertyPlaceholderConfigurer, but instead of specifying a file location, you can pass the properties directly as returned by your restful service.
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="properties" .../>
</bean>

How to retrieve context parameters in Spring 3.1 xml context

It seems like there's been a few iterations of property support in spring it's hard to tell what's best practice and the manuals are written from the point of view of someone who is familiar with every other iteration. I feel like this should be a simple and common requirement but given how hard it's been please correct me if there's a more idiomatic way.
What I want is to pass an additional properties file to my spring web app based on a context property which the client is setting using a tomcat descriptor like so
<Context path="/foo" reloadable="true">
<Parameter name="foo.config" value="file:${catalina.base}/conf/foo.properties"/>
</Context>
In spring for the live profile I have this
<beans profile="live">
<context:property-placeholder location="classpath:timetabling.live.properties,${timetabling.config}"
ignore-resource-not-found="true" />
</beans>
So I'd assumed this doesn;t work because I'm trying to configure placeholder suppport with a placeholder. If I use a system property however then this works fine. I know that spring 3.1 has baked in support for system and environment properties so I guess my question is how can I augment this support with something context aware before the placeholder is resolved?
--Update--
looking at http://blog.springsource.org/2011/02/15/spring-3-1-m1-unified-property-management/ particularly at footnote 1, I would expect to have a DefaultWebEnvironment which should already have aceess to context init params. Now I am more confused, can someone provide me with a concrete example of context property retrieval? At this point I feel like I've read every javadoc available and they are just not helpful.
<context:property-placeholder /> sets up a PropertyPlaceholderConfigurer which reads from .properties, system properties and environment variables. A Tomcat context.xml however sets up a servlet context init parameter. So what you need is a ServletContextPropertyPlaceholderConfigurer.

Tomcat vs Jetty JNDI Lookup

I use Spring to configure my Java Web App and in my Spring configuration I obtain a datasource via JNDI for Jetty as follows:
<jee:jndi-lookup id="dataSource" jndi-name="jdbc/myDataSource" />
but this won't work with Tomcat. With Tomcat I have to do this:
<jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/myDataSource" />
Whats the best way to solve this? I am already using JNDI as a way to externalize configuration, so I can't externalize my externalized configuration! At the same time I absolutely loath the idea of having two separate Spring configuration files. HELP!!!
I found an answer here, but I thought it was a bit complicated, but it did give me the idea to use the very cool ServerDetector class that blogger had found.
Once I can dynamically figure what type of server I am running in, I was able to use the Spring expression language to do the rest of the work:
<jee:jndi-lookup id="myAppDataSource"
jndi-name="#{ (AppServerType == 'Jetty' ? 'jdbc/' : 'java:comp/env/jdbc/') +
'myAppDataSource' }" />
Easy!
After some experimenting, I figured out I could just force Jetty to use the same JNDI path as Tomcat. The following snippet is from my jetty-env.xml file:
<New id="myDataSource" class="org.mortbay.jetty.plus.naming.Resource">
<!-- We MUST specify the entire JNDI path here to force compliance with the Tomcat/J2EE convention -->
<Arg>java:comp/env/jdbc/myDataSource</Arg>
<Arg>
<New class="com.atomikos.jdbc.nonxa.AtomikosNonXADataSourceBean">
<Set name="uniqueResourceName">sbeDatabase</Set>
...............
</New>
</Arg>
</New>
Not sure if this is ideal, but it works.
Update:
It works if you put your jetty-env.xml file inside the WAR...but for whatever reason, one you move this configuration outside the WAR and into a context fragment file in Jetty's "contexts" directory then it throws an exception:
Check it out: http://jira.codehaus.org/browse/JETTY-273
The cleanest way to do it is to configure your configuration. ;)
Use a Spring property place holder. See
http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/beans.html#beans-factory-placeholderconfigurer
The basic idea is that you just put a placeholder in your spring config with a property, and then it reads matching property from a properties file. You generate the properties file in your build process. Ive seen it done where the build tool (ant) reads an environment variable and then creates a properties file appropriate for the environment based of a skeleton file populated with tokens.

why is jax-ws spring service reference prefixed with #, as in ws:service bean="#myService"

I've developed a web service with jax-ws and Spring using the tutorials at the jax-ws commons website. It shows you how to define and reference your service from your spring applicationContext file (https://jax-ws-commons.dev.java.net/spring/).
What is the reason for the "#" when referencing the web service? I would expect to see something more like
<ws:service name="myEventWS" ref="eventWebService"/>
but following example at the above link I created the following which works.
<bean id="eventWebService" class="com.myws.EventWS">
<property name="model" ref="EventModel"/>
</bean>
<wss:binding url="/EventWS">
<wss:service>
<ws:service bean="#eventWebService"/>
</wss:service>
</wss:binding>
<ws:service> is using a custom configuration namespace, which is a feature of Spring which allow you to express complex bean graphs using simpler namespace. The meaning and interpretation of these custom namespaces is down to the implementation in question, in this case the JAX-WS-Commons project. It seems the authors of that decided that bean=#eventWebService means what you refer to as ref="eventWebService".
I don't know whay they did it that way, maybe they thought it was more readable... maybe they thought that bean=eventWebService (without the hash) means a name, rather than a reference... I don't know. The documentation isn't very clear either.
Either way, I'm pretty sure sure it's not a core Spring syntax, nor a convention that I've seen before.
the "#" tells the bean that it's not a class, but rather a ref.
HTH
#eventWebService refers to the bean of type EventWebService (according to the default Spring naming convention when bean is is not specified).

Resources