logging with AOP in spring? - java

I am new to spring in my office . So there is no guidance for me.
I need to implement the logging with the AOP using the log4j.
I have implemented the logging without AOP in basic spring MVC example ?
Also did the small sample in AOP using the aspectJ without logging (just made the Sysout) ?
I don't know how to integrate it ?
Can any one please give me a start up idea?
Good answers are definitely appreciated ...

Spring makes it really easy for us to make use of AOP. Here's a simple logging example:
#Aspect
public class MyLogger {
private Logger log = Logger.getLogger(getClass());
#After("execution(* com.example.web.HomeController.*(..))")
public void log(JoinPoint point) {
log.info(point.getSignature().getName() + " called...");
}
}
Then simply configure your applicationContext.xml (or equivalent):
<aop:aspectj-autoproxy>
<aop:include name="myLogger"/>
</aop:aspectj-autoproxy>
<bean id="myLogger" class="com.example.aspect.MyLogger"/>
You'll notice in the MyLogger class that I specified #After right above the method. This is called the advice and it basically specifies that this 'log' method will be called after the method in question. Other options include #Before, #Around, #AfterThrowing.
The expression "execution(* com.example.web.HomeController.*(..))" is called a pointcut expression and specifies what we're targeting (in this case all methods of the HomeController class).
P.S. The aop namespace (xmlns:aop="http://www.springframework.org/schema/aop") and the schema location (version dependent) would need to be added to your applicationContext.xml right at the top. Here is my setup:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd">

You need to perform several steps to integrate Aspectj:
Install AspectJ
Add your aop.xml to META-INF\aop.xml in your project
Add aspectjrt-x.x.0.jar and aspectjweaver-x.x.0.jar in your project classpath
Add -javaagent:/path to aspectj installation/aspectjweaver-1.7.0.jar to your server's JVM.
Here is a sample aop.xml:
<aspectj>
<aspects>
<aspect name="test.MySimpleLoggerAspect" />
</aspects>
<weaver>
<include within="test.myproject.*" />
</weaver>
</aspectj>
If you are already using Spring then it is better to use Spring to simplify your setup.

Related

Configure dependency injection for xml beans in Grails 3 project

I have a project in grails 3, that has a project spring dependency, in the spring project, xml beans are configured. How should import the bens in grails architecture?
build.gradle
dependencies {
compile (project(':spring-project')) { transitive = false }
}
settings.gradle
includeFlat 'spring-project'
I tried the following ways:
in the resources.groovy load the beans:
beans = {
importBeans('path/to/beans-definition.xml')
}
in the resources.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:task="http://www.springframework.org/schema/task"
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/task http://www.springframework.org/schema/task/spring-task.xsd">
<import resource="path/to/beans-definition.xml" />
</beans>
Besides that, in the spring project, beans using java annotation are configured. The beans is not working in grails app, even by setting the spring project packages in the conponent scan.
#ComponentScan(basePackages = ["package.spring.project.beans"])
class Application extends GrailsAutoConfiguration {
static void main(String[] args) {
GrailsApp.run(Application, args)
}
}
But, nothing works. Any help would be appreciated..
Beans can also be configured using a grails-app/conf/spring/resources.xml. In earlier versions of Grails this file was automatically generated for you by the run-app script, but the DSL in resources.groovy is the preferred approach now so it isn’t automatically generated now. But it is still supported - you just need to create it yourself.
<bean id="myBean" class="my.company.MyBeanImpl">
<property name="someProperty" value="42" />
<property name="otherProperty" value="blue" />
further check this link

AspectJ - method #around not called

