I am new to Spring-AOP and trying to use it in my project. I have created a class implementing MethodBeforeAdvice :
public class LogBeforeCallAdvice implements MethodBeforeAdvice{
/* (non-Javadoc)
* #see org.springframework.aop.MethodBeforeAdvice#before(java.lang.reflect.Method, java.lang.Object[], java.lang.Object)
*/
#Override
public void before(Method arg0, Object[] arg1, Object arg2)
throws Throwable {
System.out.println("**CALLING METHOD - " + arg0.getName() + " IN BEFORE CALLING ADVICE**");
}
}
These are the entries my application-context.xml file:
<bean id="proxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target" ref="logMethods"></property>
<property name="interceptorNames">
<list>
<value>beforeCall</value>
</list>
</property>
</bean>
<bean id = "logMethods" class = "com.MyPackage.LogMethods" lazy-init = "true" init-method="init">
<property name = "someProperty" ref = "someBeanReference"/>
</bean>
And in my main method, I am getting the proxy like this:
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
LogMethods logMethods = (LogMethods)context.getBean("proxy");
After executing the above code, I am not getting the log written in before() method of Before Calling Advice. But I am able to see the sys outs mentioned in the LogMethods class and its property reference beans also.
I want to print the before advice logs for all the methods in LogMethods and its property beans' methods (without using aspectj annotations).
I am not getting any error also. What am I doing wrong? Can someone please help?
Thanks in Advance!!
Related
In the below code I'm getting a NullPointer at line private File ratesFile = new File(ratesFilePath); in my myClass.java.
As far as I can see my properties file is fine, I'm importing it fine into my .xml configuration and passing the property to my class OK. My getters and setters seem OK to me too. Any pointers on why my properties aren't being passed to my class?
Spring Batch 2.1.8
myClass.properties:
rates_file_path=/opt/rates
rates_file=rates.txt
myClass.xml:
<bean id="myClassProps" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:conf/myClass.properties</value>
</list>
</property>
<property name="ignoreUnresolvablePlaceholders" value="true" />
</bean>
<bean id="myClass" class="com.stuff.blah.myClass">
<property name="ratesFilePath" value="${rates_file_path}/${rates_file}" />
</bean>
myClass.java
public class myClass implements Tasklet, InitializingBean {
private String ratesFilePath;
private File ratesFile = new File(ratesFilePath);
public String getRatesFilePath() {
return ratesFilePath;
}
public void setRatesFilePath(String ratesFilePath) {
this.ratesFilePath = ratesFilePath;
}
}
In your myClass,
private File ratesFile = new File(ratesFilePath);
is an error raising code.
Both ratesFilePath and ratesFile is initialized when the constructor is called.
Because ratesFilePath does not have any values to initialize with, it is set to null.
And when ratesFile is trying to be initialized, it will use the ratesFilePath, which is null and will raise a NullPointerException.
To fix this, first set your ratesFile to null;
private File ratesFile = null;
And set ratesFile on the setter method of ratesfilePath after making sure that path is not null.
public void setRatesFilePath(String ratesFilePath) {
this.ratesFilePath = ratesFilePath;
if(ratesFilePath == null) ratesFile = null;
else ratesFile = new File(ratesFilePath);
}
I am facing this exception while creating bean of datasource from DBCP2. Exception is
Caused by: org.springframework.beans.NotWritablePropertyException: Invalid property 'connectionInitSqls' of bean class [org.apache.commons.dbcp2.BasicDataSource]: Bean property 'connectionInitSqls' is not writable or has an invalid setter method. Does the parameter type of the setter match the return type of the getter?
here is my bean configuration
<bean id="fileStore_dataSource" class="org.apache.commons.dbcp2.BasicDataSource"
destroy-method="close" lazy-init="true">
<!-- Just that property which causes problem -->
<property name="connectionInitSqls">
<list>
<value>#{filestore.jdbc.connectionInitSql}</value>
</list>
</property>
</bean>
Here is the setter and getter code for connectionInitSqls in BasicDataSource class. version of DBCP2 is 2.1.1
private volatile List<String> connectionInitSqls;
public List<String> getConnectionInitSqls() {
final List<String> result = connectionInitSqls;
if (result == null) {
return Collections.emptyList();
}
return result;
}
public void setConnectionInitSqls(final Collection<String> connectionInitSqls) {
if (connectionInitSqls != null && connectionInitSqls.size() > 0) {
ArrayList<String> newVal = null;
for (final String s : connectionInitSqls) {
if (s != null && s.trim().length() > 0) {
if (newVal == null) {
newVal = new ArrayList<>();
}
newVal.add(s);
}
}
this.connectionInitSqls = newVal;
} else {
this.connectionInitSqls = null;
}
}
You can see that argument in setter is Collection which is Super type of List. But I dont know why spring could not instantiate the bean. Is this Spring problem or Bug in DBCP2 code. Can we give parent type of property in setter argument?
How can I resolve this problem? Any Help would be appreciated.
Spring will use reflection to find the setter property. So it will find the setter using setConnectionInitSqls and argument list because of the property type(which it will find from getter method getConnectionInitSqls) and it will not find therefore the exception.
Exception message is self explanatory now. Note that the property may not exist at all. Spring just works with getters and setters. It finds the appropriate setter method using the getter method's( which is easy to find just prefix with get and no arg method) return value type.
Bean property 'connectionInitSqls' is not writable or has an invalid setter method. Does the parameter type of the setter match the return type of the getter?`
you can try using MethodInvokingFactoryBean.
<bean id="fileStore_dataSource" class="org.apache.commons.dbcp2.BasicDataSource"
destroy-method="close" lazy-init="true">
</bean>
<bean id="customInjector"
class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetObject" ref="fileStore_dataSource" />
<property name="targetMethod">
<value>setConnectionInitSqls</value>
</property>
<property name="arguments">
<list>
<value>#{filestore.jdbc.connectionInitSql}</value>
</list>
</property>
</bean>
Alternative way:
I would prefer this as it is SAFER. Reason being all properties are set during the instantiation phase itself. And then wiring between the beans happen. In the previous case it may be error prone because setting connectionInitSqls happens at a different time and chances are that connections might have already been created(without looking into the internals of the implementation of BasicDataSource).
public class CustomBasicDataSource extends BasicDataSource{
public void setConnectionInitSqls(List<String> connectionInitSqls) {
super.setConnectionInitSqls(connectionInitSqls);
}
}
replace with this class in xml
<bean id="fileStore_dataSource"
class="org.company.somepackage.CustomBasicDataSource" destroy-method="close" lazy-init="true">
...<!-- rest remain same-->
</bean>
Try ${ instead of #{
<property name="connectionInitSqls">
<list>
<value>${filestore.jdbc.connectionInitSql}</value>
</list>
</property>
I am introducing Apache Ignite in our application as cache system as well as for computation. I have configured spring application using following configuration class.
#Configuration
#EnableCaching
public class IgniteConfig {
#Value("${ignite.config.path}")
private String ignitePath;
#Bean(name="cacheManager")
public SpringCacheManager cacheManager(){
SpringCacheManager springCacheManager = new SpringCacheManager();
springCacheManager.setConfigurationPath(ignitePath);
return springCacheManager;
}
}
Using it like
#Override
#Cacheable("cache1")
public List<Channel> getAllChannels(){
List<Channel> list = new ArrayList<Channel>();
Channel c1 = new Channel("1",1);
Channel c2 = new Channel("2",2);
Channel c3 = new Channel("3",3);
Channel c4 = new Channel("4",4);
list.add(c1);
list.add(c2);
list.add(c3);
list.add(c4);
return list;
}
Now I want to add write-through and read-through feature. I could not find any documentation to connect ignite to mongo.
The idea is not to talk to db directly but through ignite using write behind feature.
EDIT-----------------------
As suggested I implemented
public class ChannelCacheStore extends CacheStoreAdapter<Long, Channel> implements Serializable {
#Override
public Channel load(Long key) throws CacheLoaderException {
return getChannelDao().findOne(Channel.mongoChannelCode, key);
}
#Override
public void write(Cache.Entry<? extends Long, ? extends Channel> entry) throws CacheWriterException {
getChannelDao().save(entry.getValue());
}
#Override
public void delete(Object key) throws CacheWriterException {
throw new UnsupportedOperationException("Delete not supported");
}
private ChannelDao getChannelDao(){
return SpringContextUtil.getApplicationContext().getBean(ChannelDao.class);
}
}
And added this CacheStore into cache configuration like below :
<property name="cacheConfiguration">
<list>
<bean class="org.apache.ignite.configuration.CacheConfiguration">
<property name="name" value="channelCache"/>
<property name="cacheMode" value="PARTITIONED"/>
<property name="atomicityMode" value="ATOMIC"/>
<property name="backups" value="1"/>
<property name="readThrough" value="true"/>
<!-- Sets flag indicating whether write to database is enabled. -->
<property name="writeThrough" value="true"/>
<!-- Enable database batching. -->
<!-- Sets flag indicating whether write-behind is enabled. -->
<property name="writeBehindEnabled" value="true"/>
<property name="cacheStoreFactory">
<bean class="javax.cache.configuration.FactoryBuilder$SingletonFactory">
<constructor-arg>
<bean class="in.per.amt.ignite.cache.ChannelCacheStore"></bean>
</constructor-arg>
</bean>
</property>
</bean>
</list>
</property>
But now getting class cast exception
java.lang.ClassCastException: org.springframework.cache.interceptor.SimpleKey cannot be cast to java.lang.Long
at in.per.amt.ignite.cache.ChannelCacheStore.load(ChannelCacheStore.java:19)
You can have any kind of backing database by implementing CacheStore interface:
https://apacheignite.readme.io/docs/persistent-store
Have you tried setting your key generator?
#CacheConfig(cacheNames = "cache1",keyGenerator = "simpleKeyGenerator")
https://github.com/spring-projects/spring-boot/issues/3625
So in the below line of code from what you have shared,
#Cacheable("cache1")
public List<Channel> getAllChannels(){
the #Cacheable annotation is being used on a method which is not accepting any parameters. Spring cache uses the parameters (if in basic data type) as a key for the cache (response obj as the value). I believe this makes the caching ineffective.
In a swing GUI application, where MVC pattern is applied, how can we use Spring to wire the model view and controller? i.e. what beans (model, view or controller) should be injected using spring and what should be created from the application? I have applied the MVC pattern described here when developing the application. Thanks in advance.
If you have some leeway in the technologies you're using, I'd say you switch to (Griffon)[http://griffon.codehaus.org/]. It uses spring in the background and you also get the power of groovy and Swing UI builders. Best part is, you can still reuse the java code you've written so far. Also, you don't need to worry about DI and stuff. Griffon handles it for you.
On one of my projects, I successfully used Spring Rich Client.
If you are starting from scratch, I suggest that you take a look at it, it worth it. And it also provides some services out of the box (like authentication box and so).
I suggest that you can use "spring mvc".
Jsp(View) controller how to show the data;
Controller controll the return the view required data;
Server controller the system logic;
Model is the database model.
It would come to noone's surprise that I'd recommend you to have a look at Griffon. The MVC pattern is deeply engrained in Griffon's DNA, have a look at this sample app as shown in the Griffon Guide
http://griffon.codehaus.org/guide/0.9.5-rc2/guide/2.%20Getting%20Started.html#2.3%20A%20Groovy%20Console%20Example
Griffon provides basic DI capabilities for each MVC member, you only need to define properties following a naming convention. Services, where you would usually put most of the application's logic, are also automatically injected into controllers, as the guide explains in
http://griffon.codehaus.org/guide/0.9.5-rc2/guide/8.%20Controllers%20and%20Services.html#8.2%20Services
However you can make use of Spring DI too via the Spring plugin
http://artifacts.griffon-framework.org/plugin/spring
Spring beans may be defined using the standard XML approach, annotations or the Groovy Spring DSL.
I defined all the beans in spring and used a factory method to create the views when required. Controller is injected to the view and the model and view are added to the controller via spring.
Following are the code samples from a simple example that I came up with, in order to find a solution: (sorry for the long post!)
the application context file:
<bean id="firstModel" class="com.model.FirstModel"></bean>
<bean id="secondModel" class="com.model.SecondModel"></bean>
<bean id="firstController" class="com.controller.FirstController" />
<bean
class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetObject">
<ref local="firstController" />
</property>
<property name="targetMethod">
<value>addModel</value>
</property>
<property name="arguments">
<list>
<value>FIRST</value>
<ref local="firstModel" />
</list>
</property>
</bean>
<bean id="secondController" class="com.controller.SecondController" />
<bean
class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetObject">
<ref local="secondController" />
</property>
<property name="targetMethod">
<value>addModel</value>
</property>
<property name="arguments">
<list>
<value>SECOND</value>
<ref local="secondModel" />
</list>
</property>
</bean>
<bean
class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetObject">
<ref local="secondController" />
</property>
<property name="targetMethod">
<value>addModel</value>
</property>
<property name="arguments">
<list>
<value>FIRST</value>
<ref local="firstModel" />
</list>
</property>
</bean>
<bean id="firstForm" class="com.view.FirstForm">
<property name="controller">
<ref bean="firstController" />
</property>
</bean>
<bean id="secondForm" class="com.view.SecondForm">
<property name="controller">
<ref bean="secondController" />
</property>
</bean>
following is the abstract controller class:
public class AbstractController implements PropertyChangeListener {
Map<Type, BaseView> registeredViews;
Map<Type, AbstractModel> registeredModels;
public AbstractController() {
registeredViews = new HashMap<Type, BaseView>();
registeredModels = new HashMap<Type, AbstractModel>();
}
public void addModel(Type type, AbstractModel model) {
registeredModels.put(type, model);
model.addPropertyChangeListener(this);
}
public void removeModel(AbstractModel model) {
registeredModels.remove(model);
model.removePropertyChangeListener(this);
}
public void addView(BaseView view, Type type) {
registeredViews.put(type, view);
}
public void removeView(javax.swing.JFrame view) {
registeredViews.remove(view);
}
public void propertyChange(PropertyChangeEvent evt) {
for (BaseView view : registeredViews.values()) {
view.modelPropertyChange(evt);
}
}
protected void setModelProperty(String propertyName, Object newValue) {
for (AbstractModel model : registeredModels.values()) {
Statement statment = new Statement(model, "set" + propertyName, new Object[] { newValue });
try {
statment.execute();
} catch (NoSuchMethodException e) {
continue;
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
following is the abstract model class:
public class AbstractModel {
protected PropertyChangeSupport propertyChangeSupport;
public AbstractModel() {
propertyChangeSupport = new PropertyChangeSupport(this);
}
public void addPropertyChangeListener(PropertyChangeListener listener) {
propertyChangeSupport.addPropertyChangeListener(listener);
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
propertyChangeSupport.removePropertyChangeListener(listener);
}
protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) {
propertyChangeSupport.firePropertyChange(propertyName, oldValue, newValue);
}
}
Following is the code sample of the view interface:
public interface BaseView {
void modelPropertyChange(PropertyChangeEvent evt);
public abstract void showForm();
}
following is the code sample of the factory class:
public class FormFactory {
private ApplicationContext context;
private static FormFactory viewFactory;
private FormFactory() {
if (context == null) {
context = new ClassPathXmlApplicationContext("ApplicationContext.xml");
}
}
public static synchronized FormFactory getInstance() {
if (viewFactory == null) {
viewFactory = new FormFactory();
}
return viewFactory;
}
public BaseView createForm(Type type) {
BaseView form = null;
switch (type) {
case FIRST:
form = (BaseView) context.getBean("firstForm");
break;
case SECOND:
form = (BaseView) context.getBean("secondForm");
break;
default:
break;
}
return form;
}
}
We're in the process of updating our apps from Spring 2.5 to 3.0 and we've hit a problem with the new SpEL evaluation of bean properties.
We've been using an in-house templating syntax in one module which unfortunately uses the same "#{xyz}" markup as SpEL. We have a few beans which take string's containing these expressions as properties but spring assumes they are SpEL expressions and throws a SpelEvaluationException when it tries to instantiate the bean.
e.g.
<bean id="templatingEngine" class="com.foo.TemplatingEngine">
<property name="barTemplate" value="user=#{uid}&country=#{cty}"/>
</bean>
Is it possible to disable SpEL evaluation, ideally per-bean, but alternatively for the whole application context?
Alternatively is there a way to escape the values?
Thanks,
Stephen
Completely disable SpEL evaluation by calling the bean factory setBeanExpressionResolver method passing in null. You can define a BeanFactoryPostProcessor to do this.
public class DisableSpel implements BeanFactoryPostProcessor {
public void postProcessBeanFactory(
ConfigurableListableBeanFactory beanFactory)
throws BeansException
{
beanFactory.setBeanExpressionResolver(null);
}
}
Then define this bean in the application context.
<bean class="com.example.spel.DisableSpel"/>
Well what you could do is re-define the expression language delimiters.
I would say the way to do this is through a special bean that implements BeanFactoryPostProcessor (thanks to inspiration by Jim Huang):
public class ExpressionTokensRedefiner implements BeanFactoryPostProcessor{
private BeanExpressionResolver beanExpressionResolver;
public void setBeanExpressionResolver(
final BeanExpressionResolver beanExpressionResolver){
this.beanExpressionResolver = beanExpressionResolver;
}
#Override
public void postProcessBeanFactory(
final ConfigurableListableBeanFactory beanFactory)
throws BeansException{
beanFactory.setBeanExpressionResolver(createResolver());
}
private String expressionPrefix = "${";
private String expressionSuffix = "}";
public void setExpressionPrefix(final String expressionPrefix){
this.expressionPrefix = expressionPrefix;
}
public void setExpressionSuffix(final String expressionSuffix){
this.expressionSuffix = expressionSuffix;
}
private BeanExpressionResolver createResolver(){
if(beanExpressionResolver == null){
final StandardBeanExpressionResolver resolver =
new StandardBeanExpressionResolver();
resolver.setExpressionPrefix(expressionPrefix);
resolver.setExpressionSuffix(expressionSuffix);
return resolver;
} else{
return beanExpressionResolver;
}
}
}
Define it as a bean like this:
<bean class="foo.bar.ExpressionTokensRedefiner">
<property name="expressionPrefix" value="[[" />
<property name="expressionSuffix" value="]]" />
</bean>
or like this:
<!-- this will use the default tokens ${ and } -->
<bean class="foo.bar.ExpressionTokensRedefiner" />
or use a custom resolver:
<bean class="foo.bar.ExpressionTokensRedefiner">
<property name="beanExpressionResolver">
<bean class="foo.bar.CustomExpressionResolver" />
</property>
</bean>
Now you can leave your definitions untouched and if you want to use SpEL, use the new delimiters.
EDIT: now I did test it and it actually works.
<bean class="foo.bar.ExpressionTokensRedefiner">
<property name="expressionPrefix" value="[[" />
<property name="expressionSuffix" value="]]" />
</bean>
<bean class="foo.bar.FooFritz">
<property name="fizz" value="[[ systemProperties['user.home'] ]]"></property>
<property name="fozz" value="[[ systemProperties['java.io.tmpdir'] ]]"></property>
<!-- this is what it would normally choke on -->
<property name="fazz" value="#{ boom() }"></property>
</bean>
Test code:
final ConfigurableApplicationContext context =
new ClassPathXmlApplicationContext("classpath:foo/bar/ctx.xml");
context.refresh();
final FooFritz fooFritz = context.getBean(FooFritz.class);
System.out.println(fooFritz.getFizz());
System.out.println(fooFritz.getFozz());
System.out.println(fooFritz.getFazz());
Output:
/home/seanizer
/tmp
#{ boom() }
I am not a dab, but this mighbe of help.
https://issues.apache.org/jira/browse/CAMEL-2599