Using Spring and Java;
I have a pointcut which works OK. Now I want to remove the pointcut and AOP from the spring and just trigger the event with an event from inside the java code but I want "myAdvice" bean still called via Spring and its properties set.
I want to get ridoff all advice things even in java code, no more advice or any trace of AOP, I already have a nice event system working. I just want to instantiate my bean via Spring.
When I remove the second code block (one starting with "aop:config") then I noticed the bean "myAdvice" is not called and instantiated anymore. How can i stil call it set its properties without referencing it from the "aop:aspect" ?
in my application context ;
<bean id="myAdvice" class="com.myclass">
<property name="name1" ref="ref1" />
<property name="name2" ref="ref2" />
</bean>
<aop:config proxy-target-class="true">
<aop:aspect id="myAspect" ref="myAdvice">
<aop:pointcut id="myPointcut" expression="execution(* com.myexcmethod" />
<aop:around pointcut-ref="myPointcut" method="invoke" />
</aop:aspect>
</aop:config>
Your configuration looks fine . Your bean should be instantiated as a singleton bean when the ApplicationContext loads up . Maybe you would want to check if you have a default-lazy-init setting which prevents eager loading of the beans.
If you want to be able to get at the bean itself, you can pass it into this function:
public static Object unwrapProxy(Object proxiedBean) throws Exception {
while(proxiedBean instanceof Advised) {
proxiedBean = ((Advised) proxiedBean).getTargetSource().getTarget();
}
return proxiedBean;
}
Note that you need to have the loop in order to ensure that you unwrap all the AOP advice.
Related
I am working on a Spring-MVC application in which I want to use #Async at-least for the methods which are fire-and-forget. When I try to use #Async and I have used #EnableAsync annotation too for class, the actions inside the method are not performed. When I add task executor in servlet-context.xml, then I get an error bean is getting currently created. I am new to Async, can anyone tell me how I can use it.
I am not using Eager loading btw.
Error log :
Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'groupNotesService': Bean with name 'groupNotesService' has been injected into other beans [mattachService] in its raw version as part of a circular reference, but has eventually been wrapped. This means that said other beans do not use the final version of the bean. This is often the result of over-eager type matching - consider using 'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.
Code :
GroupNotesServiceImpl :
#Service
#Transactional
#EnableAsync
public class GroupNotesServiceImpl implements GroupNotesService {
#Override
#Async
public void editGroupNote(GroupNotes mnotes, int msectionId) {
//Code to be executed, which is not getting executed
}
}
Servlet-context.xml :
<task:annotation-driven executor="executor" />
<task:executor id="executor" pool-size="20"/>
<mvc:annotation-driven />
<mvc:default-servlet-handler />
<resources mapping="/resources/" location="/resources/" />
If I remove any of the mvc lines above, I get a servlet.init() threw load exception error.
Also, Is it possible to use Async where I am returning int? I checked out the Future tag, but I don't know what modifications are required.
Here is the method that returns int.
#Override
public int saveGroupNoteAndReturnId(GroupNotes mnotes, int msectionid) {
// saves note and returns its id.
}
MattachService bean :
<beans:bean id="mattachDAO"
class="com.journaldev.spring.dao.GroupAttachmentsDAOImpl">
<beans:property name="sessionFactory"
ref="hibernate4AnnotatedSessionFactory" />
</beans:bean>
<beans:bean id="mattachService"
class="com.journaldev.spring.service.GroupAttachmentsServiceImpl">
<beans:property name="groupAttachmentsDAO" ref="mattachDAO" />
</beans:bean>
Edit
I checked out that there is a problem to run #Transactional and #Async both in one class. Jira SPR-7147. The workaround suggested there was to introduce a normal facade, and I really don't know what that means.
#EnableAsync should be in configuration, not the service itself. Since you seem to use xml configuration, check this https://stackoverflow.com/a/20127051/562721. It recommends to declare org.springframework.scheduling.annotation.AsyncAnnotationBeanPostProcessor to take care of #Async annotations
I'm using Spring to auto-wire beans for configuration. Some parameters come from a properties file:
<bean id="mydb" class="myproject.mydb" autowire="constructor">
<constructor-arg name="host" value="${mydb.host}" />
<constructor-arg name="db" value="${mydb.db}" />
<constructor-arg name="user" value="${mydb.user}" />
<constructor-arg name="password" value="${mydb.password}" />
</bean>
Is there a way to auto-wire these properties based on the bean id so that I would just have to write the following?
<bean id="mydb" class="myproject.mydb" autowire="constructor" />
Edit: The point of this is to not have to explicity specify the non-bean constructor arguments. I want Spring to automatically check the properties for beanId.constructorArgName
To achieve exactly what you want, I think you'd need to implement a BeanPostProcessor and provide your custom wiring logic (where you read the .properties file) in postProcessBeforeInitialization. The bean name is available to that method, but there are multiple problems with this. The first is that argument names are not necessarily available at runtime, so indexes might be a better option. The second is that you already have an instantiated bean (so a default constructor would need to exists), and you'd instantiate another, throwing the first one away which is wasteful. To use the instance that already exists, you'd need to wire it by properties, not constructor, which violates encapsulation and is not what you asked. The third is that it's not at all obvious what is going on. So, all in all, you are probably better off avoiding this completely.
In your class myproject.mydb
#Autowired
public mydb(#Value("mydb.host") String host, ...){...}
As per your question, the only way Property values can be injected to the constructor is through the XMLfile as done above or using the #Value("${some.property}") annotation.
Refer this for more info
Use #Value("property key") annotation. look at eg.: http://java.dzone.com/articles/autowiring-property-values
I have the following construct Spring XML (Spring 3.1):
<bean id="taskRunner" abstract="true" init-method="startThreads"
class="my.class.TaskRunner" />
...
<bean id="taskRunnerA" parent="taskRunner">
<constructor-arg name="foo">...</constructor-arg>
<property name="bar">...</property>
</bean>
And I am trying to separate out the init method into a higher level abstract bean:
<bean id="taskRunnerLauncher" abstract="true" init-method="startThreads" />
<bean id="taskRunner" abstract="true" depends-on="taskRunnerLauncher"
class="my.class.TaskRunner" />
...
<bean id="taskRunnerA" parent="taskRunner">
<constructor-arg name="foo">...</constructor-arg>
<property name="bar">...</property>
</bean>
Somehow this does not work, i.e. startThreads() is never invoked in the second case. Does anybody know why? Does Spring support nested abstract beans?
My idea for doing this is so I can override "taskRunnerLauncher" in unit tests and set it to "mock" or "java.lang.Object" and suppress startThreads() call (which starts new thread and making it a pain to test).
Does anybody know why?
The taskRunnerLauncher bean is set to be abstract. This means it will only act as a template for other beans. Spring will not actually create a bean for it. Therefore there won't be any invocation of startThreads because there is nothing to invoke it on.
Found the problem. I mistakenly used depends-on instead of parent attribute on taskRunner bean.
I have a situation very similar to "Inject a file resource into Spring bean"
I have a controller that uses some .jasper compiled files and I am declaring them as such
//...
#Controller
public class InvoicingController {
private Resource quoteTemplate;
...//
And in my context configuration file
<bean id="invoicingController" class="x.x.InvoicingController">
<property name="quoteTemplate" value="/WEB-INF/jasper/Quote.jasper" />
...
I set a breakpoint on the setQuoteTemplate() function and it is being called and the Resource object is being set properly when I initialize the container. However when I actually hit the controller quoteTemplate is null.
I am under the understanding that Controllers are singletons and unless there is a gap in my understanding I am not sure why the values that are set during the container's initialization become null when I hit a url that the controller handles.
EDIT:
Thanks #Sotirios Delimanolis
I ended up declaring beans as such:
<bean id="quoteFile" class="java.io.File">
<constructor-arg value="resources/jasper/Quote.jasper" />
</bean>
<bean id="quoteTemplate" class="org.springframework.core.io.FileSystemResource">
<constructor-arg ref="quoteFile" />
</bean>
And then #Autowireing the dependencies as such
#Autowired #Qualifier("quoteTemplate") private Resource quoteTemplate;
#Qualifier is used because I have multiple Resource implementation classes declared as beans and this makes sure the correct one gets used.
You can't be using both the #Controller annotation and a <bean> declaration, unless you don't have a component-scan. You will end up with two bean definitions where the last one will overwrite the first one.
In this case, it seems like the component-scanned bean definition comes second and overwrites the bean you created with <bean>.
Choose which bean declaration method you want to use.
<bean id="data.emf"
class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean" >
<property name="persistenceUnitName" value="transactions-optional" />
</bean>
from what i know by default all bean are singleton (according to document) but i somehow still getting duplicated creating of entitymanagerfactory. is there any parameter i can set for bean above in spring 3.0 to force singleton? the problem only appear in gae production, on hosted mode, no problem
You can force a bean to be a singleton like this:
<bean scope="singleton" ... >
</bean>
You generally don't need to do this, however, since singleton is the default scope, and there's no way to change the default.
The Spring DEBUG-level logs will generate entries every time a bean is instantiated, so have a look through there to see when and where your bean is being processed.
Maybe the problem doesn't come form the scope. Are you sure you haven't defined another bean in anther place of the program (for example with an annotation) or in another context file? Comment that bean definition and try if it can find a instance of it without declaring it here.