I want to use AspetcJ to plug in to log4J method that is located in org.apache.log4j.Category.java file.
protected void forcedLog(String fqcn, Priority level, Object message, Throwable t) {
callAppenders(new LoggingEvent(fqcn, this, level, message, t));
}
so finally that
#Around("execution(protected void org.apache.log4j.Category.*(..))
would work.
What problem do i have?
My aspect dont get called.
So i made easier example - and it also does not get called.
core.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"
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
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<!-- <aop:aspectj-autoproxy /> -->
<context:load-time-weaver/>
<!-- Aspect -->
<!--
<bean id="beanName" class="class.sth.ClazzName" />
<bean id="beanName2" class="class.sth.Clazz2Name" />
-->
<!-- other beans - not aspects -->
</beans>
aop.xml
<!DOCTYPE aspectj PUBLIC "-//AspectJ//DTD//EN" "http://www.eclipse.org/aspectj/dtd/aspectj.dtd">
<aspectj>
<weaver>
<!-- only weave classes in our application-specific packages -->
<include within="*"/>
<exclude within="org.jibx*"/>
</weaver>
<aspects>
<!-- weave in just this aspect -->
<aspect name="class.sth.ClazzName"/>
<aspect name="class.sth.Clazz2Name"/>
</aspects>
</aspectj>
Example java class which should be invoked when i run JUnit test - in which clearly i see that this line of code is executed:
System.out.println("test");
Still i don't see my aspect getting called.
#Aspect
#Order(3)
public class ClazzName {
#Around("call(* *println(..))")
public void testMethod(ProceedingJoinPoint joinPoint) {
Object o = joinPoint.getArgs();
System.out.println("test");
}
}
In my app in the same JUnit test other aspect is called.
That can tell Us that we have good dependencies in the project.
#Aspect
#Order(2)
public class Clazz2Name {
#Around("#annotation(loggable)")
public Object doStuff(ProceedingJoinPoint joinPoint, Clazz2Name log) throws Throwable{
...
}
...
My classes are not always marked as #Component and i want to leave it that way.
JUnit VM arguments
-javaagent:C:\aspectjWeaver\spring-instrument-3.0.4.jar
The question is how i can achieve my goal and make my aspect get called when i want it to ?
You actually have at least the following problems:
You did not read the Spring AOP documentation. (Sorry, couldn't resist.)
You are using Spring AOP, not full AspectJ. The difference is that the former only works for Spring components, but Log4J is not a Spring component. So if you want to make it work you need to use full AspectJ via load-time weaving as described by chapter 11.8 of the Spring manual, secsion Using AspectJ with Spring applications.
Even when using full AspectJ you need to know that you cannot hook into executions of JDK methods because those have already been loaded before the aspect weaver is instantiated. Thus, you should hook into method calls via call(* println(..)), not into method executions.
What I do not understand is why you want to hook into Log4J and JDK methods anyway. Do you want to redirect the calls to some other channel? Maybe it would be better to describe what you actually want to achieve, not how you think the problem should be solved.

what are the spring integration classes used stdin-channel-adapter?

I am interested to know the classes used in spring integration tag so that I can get more details of the tags by going through the javadoc of the classes.
I have two basic questions:
Do the spring integration xml tags (for example stdin-channel-adapter) convert to <bean class=".." /> tags?
how to figure out the bean class associated with the spring integration tags?
Here is a simple example of spring integration xml context file:
<?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:int="http://www.springframework.org/schema/integration"
xmlns:int-stream="http://www.springframework.org/schema/integration/stream"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration-4.0.xsd
http://www.springframework.org/schema/integration/stream http://www.springframework.org/schema/integration/stream/spring-integration-stream-4.0.xsd">
<int-stream:stdin-channel-adapter id="producer" channel="messageChannel" />
<int:poller id="defaultPoller" default="true" max-messages-per-poll="2" fixed-rate="100" />
<int-stream:stdout-channel-adapter id="consumer" channel="messageChannel" append-newline="true" />
<int:channel id="messageChannel" />
</beans>
Thanks
I think you have some mistake in your first question. See Andreas' comment.
Anyway the answer for you is like.
Any custom tags in Spring are handler by the particular NamespaceHandler. Typically you can find the target impl in file like META-INF/spring.handlers in the particular Spring jar, e.g.:
http\://www.springframework.org/schema/integration/stream=org.springframework.integration.stream.config.StreamNamespaceHandler
With that in hands you can find the code like:
this.registerBeanDefinitionParser("stdin-channel-adapter", new ConsoleInboundChannelAdapterParser());
Where you can determine that a ConsoleInboundChannelAdapterParser is responsible for parsing and instantiation beans for <stdin-channel-adapter> tag.
And there you can find the code like:
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(
"org.springframework.integration.stream.CharacterStreamReadingMessageSource");
So, the real class for target bean instance is CharacterStreamReadingMessageSource. But that's not all.
Please, look here for the design and model: http://docs.spring.io/spring-integration/docs/4.3.0.RELEASE/reference/html/overview.html#programming-tips

GWT vs Spring: applicationContext is null if I change the page

I am inheriting a project from a developer who left, and I am trying to understand GWT and Spring Framework.
The original problem that lead me to this path: GWT had one module where I loaded ALL third party javascripts... that could result in conflicts. Example, I would include chart drawing libraries, etc. all in one page.
Possible solutions: Have the chart drawing library in an iframe so that it would not conflict with other third party libraries of javascript... OR open the page in a new window.
I decided to go with a new window.
So I did this:
Window.Location.assign(GWT.getHostPageBaseURL()
+ "chartModule.html?gwt.codesvr=127.0.0.1:9997/");
However, in my new chartModule.java (GWT) the problem I have is I do not have the beans/classses defined in (Spring framework) applicationContext.xml anymore:
#Autowired
ApplicationContext applicationContext;
And applicationContext is null after I have changed the host page url... so I do not have any beans that I tried autowiring...
Is it possible to reload the beans from applicationContext.xml??
Here is my applicationContext.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:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd">
<!-- Activates various annotations to be detected in bean classes -->
<context:annotation-config />
<!-- This file has properties that are used by other XML files loaded via ${var name} syntax -->
<context:property-placeholder location="/WEB-INF/classes/environment.properties" />
<import resource="spring-security-cas.xml" />
<!-- Scans the classpath for annotated components that will be auto-registered
as Spring beans. For example #Controller and #Service. Make sure to set the
correct base-package -->
<context:component-scan base-package="com.javamango.sixtydegrees" />
<import resource="mongo-config.xml" />
<import resource="rabbitmq-context.xml" />
<import resource="spring-mail.xml" />
</beans>
You cannot use spring beans on client side. If you want retriewe some data from spring in gwt, you can do this at two ways:
1) use server side library like gwt-sl to inject spring beans in gwt servlet
#Service("greetingService")
public class GreetingServiceImpl extends RemoteServiceServlet implements GreetingService
{
#SuppressWarnings("unused")
private static final Logger LOGGER = LoggerFactory.getLogger(GreetingServiceImpl.class);
#Autowired
UserFileService userFileService;
#Autowired
UserService userService;
}
now you can autowire spring beans and obtain data via gwt-rpc
2) put data via jsp in hidden html form fields and retriewe data from it
<input type="hidden" value="7" id="documentid"/>
String id = (InputElement) (Element) DOM.getElementById("documentid").value

