Reconfigure mongodb connection on each request - spring

I'm using an external module on a webapp, meaning I can't change that code, that uses Spring Data. It starts using some properties like ${mongoURI} and ${mongoDB} to connect to a database and feed its repositories, which you access through a Service wiring it to your Controllers.
The problem I'm trying to solve is that we have a database per user, therefore I need a different connection for each user, but I'm not sure how Spring supports it.
I import this service like this:
<!-- This is in the imported jar -->
<import resource="classpath:/service-mongo-context.xml" />
<!-- This is in my folder structure -->
<context:property-placeholder location="classpath:/mongodb-config.properties" />
And then in my Controller I just:
#Autowired private Service service;
I would like to know if it is possible to rebuild the entire service each time you receive a connection passing a different ${mongoURI} and ${mongoDB}, perhaps changing variables in #Autowired.

Related

Binding datasource to application when using springBootApplication in Liberty?

When deploying "regular" web apps to Liberty, I was used to binding the global datasource configured in Liberty's server.xml to the individual application by using a child element within the element, like this:
<application context-root="helloApp" location="..." name="helloApp" type="war">
<application-bnd>
<data-source id="db2appDs" name="jdbc/datasource" binding-name="jdbc/theDB"/>
</application-bnd>
...
</application>
<dataSource id="db2ds" jndiName="jdbc/theDB" type="javax.sql.DataSource">
...
</dataSource>
When configuring my first Spring Boot application to deploy to Liberty, I am trying to use the new <springBootApplication> element for it - but I don't seem to be able to add a binding for the datasource I want to use the same way, as this element doesn't seem to support such a child. (It seems to want only <classloader> as a child).
I've seen people suggest I use an #Resource annotation that includes both application-local JDNI name and global JNDI name for the datasorce - but that defeats the purpose, since I don't want to know what the global name is until deploy time.
Is there another way to do this, like we used to before? Or are applications deployed through <springBootApplication> expected to know the global JNDI name of the datasource(s) they want?
Application-defined datasources are not supported for <springBootApplication/>’s. While your application may certainly access a Liberty datasource using its global JNDI name, you should configure the spring.datasource.jndi-name property within your Spring Boot application as described in section 29.1.3 of the Spring Boot features reference. For your example try spring.datasource.jndi-name=jdbc/theDB.

How to make Drools KnowledgeAgent be dependant a custom component with Spring configuration?

I have my KnowledgeAgent setup as
<drools:kagent kbase="kbase" id="knowledgeAgent" new-instance="false" >
<drools:resources>
<drools:resource source="classpath:change-set.xml" type="CHANGE_SET" />
</drools:resources>
</drools:kagent>
So it scans the change-set.xml from classpath for resources. And I have another component which will dynamially generate the change-set.xml based on rulefiles found on disk. The spring configuration for this is
<bean id="changesetHandler" class="ChangesetHandler" autowire="byName" lazy-init="true" />
The problem here is that the change-set.xml is generated by my custom component, but I cannot set the Drools KnowledgeAgent component to be dependant on it as it follows it's own schema which does not seem to have depends-on attribute.
Given that a knowledge agent listens for changes, it should reload the knowledge base as soon as your bean generates the change set. Why not load a default empty change set initially and then load the dynamic change set when it has been generated?
Personally I avoid the Drools-Spring components. I find it easier to create a service within my application, which holds my knowledge base. I can then define whatever dependencies I like within that service and ensure that any initialisation has been completed.

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 unregister an OSGI/Blueprint Service from within the Service?

