Marklogic XCC ContentSource using JNDI - java

I'm trying to get a Marklogic ContentSource object loaded from Tomcat's context.xml using JNDI and Spring.
I'm using Tomcat 8.5, and Spring 2.5 (unfortunately)
I have added the following to context.xml in Tomcat
<Resource name="MLContentSource" auth="Container" type="com.marklogic.xcc.ContentSource"
factory="com.marklogic.xcc.jndi.ContentSourceBeanFactory"
url="xcc://username:password#mymarklogic-server/DatabaseName"/>
And the following in my applicationContext.xml
<bean id="contentSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/MLContentSource"/>
</bean>
I have another bean declared in my applicationContext.xml that relies on the ContentSource bean. Its expecting a property to be set that is of type com.marklogic.xcc.ContentSource
<bean id="marklogicRepository" class="org.example.repository.ingestion.MarkLogicRepositoryImpl">
<property name="contentSource" ref="contentSource" />
</bean>
The issue is that the contentSource bean is of type JndiObjectFactoryBean and not com.marklogic.xcc.ContentSource. Is there something I'm missing to get a proper ContentSource from the JndiObjectFactoryBean?

It turns out the above code actually worked, my IDE was complaining about types but Spring will automatically cast the object stored inside JndiObjectFactoryBean to the target type at runtime.

Maybe try XQJ?
https://github.com/cfoster/xqj-pool-example/blob/master/src/main/java/simple/WithJNDI.java
http://xqj.net/
The XQuery API for Java
A standard Java interface to XML DataSources which support XQuery 1.0.
The XQJ API is to XML Databases as the JDBC API is to Relational Databases.
Is a light-weight design and is very easy to pick up.

Related

Use spring datasource of maven application within its dependency

I'm planning to build a library using spring and use it as an mvn dependency. The library would be used as an api in several projects. The api does only database operations. Can the included dependency get the datasource/jdbcTemplate of the project it is included in as an Autowired spring bean?
the datasource/jdbctemplate that we use in the spring application context is like following
<bean id="JdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<constructor-arg index="0" type="javax.sql.DataSource" ref="dataSource" />
</bean>
Yes. As long as there is a been with the name datasource and class javax.sql.DataSource. It needs to be available either through configuration, XML wiring or component scanning.
If creating a new library API it would be good to document what the user needs to make available for wiring.

How spring load configuration file by environment?

I use spring framework in my application,and i use some configuration files,but in different environment,i need to use different properties like db config properties.Now i put different files in different path,then i use maven profile method to package different WAR.
Now,i want to package only one WAR in all environment,and want by transfer different parameters to use different configuration files.In addition i don't want to put the configuration file out of the project.
You can use spring bean profiles or conditional beans.You can use following configuration to define propertyplaceholder beans for each environment.
<beans profile="environment1">
<bean
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>database_env1.properties</value>
</property>
</bean>
</beans>
<beans profile="environment2">
<bean
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>database_env2.properties</value>
</property>
</bean>
</beans>
For database configuration, a possible approach is to define the JDBC DataSource as a JNDI resource directly in your application server that you then use (see how) - this way your WAR file doesn't contain the connection information, the runtime environment does hold this info instead.
One advantage of this approach is that the connection information then can be managed by a server administrator instead of the application developer.
Not sure it meets your "no configuration outside project" requirement though.

Referencing a value from a spring config

First a bit of setup info:
I have a multi-tenant spring based application. The multi-tenant enabling library is an in-house developed tool where I work that I have to use. How it works is that there is an interceptor that sets in front of the servlet for the application. Upon a request hitting the servlet it loads a tenant specific spring config for "stuff" needed for the tenant specified on the url hitting the servlet.
As stated, the above is just a bit of background. Now to the issue/question:
What I want to do is to create, in the tenant configuration that is loaded, a value that I can use to inject where I need. So, is there a way I can just define a constant in a spring config and then reference it via #Value or #Resource in java code?
There will be no bean implementation behind it, it would just be purely and only a key/value that I can reference where needed in my application by name. So, something to the effect of:
<bean name="MyIdentifier">
<property name="theId" value="1001" />
</bean>
And then can I do something like?
#Value{MyIdentifier.theId}
String theId;
And have Spring be aware of and inject the value. The problem is that doing something like above Spring complains there is no implementation for the bean. Notice, no class specified for the bean. The reason I want to do this is every tenant config file will contain this bean, but the actual value will vary per tenant.
Is there some other type to use in the config to do this? If so, what schemas have to be on the config?
I am guessing I am either trying to make Spring do something not intended, or, this is so simple I cannot see it since I have stared at it too long. Anyway, thanks for the help.
You can not create bean tag in configuration file without providing class implementation. If you want to inject the value of fields, you have to go for properties file instead.
Create property file as below:
application.properties
theId=1001
Load property file in your configuration:
<bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
<property name="ignoreUnresolvablePlaceholders" value="true"/>
<property name="locations">
<list>
<value>classpath:application.properties</value>
</list>
</property>
</bean>
And access the property in your concrete class:
#Value("${theId}")
String theId;