spring java xml configuration

im using spring for my java web app. the site has got bigger and i would like to set some configurations.
i have been researching and came across things like document builder factory, replacing spring xml with java config and others. i dunno where to start.
im thinking of implementing the configurations in xml (WEB/newConfig.xml) and have it read by the java beans. basically i wanna input my cofiguration values into xml and have it load by a java bean so that i can use it in controllers and jstl.
im just giving some examples here. for example xml configurations:
<property name="numberOfCars" value="3" />
<property name="webSiteName" value="New Spring Web App" />
....
and i read it in my java class:
class Config {
public getNumberOfCars() {
return numOfCars;
}
public getWebSiteName() {
return webSiteName;
}
}
where should i start and what online materials can i read?
==============================
update
here is what i have created.
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<context:property-placeholder location="/WEB-INF/your_prop_file.properties" />
<bean id="ConfigMgr" class="org.domain.class.ConfigMgr">
<property name="username" value="${username}">
</bean>
</beans>
you_prop_file.properties
username=hello world name
ConfigMgr.java
public class ConfigMgr {
private String username;
...getter
...setter
}
in my controller, here is what i did:
ConfigMgr config = new ConfigMgr();
sysout.out.println(config.getUsername());
i am getting null and i am sure im missing something here. where should i set the username value to the ConfigMgr class?
Spring Java configuration is a newer feature that allows you to configure your Spring application using Java classes instead of XML files. Its just an alternative for XML configuration. XML way is equally feature rich.
From what I could figure out from your problem, you want to move the hardcoded values of params (numberOfCars,webSiteName.. ) outisde your configuration file.
If that is the case, you don't have to go that far.
Just use :-
<context:property-placeholder location="classpath:your_prop_file.properties" />
in your spring xml file and replace the param values like:-
<property name="webSiteName" value="${website.name}" />
You need to have a your_prop_file.properties file in your classpath with enteries like:-
website.name=New Spring Web App
You are not injecting the ConfigMgr bean that you created in XML file.
What you are doing is you are creating a new Object in controller which does not have a clue about properties file.
Now you can inject it using either #Autowired inside your controller or through xml configuration.
There are plenty of examples available in google on basic spring dependency injection.

Categories