I want to weave the following custom aspect using Spring 4.X.
(I use Scala, but is exactly the same as in Java).
I'm based on this existing code, acting as sample from the Vaughn Vernon's IDDD book:
#Aspect
#Component
class EventProcessor #Autowired()(private val eventRepository: EventRepository) {
#Before("execution(* com.mymainpackage.*.application.commands.*.*(..)")
def listen() {
DomainEventPublisher.instance().subscribe(new DomainEventSubscriber[Event] {
def handleEvent(domainEvent: Event) {
eventRepository.save(domainEvent)
}
def subscribedToEventType = {
classOf[Event]
}
})
}
}
My application-context.xml:
.........
<context:load-time-weaver/>
<context:annotation-config/>
<context:component-scan
base-package="........" />
The typical classes/services I want to weave with aspect contains this kind of method:
def handle(event:Event)
and its corresponding interfaces and implementation may be found in this explicit package for instance:
com.mymainpackage.myboundedcontext1.application.commands.anestedpackage
I well checked that the base-package contains the class's package of the custom aspect.
Is there a necessity to declare a #PointCut additionally to #Before?
The sample doesn't do it...
Of course, I executed my code with the following jar allowing "weaving" at Runtime so:
-javaagent:/cache/org.springframework/spring-instrument/jars/spring-instrument-4.0.0.RELEASE.jar
Did I miss something "obvious"?
Any idea how to fix this?
As #M.Deinum mentionned, I forgot a last ) regarding the matcher of my pointcut.
Furthermore I forgot to specify the aspectj-autoproxy, in order to take into account my aspect class.
With that, would no need to declare an aop.xml if I expect all aspects classes to have their created respective proxies.
So I specified it by adding spring-aop xsd to my application-context.xml like this ("------->" to make a legend, although not valid :) in this xml):
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:neo4j="http://www.springframework.org/schema/data/neo4j"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop" ------->That is added
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd http://www.springframework.org/schema/data/neo4j
http://www.springframework.org/schema/data/neo4j/spring-neo4j-2.1.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd" ---------> That is added >
.....
<aop:aspectj-autoproxy/>
.....
Now the whole works.
Related
So I have been using the 3.2.0.RELEASE Spring XML configurations for most of my beans but now I am faced with a unique situation where the Getters and Setters can't be used (bad legacy code - can't get around it).
As such, I want to use Spring #Configuration class and the XML to workaround this problem.
However, I am getting "Class Not Found" exception when it tries to read my #Configuration Class.
Caused by: java.lang.ClassNotFoundException: v1.inventory.item.myJavaConfig
My XML file which is failing looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config/>
<bean class="v1.inventory.item.myJavaConfig"/>
</beans>
My #Configuration class looks like this:
package v1.inventory.item;
#Configuration
#ImportResource("classpath:v1/inventory/item/baseItemConfigs.xml")
public class myJavaConfig {
#Autowired
#Qualifier("parentItem")
Item baseItem;
#Bean
public Item realItem(){
Item modifiedBean = baseItem;
modifiedBean.setManufacturer("Fake Setter for Manufacturer");
modifiedBean.setDesigner("Fake Setter for Designer");
return modifiedBean;
}
}
I need this to be read by the ApplicationContext so I need to make sure these beans can be found. Is this a bug with Spring 3.2.0.RELEASE? Or my code?
For the record, I am pulling in the #Configuration last (parentItem is scanned first in XML).
I figured out the issue here.
It seems that maven/spring (not sure which) wasn't looking in my "resource" directory for the file. Only my "java" directory. When I moved my file into the "java" directory, Spring found the file just fine.
The tests which were passing in JUnit now pass using the Maven compiler (which was throwing the above error during the test phase)
I created a CustomWebSecurityExpressionHandler to check users on a db table by searching for a function id. I want to change my roles on every function with only some db update and a restart of the context, without recompile and editing a mountain of XML.
I want to use SpringSecurityExpression inside a webflow! Like I can do in any other parts of Spring...
<?xml version="1.0" encoding="UTF-8"?>
<flow xmlns="http://www.springframework.org/schema/webflow"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/webflow
http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd">
<secured attributes="isFUUU('key')" />
<view-state id="main" view="dashboard/main.html" >
</view-state>
</flow>
How can I make isFUU("key") working? it's a custom CustomAccessDecisionManager needed?
I found a workaround
I had to debug 20 classes of spring security and webflow to discover that in SecurityFlowExecutionListener even if you set spring security to work with expression, the listener will be role-based only.
I found that for parsing expression a would need a specific type config attribute, WebExpressionConfigAttribute to be precise.
But it's not a public class!!! https://jira.spring.io/browse/SEC-1727 .
So as suggested in this OLD Jira, I needed to creat my CustomSecurityFlowExecutionListener in the same package (org.springframework.security.web.access.expression)
Here the example
CustomSecurityFlowExecutionListener:
package org.springframework.security.web.access.expression; //First part of the trick!
import foo.bar.example.services.security.CustomAccessDecisionManager;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.springframework.expression.ExpressionParser;
import org.springframework.security.access.AccessDecisionManager;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.webflow.security.SecurityFlowExecutionListener;
import org.springframework.webflow.security.SecurityRule;
/**
* Force Spring WebFlow Security listener to use expression!
*
* #author roberto.gabrieli
*/
public class CustomSecurityFlowExecutionListener<T > extends SecurityFlowExecutionListener
{
/**
* Convert SecurityRule into a form understood by Spring Security Force the usage of WebExpressionConfigAttribute!
*
* #param rule
* the rule to convert
* #return list of ConfigAttributes for Spring Security
*/
#Override
#SuppressWarnings("deprecation")
protected Collection<ConfigAttribute> getConfigAttributes(SecurityRule rule)
{
// Get Access Decision Manager to find if has my expression handler
AccessDecisionManager adm = getAccessDecisionManager();
ExpressionParser ep = null;
// Check if is my CustomAccessDecisionManager so I can use my expressions
if ( adm instanceof CustomAccessDecisionManager )
{
ep = ((CustomAccessDecisionManager) adm).getWebSecurityExpressionHandler().getExpressionParser();
}
List<ConfigAttribute> configAttributes = new ArrayList<ConfigAttribute>();
for ( String attribute : rule.getAttributes() )
{
if ( ep != null )
// this will end the trick with fireworks!
configAttributes.add(new WebExpressionConfigAttribute(ep.parseExpression(attribute)));
else
configAttributes.add(new SecurityConfig(attribute));
}
return configAttributes;
}
}
WebFlow-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:util="http://www.springframework.org/schema/util" xmlns:webflow="http://www.springframework.org/schema/webflow-config"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd
http://www.springframework.org/schema/webflow-config http://www.springframework.org/schema/webflow-config/spring-webflow-config-2.4.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd">
...
<bean id="securityFlowExecutionListener"
class="org.springframework.security.web.access.expression.MamSecurityFlowExecutionListener">
<property name="accessDecisionManager" ref="customAccessDecisionManager"/>
</bean>
...
</beans>
I've found another solution how to use Spring Expression Language in WebFlows. It's from the book "Pro Spring Security". In short, they define a custom AccessDecisionManger with a custom AccessDecisionVoter (implements AccessDesisionVoter<org.springframework.webflow.engine.State) and a custom SecurityExpressionRoot. So no need for an own listener as in your solution. These custom classes support expressions at the flow state level. The full example you can find on github with this link.
I have a property file with key value pairs:
key1=value1
key2=value2
Now, in my controller, I want to directly print the value of a property file (of course after loading the property file using web.xml / app-servlet.xml), like:
System.out.printl(${key1});
Is it possible to do that?
If not, I want to create an interface with all constant variable to read values from property file. How do I do it??
public interface MyConstants
{
#Value("${key1}")
public static final KEY_1="";
}
But as expected only empty string is assigned.
How do I solve this issue? Or, what is the best way to using property files to retrieve values? Thanks in advance...
There are two reasons why having an interface for 'MyConstants' instead of a class is incorrect :
1) Spring cannot inject values to an interface which has no implementation. Simply because you wont be able instantiate the interface. Remember, Spring is just a factory and it can play only with 'things' which can be instantiated.
2) Another reason is that having an interface for storing your constants is an anti-pattern in itself. That is not what interfaces are designed for. You might want to refer to the Constant interface anti-pattern.
http://en.wikipedia.org/wiki/Constant_interface
It's possible! You need to use the util namespace in your app-servlet.xml as below:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p" xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd">
<util:properties id="props" location="classpath:yourfile.properties" />
<!-- other -->
</beans>
And your controller is something like
#org.springframework.beans.factory.annotation.Value("#{props.key1}")
public void setFoo(String foo) {
System.out.println("props.key1: " + foo);
}
update for another way:
You also can use namespace context
<context:property-placeholder location="classpath:yourfile.properties" />
In controller, declare a property as below
#Value("${pros.key1}")
private String foo;
Creating a ''Constants'' class / interface is a widely used approach, but I think its a flawed approach. It creates a weird coupling where classes from different layers in your system suddenly start depending on one Constants class. It also becomes difficult to understand by looking at the constants class, as to which constant is being used by who? Not to mention the fact that it completely mocks abstraction. You suddenly have a constants class which contains information about the error message to show on the jsp, username and password of a third party api, thread pool size etc.. all in one "I know everything" class
So avoid a constant class / interface as far as possible. Look at your controllers / services, if a particular service class needs a particular configuration value that you want exposed in a property file, inject it into the class and store it as an instance level constant. This design is much cleaner from an abstraction point of view, it also helps to unit test this class easily.
In Spring, you can create a handle to a property file as follows:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations" value="classpath:my-application.properties" />
</bean>
As the code suggests, you can mention multiple property files here. After you do this, you can reference a key from the mentioned property file, elsewhere in the context like so:
<bean id="xx" class="com.xx.SomeClass" p:imageUrl="${categories.images}"/>
The SomeClass instance here has a property called imageUrl which is now injected with the value mentioned against the categories.images key from the property file called my-application.properties
Hope this helps.
I am experimenting with Spring AOP for the first time and get stuck in the XML configuration. I'm trying to get a mock version of AOP-based "logging" up and running, using a MethodInterceptor to wrap specific method calls and do some simple System.out.println statements before and after those method invocations. Simple stuff, right?
So my project has many classes, two of them are Fizz and Buzz. Fizz has a method named foo() and Buzz has a method named wapap(). Every time these methods are invoked at runtime, I want my LoggingInterceptor to execute its invoke() method around them:
public class LoggingInterceptor implements MethodInterceptor
{
public Object invoke(MethodInvocation methodInvocation)
{
try
{
System.out.println("About to call a special method.");
Object result = methodInvocation.proceed();
return result;
}
finally
{
System.out.println("Finished executing the special method.");
}
}
}
So I understand the concepts of advice (my interceptor impl), pointcuts (the methods that will have advice executed around them), and pointcut advisors (bindings between advice and pointcuts).
I'm just struggling tying it altogether in a simple XML config.
Here's what I have so far, but I know it's missing pointcut and pointcut advisor definitions, and possibly more.
<beans default-autowire="no" >
<bean name="loggingInterceptor" class="org.me.myproject.aop.LoggingInterceptor"/>
</beans>
What am I missing here to make this specific to Fizz::foo() and Buzz::wapap() calls?
Any nudges in the right direction are enormously appreciated!
Add this:
<aop:config>
<aop:advisor advice-ref="loggingInterceptor" pointcut="execution(public * Fizz.foo(..))"/>
<aop:advisor advice-ref="loggingInterceptor" pointcut="execution(public * Buzz.wapap(..))"/>
</aop:config>
You also need to add AOP namespace declaration in version appropriate to your framework:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
">
Also consider using #AspectJ aspects and see this question: Spring: Standard Logging aspect (interceptor).
If you are using Spring 2.5+ you can use annotation to and create your advice and Pointcuts.
Create class with #Aspect annotation.
Create #PointCut for specific class and specific method and then create #Around advice.
You can read short tutorial how to do it here:
http://veerasundar.com/blog/2010/01/spring-aop-example-profiling-method-execution-time-tutorial/
It' very easy to implement.
Can you enlighten me on this problem I encountered while experimenting with Spring.
I have 2 context here. let's name them springA.xml and springB.xml
springA.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<import resource="springB.xml" />
<bean name="name2" class="java.lang.String"/>
</beans>
springB.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean name="name2,name3" class="java.lang.String"/>
</beans>
springC.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean name="name3,name2" class="java.lang.String"/>
</beans>
And this is my Java File.
public static void main(String[] args) {
BeanFactory factory = new XmlBeanFactory(new ClassPathResource("springA.xml"));
Object obj1 = factory.getBean("name2");
Object obj2 = factory.getBean("name3");
System.out.println(obj1.getClass().getName() + " " + obj2.getClass().getName());
}
And the result, I get a "java.lang.String java.lang.String". If I change the position of
the name "name2,name3" to "name3,name2" (springC.xml), I get a "java.lang.Object java.lang.Object".
I am just confused as to why the result is like that. I was expecting that the function will return java.lang.String for name2 and java.lang.Object for name3 (since name2 is already used in the springA.xml, I am assuming this name will not be used and instead, will use name3 for springB.xml)
Thanks!
PS:
Spring 2.5
Eclipse 3.5
From Spring's documentation:
Every bean has one or more ids (also
called identifiers, or names; these
terms refer to the same thing). These
ids must be unique within the
BeanFactory or ApplicationContext the
bean is hosted in.
According to this, your combined application context is invalid as it contains two different beans which have the same ID - your bean named "name2" from ContextA.xml and your bean named "name2", aliased "name3" in ContextC.xml. I would expect Spring to issue at least a warning about this.
To answer your question: You shouldn't expect any sane results from this kind of setup. Bean names have to be unique and if they aren't the results are undefined. And by "undefined" I mean "unlikely to be helpful" :)
Hope this helps.
I believe you are seeing different results because Spring is loading the beans in the context in different orders in each scenario. Spring makes no guarantee as to which order it will load it's beans other than the fact that any beans used as "ref"'s in other bean definitions will be loaded before the beans that depend on them.
The correct solution to your problem is DO NOT use duplicate bean identifiers and then you won't have to guess as to which bean you will get when you look one up.
I've ran your code on Spring 2.5.6 and 3.0.0.M1 and both version produce the same result.
java.lang.String java.lang.String
My advice is if you want two strings and you are getting strange results with 2.5, then bump to 2.5.6 or 3.0.0.M1.