The issue is the #Before and #AfterReturning are working but it's not the case for Pointcut.
Here is my aspect.
As part of a springboot service, What I want do is trigger the pointcut with first method profile to show execution time and other things.
Am I missing something ?
package com.myproj.service.myagg.aop;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.util.StopWatch;
/**
* Created by shammami on 26/05/2017.
*/
#Aspect
#Component
public class LoggingService {
#Pointcut("execution(public void com.myproj.service.myagg.listener.MyMessageConsumer.handleMessage(..))")
public Object profile(ProceedingJoinPoint pjp) throws Throwable {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
boolean isExceptionThrown = false;
try {
// execute the profiled method
return pjp.proceed();
} catch (RuntimeException e) {
isExceptionThrown = true;
throw e;
} finally {
stopWatch.stop();
StopWatch.TaskInfo taskInfo = stopWatch.getLastTaskInfo();
// Log the method's profiling result
String profileMessage = taskInfo.getTaskName() + ": " + taskInfo.getTimeMillis() + " ms" +
(isExceptionThrown ? " (thrown Exception)" : "");
System.out.println(profileMessage);
}
}
#Before("execution(public void com.myproj.service.myagg.listener.MyMessageConsumer.handleMessage(..))")
public void before(JoinPoint joinPoint) {
System.out.println("Started: " + joinPoint.getStaticPart().getSignature().toLongString());
}
#AfterReturning("execution(public void com.myproj.service.myagg.listener.MyMessageConsumer.handleMessage(..))")
public void completed(JoinPoint joinPoint) {
System.out.println("Completed: " + joinPoint.getStaticPart().getSignature().toLongString());
}
}
When you annotate something with #Pointcut you are basically defining the pointcut signature, you can not do any sort of processing in there. What you need to do is to create another method which has all the processing details and uses the pointcut signature you evaluated above. Hence,
#Pointcut("execution(public void com.myproj.service.myagg.listener.MyMessageConsumer.handleMessage(..))")
public void myPointcutSignature(){
//This basically has nothing :)
}
#Around("myPointcutSignature")
public Object profile(ProceedingJoinPoint pjp) throws Throwable {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
boolean isExceptionThrown = false;
//And the remaining code
-------
}
Hope this works. Also remember that ProceedingJoinPoint can be used only with #Around advice.
Related
The line of code that is giving me fits is:
this.databaseHandler = new DatabaseHandler(MainActivity.
I have that module in the project and this line is from another project that I am trying to incorporate. I believe I need this line and am having trouble getting the idea of context parameter as it is used here.
Yes, the line is incomplete because I can not finish it.
Could my whole structure or thinking be wrong?
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.os.AsyncTask;
import com.Table.TableMainLayout;
import com.example.tablefreezepane.DatabaseHandler;
public class MainActivity extends Activity {
final String TAG = "MainActivity.java";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
/* Loads next module */
setContentView(new TableMainLayout(this));
}
}
public class AsyncInsertData extends AsyncTask<String, String, String> {
DatabaseHandler databaseHandler;
String type;
long timeElapsed;
protected AsyncInsertData(String type){
this.type = type;
this.databaseHandler = new DatabaseHandler(MainActivity.
//(MainActivity.this);
}
// #type - can be 'normal' or 'fast'
//#Override
//protected void onPreExecute() {
// super.onPreExecute();
// tvStatus.setText("Inserting " + editTextRecordNum.getText() + " records...");
//}
#Override
protected String doInBackground(String... aurl) {
try {
// get number of records to be inserted
int insertCount = 20;
// empty the table
databaseHandler.deleteRecords();
// keep track of execution time
long lStartTime = System.nanoTime();
if (type.equals("normal")) {
databaseHandler.insertNormal(insertCount);
} else {
databaseHandler.insertFast(insertCount);
}
// execution finised
long lEndTime = System.nanoTime();
// display execution time
timeElapsed = lEndTime - lStartTime;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
protected void onPostExecute(String unused) {
//Toast.makeText(getApplicationContext(),"This is an Android Toast Message", Toast.LENGTH_LONG).show();
//tvStatus.setText("Done " + choice + " inserting " + databaseHandler.countRecords() + " records into table: [" + this.databaseHandler.tableName + "]. Time elapsed: " + timeElapsed / 1000000 + " ms.");
}
}
Thank you in advance.
Where this is async, you can't access the context from MainActivity the way you are. To do so, add constructor with a context parameter, then replace your MainActivity.this with context
I have a method which returns an object. I would like to print that object's value in my log using spring AOP. How can I achieve that?
Please help!
Using #AfterReturning with a returnValue param.
You could then interogate the object returned
This is an example where I do it on everything but get methods in a repository
#AfterReturning(value = "#target(org.springframework.stereotype.Repository) && !execution(* get*(..))", returning = "returnValue")
public void loggingRepositoryMethods(JoinPoint joinPoint, Object returnValue) {
String classMethod = this.getClassMethod(joinPoint);
if(returnValue !=null)
{
//test type of object get properties (could use reflection)
log it out
}
else
{
//do logging here probably passing in (joinPoint, classMethod);
}
}
In our case, majority of the time we return entity classes of spring modal, so we overridden the toString method of all entity classes with required minimal information and printed as below
#AfterReturning(pointcut = "within(#org.springframework.stereotype.Service *)", returning = "result")
public void logAfterReturning(JoinPoint joinPoint, Object result) {
logger.info(" ###### Returning for class : {} ; Method : {} ", joinPoint.getTarget().getClass().getName(), joinPoint.getSignature().getName());
if (result != null) {
logger.info(" ###### with value : {}", result.toString());
} else{
logger.info(" ###### with null as return value.");
}
}
Spent quite sometime on this, so putting here...
package com.mycomp.poc.JcachePoc.config;
import java.util.HashMap;
import java.util.Map;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import lombok.extern.slf4j.Slf4j;
#Aspect
#Component
#Slf4j
public class LoggingAspectConfig {
private static LoggingAspectConfig loggingAspectConfig;
#Bean
public LoggingAspectConfig createBean() {
if(loggingAspectConfig==null)
return new LoggingAspectConfig();
else
return loggingAspectConfig;
}
private LoggingAspectConfig () {
}
#Before("execution(* com.mycom.poc.JcachePoc.service*.*.*(..)) && #annotation(Log)")
public void logBefore(JoinPoint joinPoint) {
if(log.isDebugEnabled()) {
Object[] args= joinPoint.getArgs();
Map<String, String> typeValue= new HashMap<>();
for(Object obj: args) {
if(obj!=null) {
typeValue.put(obj.getClass().getName(), obj.toString());
}
}
//log.debug("calling Method:"+joinPoint.getSignature().getDeclaringTypeName()+", "+joinPoint.getSignature().getName()+", Parameter:-> "+ typeValue);
}
}
#AfterReturning(pointcut = "execution(* com.mycom.poc.JcachePoc.service*.*.*(..)) && #annotation(Log)", returning = "result")
public void logAfter(JoinPoint joinPoint, Object result) {
if (log.isDebugEnabled() && result!=null) {
log.debug("Method returned:" +
joinPoint.getSignature().getName() + ", Result: " + result.getClass().getName()+" -->"+result);
}
//log.info(gson.toJson(result));
}
}
I am not able to inject a SLSB in another SLSB. Actually created 3 projects
1) created a EJB project with an MDB
2) created a EJB project with a stateless session bean for posting the message
3) created a EJB project with a stateless session bean for injecting the above session bean
But while injecting I am not able to inject the EJB it is returning null
the code is as below
1) MDB:
#MessageDriven(
activationConfig = {
#ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
#ActivationConfigProperty(propertyName = "destination", propertyValue = "activemq/queue/TestQueue"),
#ActivationConfigProperty(propertyName="acknowledgeMode", propertyValue="Auto-acknowledge")
})
#ResourceAdapter("activemq-ra.rar")
public class ConsumerMDB implements MessageListener {
public void onMessage(Message message) {
try {
System.out.println("Queue: Received a TextMessage at " + new Date());
TextMessage msg = (TextMessage) message;
System.out.println("Message is : " + msg.getText());
} catch (JMSException e) {
e.printStackTrace();
}
}
}
2) Session Bean 1
package com.springboard.session;
import javax.annotation.Resource;
import javax.ejb.LocalBean;
import javax.ejb.Stateless;
import javax.jms.JMSException;
import javax.jms.Queue;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.QueueSender;
import javax.jms.QueueSession;
import javax.jms.TextMessage;
#Stateless
#LocalBean
public class ProducerSession implements ProducerSessionLocal {
#Resource(mappedName="java:jboss/activemq/QueueConnectionFactory")
public static QueueConnectionFactory factory;
#Resource(mappedName = "java:jboss/activemq/queue/TestQueue")
public static Queue queue;
#Override
public void sendMessage(String msg) {
System.out.println("****************Entering into method********************");
try {
System.out.println(queue.getQueueName());
QueueConnection qConnection = factory.createQueueConnection();
QueueSession qSession = qConnection.createQueueSession(false, QueueSession.AUTO_ACKNOWLEDGE);
TextMessage message = qSession.createTextMessage();
message.setText(msg);
QueueSender qSender = qSession.createSender(queue);
qSender.send(message);
qSender.close();
qSession.close();
qConnection.close();
} catch (JMSException e) {
e.printStackTrace();
}
System.out.println("****************Exiting into method********************");
}
}
and the interface is
package com.springboard.session;
import javax.ejb.Local;
#Local
public interface ProducerSessionLocal {
public void sendMessage(String msg);
}
3) Second session bean to inject the first session
#Stateless
public class TestProducerLocalBean implements TestProducerLocalBeanLocal {
#EJB(mappedName = "java:global/ProducerSessionActiveMQ/ProducerSession!com.springboard.session.ProducerSessionLocal")
public ProducerSessionLocal producer;
public TestProducerLocalBean() {
System.out.println("*************Testing Producer****************");
if(producer!=null){
producer.sendMessage("This Message is from SessionBean to Session Bean to MDB");
}
else{
System.out.println("EJB is null");
}
System.out.println("**********End************************");
}
#Override
public void messageSend(String msg) {
// TODO Auto-generated method stub
}
and for testing purpose used a class
import javax.ejb.EJB;
import com.springboard.session.test.TestProducerLocalBean;
public class testEJB {
#EJB
public static TestProducerLocalBean local =new TestProducerLocalBean();
public static void main(String[] args) {
}
}
At producer EJB always retuns null. With using servlet to inject ProducerSession i am able to do it. but injecting with another EJB i not able to get it.
Could any one please help me out what i am missing
Thanks in advance
It's incorrect to use initialization ... = new Xyz() when using injection because initialization of those fields is the responsibility of the container. You probably attempted that because you noticed that the field was null, and that's because injection (including #EJB) is not supported in the main class unless you use an application client container.
I came across the problem described in Checking If alert exists before switching to it. I find horrible to capture a NullPointerException. Has anyone solved this problem more elegantly?
My current solution uses a wait that captures the NPE. The client code just have to invoke waitForAlert(driver, TIMEOUT):
/**
* If no alert is popped-up within <tt>seconds</tt>, this method will throw
* a non-specified <tt>Throwable</tt>.
*
* #return alert handler
* #see org.openqa.selenium.support.ui.Wait.until(com.google.common.base.Function)
*/
public static Alert waitForAlert(WebDriver driver, int seconds) {
Wait<WebDriver> wait = new WebDriverWait(driver, seconds);
return wait.until(new AlertAvailable());
}
private static class AlertAvailable implements ExpectedCondition<Alert> {
private Alert alert = null;
#Override
public Alert apply(WebDriver driver) {
Alert result = null;
if (null == alert) {
alert = driver.switchTo().alert();
}
try {
alert.getText();
result = alert;
} catch (NullPointerException npe) {
// Getting around https://groups.google.com/d/topic/selenium-users/-X2XEQU7hl4/discussion
}
return result;
}
}
JavaDoc for FluentWait.until()
Repeatedly applies this instance's input value to the given function until one of the following occurs:
the function returns neither null nor false,
the function throws an unignored exception,
the timeout expires
.......(snip)
Since NullPointerException denotes a false condition, and WebDriverWait is only ignoring NotFoundException, just remove the try/catch block. An unchecked, unignored Exception thrown in apply() is semantically equivalent to returning null as in your existing code.
private static class AlertAvailable implements ExpectedCondition<Alert> {
#Override
public Alert apply(WebDriver driver) {
Alert result = driver.switchTo().alert();
result.getText();
return result;
}
}
Based upon #Joe Coder answer, a simplified version of this wait would be:
/**
* If no alert is popped-up within <tt>seconds</tt>, this method will throw
* a non-specified <tt>Throwable</tt>.
*
* #return alert handler
* #see org.openqa.selenium.support.ui.Wait.until(com.google.common.base.Function)
*/
public static Alert waitForAlert(WebDriver driver, int seconds) {
Wait<WebDriver> wait = new WebDriverWait(driver, seconds)
.ignore(NullPointerException.class);
return wait.until(new AlertAvailable());
}
private static class AlertAvailable implements ExpectedCondition<Alert> {
#Override
public Alert apply(WebDriver driver) {
Alert alert = driver.switchTo().alert();
alert.getText();
return alert;
}
}
I have written a short test to proof the concept:
import com.google.common.base.Function;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.concurrent.TimeUnit;
import org.junit.Test;
import org.openqa.selenium.support.ui.FluentWait;
import org.openqa.selenium.support.ui.Wait;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class TestUntil {
private static Logger log = LoggerFactory.getLogger(TestUntil.class);
#Test
public void testUnit() {
Wait<MyObject> w = new FluentWait<MyObject>(new MyObject())
.withTimeout(30, TimeUnit.SECONDS)
.ignoring(NullPointerException.class);
log.debug("Waiting until...");
w.until(new Function<MyObject, Object>() {
#Override
public Object apply(MyObject input) {
return input.get();
}
});
log.debug("Returned from wait");
}
private static class MyObject {
Iterator<Object> results = new ArrayList<Object>() {
{
this.add(null);
this.add(null);
this.add(new NullPointerException("NPE ignored"));
this.add(new RuntimeException("RTE not ignored"));
}
}.iterator();
int i = 0;
public Object get() {
log.debug("Invocation {}", ++i);
Object n = results.next();
if (n instanceof RuntimeException) {
RuntimeException rte = (RuntimeException)n;
log.debug("Throwing exception in {} invocation: {}", i, rte);
throw rte;
}
log.debug("Result of invocation {}: '{}'", i, n);
return n;
}
}
}
In this code, in the until the MyObject.get() is invoked four times. The third time, it throws an ignored exception, but the last one throws a not-ignored exception, interrupting the wait.
The output (simplified for readability):
Waiting until...
Invocation 1
Result of invocation 1: 'null'
Invocation 2
Result of invocation 2: 'null'
Invocation 3
Throwing exception in 3 invocation: java.lang.NullPointerException: NPE ignored
Invocation 4
Throwing exception in 4 invocation: java.lang.RuntimeException: RTE not ignored
------------- ---------------- ---------------
Testcase: testUnit(org.lila_project.selenium_tests.tmp.TestUntil): Caused an ERROR
RTE not ignored
java.lang.RuntimeException: RTE not ignored
at org.lila_project.selenium_tests.tmp.TestUntil$MyObject$1.<init>(TestUntil.java:42)
at org.lila_project.selenium_tests.tmp.TestUntil$MyObject.<init>(TestUntil.java:37)
at org.lila_project.selenium_tests.tmp.TestUntil$MyObject.<init>(TestUntil.java:36)
at org.lila_project.selenium_tests.tmp.TestUntil.testUnit(TestUntil.java:22)
Note that as the RuntimeException is not ignored, the "Returned from wait" log is not printed.
I tried to apply AOP to Struts2 action classes.
My configurations are:
<aop:aspectj-autoproxy proxy-target-class="true"/>
<bean id="actionClassAspect" class="com.rpm.application.profiling.ActionClassAspect"/>
<aop:config>
<aop:pointcut id="actionClassPointcut" expression="execution(public * com.rpm..action.*.*(..))
and !execution(public * com.rpm..action.*.get*(..))
and !execution(public * com.rpm..action.*.set*(..))
and !within(com.rpm..profiling.*)"/>
<aop:aspect id="actionAspect" ref="actionClassAspect">
<aop:around method="doAspect" pointcut-ref="actionClassPointcut"/>
</aop:aspect>
my action class is:
package com.rpm.application.common.web.action;
import com.opensymphony.xwork2.ActionSupport;
public class ApplicationLoginAction extends ActionSupport {
private String userID, password;
#Override
public String execute() throws Exception {
try {
//validation logic
System.out.println("Login success");
return SUCCESS;
} catch(Exception e) {
return ERROR;
}
}
public String getUserID() {
return userID;
}
public void setUserID(String userID) {
this.userID = userID;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
my aspect is:
package com.rpm.application.profiling;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Aspect;
#Aspect
public abstract class ActionClassAspect {
public Object doAspect(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
long start = System.currentTimeMillis();
Object returnValue = proceedingJoinPoint.proceed(proceedingJoinPoint.getArgs());
long end = System.currentTimeMillis();
System.out.println(" " + proceedingJoinPoint.getTarget().getClass() + " KIND:" + proceedingJoinPoint.getSignature().toShortString() + " TIME: " + (end - start));
return returnValue;
}
}
When I executing this application on tomcat6.x server AOP is not applied to that action class.
I found the solution. Need to add struts2-spring-plugin-2.x.x.jar in classpath.
This plug-in will add automatically all action classes configured in struts.xml into spring container.