i am using single weblogic which host two web application. I am using spring container and below is my Ehcache configuration
<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager">
<property name="cacheManager" ref="ehcache"/>
</bean>
<bean id="ehcache" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" scope="singleton">
<property name="configLocation" value="classpath:ehcache.xml" />
<property name="shared" value="true" />
</bean>
As i mentioned shared attribute as true, i was expecting there will be single cache manager and single cache .But i can see two customerCache
elements in memory separate for each application. How can i make it truly singleton per jvm with spring across application ?
for example
<cache name="customerCache" maxElementsInMemory="1000" eternal="false" overflowToDisk="false" memoryStoreEvictionPolicy="LRU" />
In order to achieve this, you will have to share a common Ehcache CacheManager between your two applications.
For Ehcache, this means having the CacheManager loaded by the same class loader in both applications.
Ways to achieve this are:
Find a way to share a Spring context between your two applications (see this question) or
Move Ehcache library to a shared lib system which will give you the shared cache loader, and then make sure its initialisation is properly handled by either webapps (but not both)
Related
I am deploying an application where I need to maintain some data in Ignite cache. I used in memory Ignite cache. Here is the Ignite configuration I have used:
<property name="cacheConfiguration">
<list>
<bean
class="org.apache.ignite.configuration.CacheConfiguration">
<property name="name" value="IGNITE_DATA" />
<property name="cacheMode" value="PARTITIONED" />
<property name="atomicityMode" value="ATOMIC" />
<property name="writeSync"
value="PRIMARY_SYNC" />
<property name="backups"
value="${IGNITE_CACHE_BACKUPS}" />
</bean>
</list>
</property>
Now when I deployed multiple instances of my application and stored data in Ignite cache. Its shared among all the application instances.
Even if any any instance goes down and comes up after sometime it has the latest data via Ignite cache sync.
But issue occurs when all the application instances go down. When they come up data is gone since it was not persisted. For persistence I used dataStorageConfiguration property and enabled the persistence. Here is the change I added to Ignite configuration:
<property name="dataStorageConfiguration">
<bean
class="org.apache.ignite.configuration.DataStorageConfiguration">
<!-- Enabling Apache Ignite Persistent Store. -->
<property name="defaultDataRegionConfiguration">
<bean
class="org.apache.ignite.configuration.DataRegionConfiguration">
<property name="persistenceEnabled" value="true" />
</bean>
</property>
<!-- Changing Write Ahead Log Mode. -->
<property name="storagePath" value="${IGNITE_BC_STORE_PATH}"/>
<property name="walMode" value="LOG_ONLY" />
</bean>
</property>
Now when I deploy my application and I try and start Ignite from Java code as mentioned below:
log.info("Initializing IGNITE...");
ignite = Ignition.start(getClass().getResource(CONF_FILE));
I get an exception every time stating the default instance has already started.Tried several things but didn't work. Even if I remove the CacheConfiguration from Ignite Configuration and just keep dataStorageConfiguration I still getting the same error. Error is :
Caused by: class org.apache.ignite.IgniteCheckedException: Default Ignite instance has already been started.
at org.apache.ignite.internal.IgnitionEx.start0(IgnitionEx.java:1141)
at org.apache.ignite.internal.IgnitionEx.startConfigurations(IgnitionEx.java:1076)
at org.apache.ignite.internal.IgnitionEx.start(IgnitionEx.java:962)
at org.apache.ignite.internal.IgnitionEx.start(IgnitionEx.java:881)
at org.apache.ignite.Ignition.start(Ignition.java:373)
Normally this error comes when we try and run multiple Ignite nodes under same JVM but here I am running single node per JVM. Then also getting the error.
Please do correct me if I am wrong.
Any help here will be appreciated.
Most probably, you have more than one IgniteConfiguration bean in your config file. If one configuration bean extends another one, then make sure, that the parent is abstract.
I have resolved the issue. Seems like the issue was not woth the Ignite configuration but was with Spring Framework configuration.
I was creating the bean for the Ignite class using the lazy-init=true. I switched that to the eager-init and that resolved my issue.
Not sure how exactly it solved this but it worked at least in my case.
One of our team has implemented loading properties this way (see pseudo code below) and advises this approach is right as the client application using this is free to keep the properties in any file. Contrary to the widely used propertyplaceholderconfigurer.
application-context.xml
<bean class="com.mypackage.Myclass">
<property name="xml" value="classpath:"{com.myapp.myproperty1}"> </property>
</bean>
config.properties
com.myapp.myproperty1=data.xml
edit: I should have added it is data.properties and not data.xml. We want to load a property file (this property file is given in the config.properties as a "property".
com.myapp.myproperty1=data.properties
java class
import org.springframework.core.io.Resource;
public class Myclass {
private Resource xmlField;
// setter & getter methods..
}
Is it right to use spring core.io.Resource?
Another reason is the client application wants to load a environment specific configuration. I suggested use the propertyconfigurer and use maven profiles to generate the environment specific build
Can you please advise which one suits which case? and if it differs in different scenarios, please help me point out them?
thanks
You can put the properties in any file and still use PropertyPlaceholderConfigurer. Here's an example that satisfies both your coworker's concerns and your desire for environment specific stuff:
<bean id="propertyPlaceholderConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<!-- default settings -->
<value>classpath:MyCompany.properties</value>
<!-- environment-specific settings -->
<value>classpath:MyCompany.${mycompany.env:dev}.properties</value>
<!-- keep your coworker happy -->
<value>classpath:${mycoworker}</value>
<!-- allows emergency reconfiguration via the local file system -->
<value>file:///${user.home}/MyCompany.properties</value>
</list>
</property>
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE"/>
<property name="ignoreResourceNotFound" value="true" />
<!-- should be validated separately, in case users of the library load additional properties -->
<property name="ignoreUnresolvablePlaceholders" value="false"/>
</bean>
If you pass in no -D arguments, then you'll pick up the following properties files, where properties in the later files overwrite previously determined values.
MyCompany.properties off the classpath
MyCompany.dev.properties off the classpath
$HOME/MyCompany.properties if it exists
To swap in a production config for #2, just pass -Dmycompany.env=prod to java. Similarly your coworker can pass -Dmycoworker=/some/path/config.properties if he/she wants.
I'm not sure why a PropertyPlaceholderConfigurator wouldn't have been the correct choice.
I've almost always handled environment-specific configs via a customized PPC that can either (a) get a -D parameter on startup, and/or (b) use the machine name, to decide which property file to load.
For me, this is more convenient than bundling the information in via Maven, since I can more easily test arbitrary configurations from whatever machine I'm on (using a -D property).
+1 for Dave's suggestion. You should be using PropertyPlaceholderConfigurer for loading\reading properties. Here is the example i just pulled out from my previous project if you wonder how to use this. This example is for loading multiple properties files but the concept is same. Good luck.
<bean id="projectProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="locations">
<list>
<value>classpath:config.properties</value>
</list>
</property>
</bean>
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="properties" ref="projectProperties" />
</bean>
<bean id="uniqueAssetIdRetriever" class="com.mypackage.Myclass">
<property name="xml" value="${com.myapp.myproperty1}" />
</bean>
I am new to spring. Admins of my spring based web app want to configure settings from the web interface, so users can authenticate against LDAP server with their company username and password.
Change in LDAP settings should be possible without restarting the application. This might happen during a 'migration' or whatever reason. I have a couple beans, which need to be refreshed after the admin saves new settings for the LDAP server:
<bean id="ldapServer" class="org.springframework.security.ldap.DefaultSpringSecurityContextSource">
<constructor-arg>
<list>
<value>${ldap.url1}</value>
...
</list>
</constructor-arg>
<constructor-arg value="${ldap.basedn}"</constructor-arg>
<property name="referral" value="${ldap.referral}" />
<property name="baseEnvironmentProperties">...</property>
<property name="userDn" value="${ldap.username}" />
<property name="password" value="${ldap.password}" />
</bean>
I am using Springframework 3.1.2. The problem is, there are constructor arguments, which I want to change and not affect other running jobs. I tried playing with Scoped proxy, but not to much success yet:
<bean id="ldapServer" scope="prototype" ...>
<aop:scoped-proxy/>
I was successful though to get ldapServer to reinstantiate, when using prototype scope by running this piece of code:
#Controller
public class LDAPSettingsController implements ApplicationContextAware {
public ModelAndView handleRequest(...) {
DefaultSpringSecurityContextSource ldap;
ldap = context.getParentBeanFactor().getBean("ldapServer");
System.out.println(ldap.hashCode());
return new ModelAndView(new RedirectView('login.jsp'));
}
...
}
Are scopes and proxies here the way to go, or is the another mechanism in Spring to reflect configuration changes into a running program instance?
UPDATE: Clear up the question.
UPDATE: The root problem with the AOP proxies was following root exception:
java.lang.IllegalArgumentException: Superclass has no null constructors but no arguments were given
What worked was adding proxy-target-class="false" attribute to the <aop:scoped-proxy/> tag. I created a new scope, which works better than prototype - It destroys beans on settings update. Now I have this in my beans.xml:
<bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
<property name="scopes">
<map>
<entry key="ldap">
<ref bean="ldapScope" />
</entry>
</map>
</property>
</bean>
<bean id="ldapScope" class="com.myapp.SettingsScope" />
<bean id="ldapServer" scope="ldap" ...>
<aop:scoped-proxy proxy-target-class="false"/>
<constructor-args>
<list><value>${ldap.url1}</value> .. </list>
</constructor-args>
...
</bean>
I also have a controller for LDAP settings into which I inject ldapScope and I call a method which destroys current life-cycle objects and starts a new life-cycle every time, user presses the apply button.
PS: Not sure if I handle the life-cycle "re-start" in the right way - people my way to look for auto-start beans and start them after such event happens (i.e.: Setting -> Apply)
One of our team has implemented loading properties this way (see pseudo code below) and advises this approach is right as the client application using this is free to keep the properties in any file. Contrary to the widely used propertyplaceholderconfigurer.
application-context.xml
<bean class="com.mypackage.Myclass">
<property name="xml" value="classpath:"{com.myapp.myproperty1}"> </property>
</bean>
config.properties
com.myapp.myproperty1=data.xml
edit: I should have added it is data.properties and not data.xml. We want to load a property file (this property file is given in the config.properties as a "property".
com.myapp.myproperty1=data.properties
java class
import org.springframework.core.io.Resource;
public class Myclass {
private Resource xmlField;
// setter & getter methods..
}
Is it right to use spring core.io.Resource?
Another reason is the client application wants to load a environment specific configuration. I suggested use the propertyconfigurer and use maven profiles to generate the environment specific build
Can you please advise which one suits which case? and if it differs in different scenarios, please help me point out them?
thanks
You can put the properties in any file and still use PropertyPlaceholderConfigurer. Here's an example that satisfies both your coworker's concerns and your desire for environment specific stuff:
<bean id="propertyPlaceholderConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<!-- default settings -->
<value>classpath:MyCompany.properties</value>
<!-- environment-specific settings -->
<value>classpath:MyCompany.${mycompany.env:dev}.properties</value>
<!-- keep your coworker happy -->
<value>classpath:${mycoworker}</value>
<!-- allows emergency reconfiguration via the local file system -->
<value>file:///${user.home}/MyCompany.properties</value>
</list>
</property>
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE"/>
<property name="ignoreResourceNotFound" value="true" />
<!-- should be validated separately, in case users of the library load additional properties -->
<property name="ignoreUnresolvablePlaceholders" value="false"/>
</bean>
If you pass in no -D arguments, then you'll pick up the following properties files, where properties in the later files overwrite previously determined values.
MyCompany.properties off the classpath
MyCompany.dev.properties off the classpath
$HOME/MyCompany.properties if it exists
To swap in a production config for #2, just pass -Dmycompany.env=prod to java. Similarly your coworker can pass -Dmycoworker=/some/path/config.properties if he/she wants.
I'm not sure why a PropertyPlaceholderConfigurator wouldn't have been the correct choice.
I've almost always handled environment-specific configs via a customized PPC that can either (a) get a -D parameter on startup, and/or (b) use the machine name, to decide which property file to load.
For me, this is more convenient than bundling the information in via Maven, since I can more easily test arbitrary configurations from whatever machine I'm on (using a -D property).
+1 for Dave's suggestion. You should be using PropertyPlaceholderConfigurer for loading\reading properties. Here is the example i just pulled out from my previous project if you wonder how to use this. This example is for loading multiple properties files but the concept is same. Good luck.
<bean id="projectProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="locations">
<list>
<value>classpath:config.properties</value>
</list>
</property>
</bean>
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="properties" ref="projectProperties" />
</bean>
<bean id="uniqueAssetIdRetriever" class="com.mypackage.Myclass">
<property name="xml" value="${com.myapp.myproperty1}" />
</bean>
I develop some Java EE/Spring web-app. I use JPA 2.0 - Hibernate. For integration tests I need to use different database. Those tests require Jetty to run application, but I managed to override web.xml for such run, there I can modify my Spring context files, it's ok.
But I need each time a clean database (and load some data into it).
As my database name and address are configured in sprig context I just switched them as I described above - but how can I change some of my persistence.xml properies for this tests only to have database drop and recreated?
I tried to make another persistence.xml in /src/test/resources/META-INF (and checked that test-classes are first in classpath) but it is not loaded and only the 'master' version is used (from /src/main/resources/META-INF). Any help?
With spring you usually define your data source as a spring bean. The database url and credentials are usually included form an external file, for example application.properties.
If you put a new applicaiton.properties in src/test/resources it will work. See also here.
You can define org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager :
<bean id="pum" class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager">
<property name="persistenceXmlLocations">
<list>
<value>/path/to/my/test-persistence.xml</value>
</list>
</property>
<property name="dataSources">
<map>
<entry key="dataSource" value-ref="dataSource"/>
</map>
</property>
<!-- if no datasource is specified, use this one -->
<property name="defaultDataSource" ref="dataSource"/>
</bean>
Then, link it to your entityManagerFactory :
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
...
...
<property name="persistenceUnitManager" ref="pum"/>
</bean>
I used this to make my own persistence.xml linked to a HSQL in-memory db, preloaded with DBUnit (using hibernate.hbm2ddl.auto=create-drop).
It Works perfectly.