applicationContext.xml not reading servletContext.contextPath

Im trying to read a properties file from an external location and I am trynig to use the contextPath name as the file's names beacuse I will run multiple instances of the app on he same server. I'm currently using SpringFramework 3.1.4
<context:property-placeholder location="file:/configFolder/#{servletContext.contextPath}.properties" />
the file name ends up being /configFolder/#{servletContext.contextPath}.properties
It does not replace the variable
is there another way to get this value?
Try:
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="file:/config/#{servletContext.contextPath}.properties" />
</bean>
#{servletContext.contextPath} is a variable only known in JSP and Facelets through Expression Language. This won't work in Spring. You should put your configuration file inside a resource folder in your jar and retrieve it from there instead.
You state that this worked in other projects but that was because Spring supported a variable called servletContext (which IMO is wrong). Looks like Spring MVC 3.2 doesn't support this anymore, as explained here: Resolving servletContext.contextPath Expression in Spring 3.2.

Spring JTA TransactionManager config: Supporting both Tomcat and JBoss

I have a web application using JPA and JTA with Spring. I would like to support both JBoss and Tomcat. When running on JBoss, I'd like to use JBoss' own TransactionManager, and when running on Tomcat, I'd like to use JOTM.
I have both scenarios working, but I now find that I seem to need two separate Spring configurations for the two cases. With JOTM, I need to use Spring's JotmFactoryBean:
<bean id="transactionManager"
class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="userTransaction">
<bean class="org.springframework.transaction.jta.JotmFactoryBean"/>
</property>
</bean>
In JBoss, though, I just need to fetch "TransactionManager" from JNDI:
<bean id="transactionManager"
class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="transactionManager">
<bean class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="resourceRef" value="true" />
<property name="jndiName" value="TransactionManager" />
<property name="expectedType"
value="javax.transaction.TransactionManager" />
</bean>
</property>
</bean>
Is there a way to configure this so that the appropriate TransactionManager - JBoss or JOTM - is used, without the need for two different configuration files?
I think you have missed the point of JNDI. JNDI was pretty much written to solve the problem you have!
I think you can take it up a level, so instead of using the "userTransaction" or "transactionManager from JNDI" depending on your situation. Why not add the "JtaTransactionManager" to JNDI. That way you push the configuration to the JNDI where it is supposed to be instead of creating even more configuration files [ like there aren't enough already ;) ].
You can use PropertyConfigurerPlaceholder to inject bean references as well as simple values.
For example if you call your beans 'jotm' and 'jboss' then you could inject your TM like:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE">
<property name="location" value="classpath:/path/to/application.properties"/>
</bean>
<bean id="jotm">...</bean>
<bean id="jboss">...</bean>
<bean id="bean-requiring-transaction-manager">
<property name="transactionManager" ref="${transaction.strategy}"/>
</bean>
Then you can swap transaction managers using
transaction.strategy=jotm in a properties file
-Dtransaction.strategy=jotm as a system property
This is one possible approach. See my blog for a more complete example.
Hope this helps.
If you are using Spring 2.5 you can use <tx:jta-transaction-manager/>. I have not used it with JBoss but it should work for you according to section 9.8 Application server-specific integration from the Spring reference manual.
The <tx:jta-transaction-manager/> approach will look for a transaction manager in several default locations listed here. If your JBoss transaction manager is not in one of those locations, I suggest you move it, if possible, or move it in Tomcat so that both containers have their TM in the same JNDI location.
Just adding my experience here so I don't have to re-suffer the experience again.
As bmatthews68, Chochos and these posters have said, use <tx:jta-transaction-manager/> in your Spring bean file; it definitely provides the appropriate level of abstraction and there's no need to do anything extra on the Spring side.
As for Tomcat, I declared <Transaction factory="org.objectweb.jotm.UserTransactionFactory" jotm.timeout="60" /> in the default/shared conf/context.xml file, which binds to java:comp/UserTransaction. As this is one of the places searched for by Spring, you shouldn't need to do anything else.
One gotcha though: if like me you use Maven, make sure you exclude any dependencies on the javax.transaction:jta jar or set the scope to provided. Otherwise you will experience classloader issues.

Categories