In my application I have a Service ChatProtocolClient. The implementation is a tcp client which connects to a remote server in the blueprint "init-method" and disconnects in the "destroy-method".
I also have another bundle that uses this ChatProtocolClient's connection to read and post messages from a channel, ChatChannel.
Currently I have an xml file that creates a bean of the ChatProtocolClient, and creates a bean ChatChannel in which a reference to the created ChatProtocolClient service is injected.
But how can I handle disconnects from the server? I'd want to tell the Blueprint framework that my ChatProtocolClient instance is unusable now and it should unregister this instance.
Preferably Blueprint would then automatically call the destroy-method on all dependent beans (beans in which Blueprint injected this service reference) and initialize a new ChatProtocolClient bean and all beans that were destroyed because the dependency failed.
How can this be done?
I found a way to implement this. In this solutions it's not Blueprint that recreates instances of all dependent services. It goes like this:
Connection "Watchdog" beans.
Instead of creating "ChatProtocolClient" Beans, I created ConnectionWatchDog beans from xml. In these beans the BundleContext is injected and the connection properties are set from the .xml file.
The ConnectionWatchDog then tries to create/connect a ChatProtocolClient instance. If connection succeeds, it registers a service in the BundleContext (with bundleContext.registerService(..)). The ServiceRegistration is kept in the watchdog. The watchdog tests the connection on set interval (it runs it's own Thread). If the connection appears to have failed; the watchdog calls the serviceRegistration.unregister() and cleans up the remainders of the client connection instance, ands starts the whole proces of creating, connecting and registering an new ChatProtocolClient instance.
The ChatChannel
The ChatChannel is now configured in Blueprint with a . The xml looks like this:
<blueprint xmlns=...>
<reference-list id="chat-connection" member-type="service-object" interface="com.example.ChatProtocolClientInterface">
<reference-listener bind-method="onBind" unbind-method="onUnbind" ref="Channel1"/>
</reference-list>
<bean id="Channel1" class="ChatChannel" init-method="startUp">
<property name="chatProtocolClient" ref="chat-connection">
... some other properties ...
</bean>
</blueprint>
The member-type set to service-object, means that when a service is registered or unregistered, the ChatChannel will be informed with the "onBind" and "onUnbind" methods. As parameter, they'll get a ChatProtocolClientInterface instance.
I'm not sure whether this is the only or best solution, but it works for me. Note that with this example xml, you'll also need a setter for "chatProtocolClient"; currently I don't use the list that is set by blueprint and I only use the onBind and onUnbind methods.

Where to store database passwords in a spring application or use JNDI?

Seems like a simple task. I have a webapp which requires a database connection. I'd like to be able to drop an updated .war file on this app server and load a new version without having to re-edit an applicationConfig.xml file to specify the database connection parameters for production.
Is using the container to setup the data source and then referencing it from JNDI the preferred way to go? I think it is cleaner having it all defined in the spring .xml file, but I can't come up with a clean way to allow the production password to be set only once as we roll out new versions.
So, how do you specify your database connection information in a spring application so that you can upgrade it without having to re-edit the files?
If you use JNDI, how do you handle setting up of your tests since the JNDI is not going to be available outside of the container?
Thanks!
The typical way to externalize database connection properties is to store them in a .properties file and load using <context:property-placeholder .../> . Then you can have different .properties files for testing and production.
If you choose JNDI, you can use a Spring's mock JNDI support for testing.
One approach is for your Spring configuration file to be composed of fragments related to specific layers in your application.
One such fragment could contain your DataSource defintion. For production, this fragment would use a jee:jndi-lookup. And then for test, have a different fragment would use a DriverManagerDataSource ?
Update:
If you want to change the datasource after deployment, then you can use this technique, along with changing the which datasource is injected into your other beans using a PropertyPlaceholderConfigurer as explained in an old post I wrote
eg:
<bean class="foo.bar.SomeClassNeedingDataSource"">
<property name="dataSource" ref="${the.datasource.to.inject}" />
</bean>
<jee:jndi-lookup id="jndiDataSource" ... />
<bean id="driverManagerDataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
...
</bean>
# the properties file
the.datasource.to.inject = jndiDataSource
#the.datasource.to.inject = driverManagerDataSource

Resources