method to be covered for metrics generation:
#Override
#Metric(metricName = "rmq.onMessage", type = { MetricType.METER, MetricType.HISTOGRAM })
public void onMessage(Object messageBytes) {
//some processing
}
Registering Method here:
MessageListenerAdapter listenerAdapter = new MessageListenerAdapter(messageConsumer, "onMessage");
if any messages come in the queue then onMessage will be invoked using:
protected Object invokeListenerMethod(String methodName, Object[] arguments, Message originalMessage)
throws Exception {
try {
MethodInvoker methodInvoker = new MethodInvoker();
methodInvoker.setTargetObject(getDelegate());
methodInvoker.setTargetMethod(methodName);
methodInvoker.setArguments(arguments);
methodInvoker.prepare();
return methodInvoker.invoke();
}
My Aspect:
#Around("#annotation(myAnnotation.graphite.annotations.Metric)")
public Object graphiteAspect(ProceedingJoinPoint joinPoint) {
//metrics reporting done here
}
Related
I wanted to do so custom logic(Record the request and response) on some routes. Based on some research I came decided to use AnnotationBased RequestInterceptor. This is my code for interceptor.
public class CustomInterceptor extends HandlerInterceptorAdapter {
#Override
public void afterCompletion(final HttpServletRequest request,
final HttpServletResponse response,
final Object handler,
final Exception ex) {
if (handler != null && handler instanceof HandlerMethod) {
HandlerMethod handlerMethod = (HandlerMethod) handler;
CustomRecord annotation = AnnotationUtils.getAnnotation(handlerMethod.getMethod(), CustomRecord.class);
if (annotation != null) {
// Record Request and Response in a File.
}
}
Now this class is working as expected but I was unable to unit test this function.
I first thought of trying a creating an HandlerMethod Object but I
did not get anywhere.
Second I tried to use PowerMokito. This was my test code:
#RunWith(PowerMockRunner.class)
#PrepareForTest(CustomInterceptor.class)
#PowerMockIgnore("javax.management.*")
public class CustomInterceptorTest {
#Test
public void restAnnotationRecording_negetivecase() {
HandlerMethod mockHandler = mock(HandlerMethod.class);
PowerMockito.mockStatic(AnnotationUtils.class);
when(AnnotationUtils.getAnnotation(mockHandler.getMethod(),
CustomRecord.class).thenReturn(null);
// Verify file is not saved
}
// A spy is stubbed using when(spy.foo()).then() syntax. It is safer to stub spies - - with doReturn|Throw() family of methods. More in javadocs for Mockito.spy() methodcannot be saved.
#Test
public void restAnnotationRecording_happycase() {
HandlerMethod mockHandler = mock(HandlerMethod.class);
PowerMockito.mockStatic(AnnotationUtils.class);
when(AnnotationUtils.getAnnotation(mockHandler.getMethod(), CustomRecord.class).thenReturn(mockAnnotation);
// Verify file is saved
}
}
This gives an Error A spy is stubbed using when(spy.foo()).then() syntax. It is safer to stub spies with doReturn|Throw() family of methods.
I wanted to check if there is any method to test the Interceptor. I am a newbie in Java, thanks for help.
You can easily create your own HandlerMethod without mocking. There's a constructor that accepts an Object (the controller) and a Method (the controller method). The easiest way to get a Method is to simply call Class.getMethod(). What you want to do is just create a dummy controller class, and then use that class to get the method. For example
class TestController {
#Custom
public void testMethod() {}
}
Method method = TestController.class.getMethod("testMethod");
TestController controller = new TestController();
HandlerMethod handlerMethod = new HandlerMethod(controller, method);
Custom annotation = handlerMethod.getMethodAnnotation(Custom.class);
It's that easy. Below is a complete test.
public class HandlerInterceptorTest {
#Target(ElementType.METHOD)
#Retention(RetentionPolicy.RUNTIME)
private #interface Custom {
}
private static class MyHandlerInterceptor implements HandlerInterceptor {
#Override
public boolean preHandle(HttpServletRequest req, HttpServletResponse res, Object handler) {
if (handler instanceof HandlerMethod) {
HandlerMethod handlerMethod = (HandlerMethod) handler;
Custom annotation = handlerMethod.getMethodAnnotation(Custom.class);
if (annotation != null) {
return true;
}
}
return false;
}
}
private static class TestController {
#Custom
public void testMethodWithAnnotation() {}
public void testMethodWithoutAnnotation() {}
}
#Test
public void testMethodWithAnnotation() throws Exception {
Method method = TestController.class.getMethod("testMethodWithAnnotation");
TestController controller = new TestController();
HandlerMethod handlerMethod = new HandlerMethod(controller, method);
MyHandlerInterceptor interceptor = new MyHandlerInterceptor();
boolean result = interceptor.preHandle(null, null, handlerMethod);
assertTrue(result);
}
#Test
public void testMethodWithoutAnnotation() throws Exception {
Method method = TestController.class.getMethod("testMethodWithoutAnnotation");
TestController controller = new TestController();
HandlerMethod handlerMethod = new HandlerMethod(controller, method);
MyHandlerInterceptor interceptor = new MyHandlerInterceptor();
boolean result = interceptor.preHandle(null, null, handlerMethod);
assertFalse(result);
}
}
I have written an Exception handler class that looks at the default Spring Integration errorChannel for incoming messages of type Message<TradeProcessingContext> message:
#Slf4j
public class ExceptionHandler {
#Autowired
private ExceptionDAO exceptionDAO;
#ServiceActivator(inputChannel = DEFAULT_ERROR_CHANNEL)
public void handleTradeError(Message<TradeProcessingContext> message) {
TradeProcessingContext tradeProcessingContext = message.getPayload();
if (tradeProcessingContext != null) {
//store in database
}
}
}
I have handler implementations as follows:
#Slf4j
#MessageEndpoint
public class ChildHandler extends ParentHandler {
#Autowired
private SomeDAO someDAO;
#ServiceActivator(inputChannel = INPUT_CHANNEL, outputChannel = DEFAULT_ERROR_CHANNEL)
public Message<TradeProcessingContext> handle(final Event event) {
return process(event);
}
#Override
protected TradeDAO getDAO() {
return someDAO;
}
}
That invokes the parent process()
public abstract class ParentHandler implements Handler {
#Resource
private SomeService service;
public Message<TradeProcessingContext> process(final Event event) {
TradeProcessingContext tradeProcessingContext = new TradeProcessingContext();
//set initial context
try {
List<Trade> trades = getDAO().findByEventId(event.getEventId());
for (Trade trade : trades) {
tradeProcessingContext.setRef(trade.getRef());
Future<TradeProcessingContext> thread = service.doSomething(trade, tradeProcessingContext);
tradeProcessingContext = thread.get();
}
} catch (Exception e) {
return MessageBuilder.withPayload(tradeProcessingContext).build();
}
return null;
}
I understand I can get org.springframework.messaging.MessageHandlingException: nested exception is java.lang.ClassCastException when the type is Message<MessageHandlingException> message in handleTradeError().
How can i improve this method so that such errors are taken care of also or the underlying tradeprocessingContext is also extracted from this type?
The error channel gets an ErrorMessage which has a Throwable payload. Usually the Throwable is a message handling exception with the original message in the failedMessage property and the exception in the cause.
I create two InvocationHandler, one for logging purpose and the other one for measuring time. Each on works but I do not know how to create a chain of these two, so that both will be executed. I thought it would be enough that for example the LoggingInvocationHandler extends the TimerInvocationHandler
public class DynamicProxyMain {
public static void main(String[] args) {
System.out.println("Starting dynamic proxy sample");
SubjectInterface timerProxy = (SubjectInterface) Proxy.newProxyInstance(SubjectInterface.class.getClassLoader(),
new Class<?>[]{SubjectInterface.class},
new TimerInvocationHandler(new SubjectInterfaceImpl()));
SubjectInterface logginProxy = (SubjectInterface) Proxy.newProxyInstance(SubjectInterface.class.getClassLoader(),
new Class<?>[]{SubjectInterface.class},
new LoggingInvocationHandler(new SubjectInterfaceImpl()));
timerProxy.methodA("a");
timerProxy.methodB("test b");
timerProxy.methodC(1, "test c");
}
}
public class LoggingInvocationHandler implements InvocationHandler {
Object impl;
String CLASSNAME = this.getClass().getCanonicalName();
public LoggingInvocationHandler(Object impl){
this.impl = impl;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object retVal;
System.out.println("LoggingHandler:" + this.getClass().getName() + " has been called");
retVal = method.invoke(impl, args);
System.out.println("LoggingHandler:" + this.getClass().getName() + " has ended");
return retVal;
}
}
public class TimerInvocationHandler extends LoggingInvocationHandler implements InvocationHandler{
private Object impl;
public TimerInvocationHandler(Object impl) {
super(impl);
this.impl = impl;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object retVal = null;
System.out.println("getting duration time for method " + method.getName());
long duration = -System.currentTimeMillis();
retVal = super.invoke(proxy,method,args);
duration += System.currentTimeMillis();
System.out.println("it took " + duration + " milliseconds");
System.out.println("duration time handler has ended");
return retVal;
}
}
Actually I solved it, so that both InvocationHandlers will be called. I edited my post with the currently working code
The idea bears a similarity to Intercepting Filter, I'll give your an implementation of it, which slightly modified in order to work with DynamicProxyHandler, if you're interested and want more details, you should read the link thoroughly.
Participants:
InvocationChain - which is responsible for dispatching invocations.
Invocation - where you should put things like logging and timer.
DynamicProxyHanlder - that simply delegates the request to InvocationChain.
Implementaiton:
DynamicProxyHandler.java
public class DynamicProxyHandler implements InvocationHandler {
private Object proxied;
InvocationChain chain = new InvocationChainImp();
DynamicProxyHandler(Object proxied) {
this.proxied = proxied;
}
#Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return chain.invoke(proxied, method, args);
}
}
Invocation.java
public interface Invocation {
Object invoke(Object callee, Method method, Object[] args, InvocationChain chain);
}
InvocationChain.java
public interface InvocationChain {
public Object invoke(Object callee, Method method, Object[] args);
}
InvocationChainImp.java
public class InvocationChainImp implements InvocationChain {
List<Invocation> list = new ArrayList<>();
Object result;
Iterator<Invocation> tasks;
InvocationChainImp() {
list.add(new LoggingInvocation());
list.add(new TimerInvocation());
list.add(new FinalInvocation());
tasks = list.iterator();
}
#Override
public Object invoke(Object callee, Method method, Object[] args) {
if (tasks.hasNext()) {
Object result = tasks.next().invoke(callee, method, args, this);
this.result = (this.result == null ? result : this.result);
}
return this.result;
}
Last not least, we want to define some custom classes that must be confined to Invocation interface for logging, timer, etc.
LoggingInvocation.java
public class LoggingInvocation implements Invocation {
#Override
public Object invoke(Object callee, Method method, Object[] args, InvocationChain chain) {
chain.invoke(callee, method, args);
Logger.getLogger(this.getClass().getCanonicalName()).info(method.getName() + "() execution logged!");
return null;
}
}
TimerInvocation.java
public class TimerInvocation implements Invocation {
#Override
public Object invoke(Object callee, Method method, Object[] args, InvocationChain chain) {
long start_time = System.nanoTime();
chain.invoke(callee, method, args);
long end_time = System.nanoTime();
System.out.println("Timer: excution took " + (end_time - start_time) / 1e6 + "ms");
return null;
}
}
FinalInvocation.java where the request is finally invoked on the proxied instance.
public class FinalInvocation implements Invocation {
#Override
public Object invoke(Object callee, Method method, Object[] args, InvocationChain chain) {
try {
return method.invoke(callee, args);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
}
Rest of code is trivial, as it's just used to prove that the implementation works.
You can stop reading now if want to write your own.
SubjectInterface.java
public interface SubjectInterface {
String hello();
}
SubjectInterfaceImp.java
public class SubjectInterfaceImp implements SubjectInterface {
#Override
public String hello() {
System.out.println("in SubjectInterfaceImp: Greeting!");
return "hello";
}
}
Main.java
public class Main {
public static void main(String[] args) throws Exception {
SubjectInterface subject = (SubjectInterface) Proxy.newProxyInstance(
SubjectInterface.class.getClassLoader(),
new Class[] { SubjectInterface.class }, new DynamicProxyHandler(new SubjectInterfaceImp()));
System.out.println("in Main: subject.hello() = " + subject.hello());
}
}
Okay, we have enough of code, it's show time, let's see we got, voila!
in SubjectInterfaceImp: Greeting!
Timer: excution took 0.532198ms
九月 02, 2016 12:37:36 下午 LoggingInvocation invoke
信息: hello() execution logged!
in Main: subject.hello() = hello
This is not the natural way to implement it.TimerInvocationHandler has nothing to do with LoggingInvocationHandler.
define a decorator which is a InvocationHandler and wraps a another InovovationHandler
https://en.wikipedia.org/wiki/Decorator_pattern
EDIT: since one comment ask me to provide a sample implementation,following part is added, but this is the not exact decorator pattern, but i think others can understand the solution. in this case TimeInvocationHandler is not limited to measure the login time
public class TimerInvocationHandler implements InvocationHandler
{
protected InvocationHandler invocationHandler;
#Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
{
//do whatever you want
Object result = invocationHandler.invoke(proxy, method, args);
// do what ever you want
return result;
}
}
I am trying to write a unit test for a AWS SWF workflow. Below is the code I would like to Test
#Override
public void execute(String abc) {
new TryCatch() {
#Override
protected void doTry() throws Throwable {
Promise<SomeObject> temp = activityClient.action(abc);
again(temp, abc);
}
#Override
protected void doCatch(Throwable e) throws Throwable {
throw new RuntimeException(e);
}
};
}
#Asynchronous
public void again(Promise<SomeObject> someObject, String abc) {
// Do Something
}
My Test class is as below:
public class SomeWorkflowTest extends AbstractTestCase {
#Rule
public WorkflowTest workflowTest = new WorkflowTest();
List<String> trace;
private SomeWorkflowClientFactory workflowFactory = new SomeWorkflowClientFactoryImpl();
#Before
public void setUp() throws Exception {
trace = new ArrayList<String>();
// Register activity implementation to be used during test run
SomeActivitiesImpl activitiesImpl = new SomeActivitiesImpl() {
#Override
public SomeObject performHostRecovery(String abc) {
trace.add("ABC: " + abc);
SomeObject testObject = new SomeObject();
return testObject;
}
};
workflowTest.addActivitiesImplementation(activitiesImpl);
workflowTest.addWorkflowImplementationType(SomeWorkflowImpl.class);
}
#Test
public void testWorkflowExecutionCall() throws Throwable {
SomeWorkflowClient workflow = workflowFactory.getClient("XZY");
workflow.execute("XYZ");
List<String> expected = new ArrayList<String>();
expected.add("ABC: abc");
AsyncAssert.assertEqualsWaitFor("Wrong Wrong", expected, trace, null);
}
}
I have used SWF Testing Docs to write above test class. However the method that I am testing (execute()) is invoking another method in same class. I am not concerned with the execution of internal method and would like to mock it out, but given the way the workflow class object is instantiated, I am not clear on how to mock the inner method.
Can someone please point out on this?
Thanks
You actually can instantiate a workflow object or any other object that workflow uses inside the test method:
#Test
public void testWorkflowExecutionCall() throws Throwable {
SomeWorkflow workflow = new SimpleWorkflow(...);
workflow.execute("XYZ");
List<String> expected = new ArrayList<String>();
expected.add("ABC: abc");
AsyncAssert.assertEqualsWaitFor("Wrong Wrong", expected, trace, null);
}
It works because WorkflowTest executes test methods in the context of a dummy test workflow. The code
SomeWorkflowClient workflow = workflowFactory.getClient("XZY");
workflow.execute("XYZ");
actually creates a child workflow in the context of this dummy workflow. But nothing prevents you from executing any async code directly without creating the child workflow.
this question was asked many times but I couldn't find elegant workaround for it.
This example works as desired:
public class RequestWrapper<T> {
private final T request;
private final Class<T> type;
public RequestWrapper(T request, Class<T> type) {
this.request = request;
this.type = type;
}
public T getRequest() {
return request;
}
public Class<T> getType() {
return type;
}
}
public class Service {
private void invoke(String request) {
System.out.println("String:" + request);
}
private void invoke(Object request) {
System.out.println("Object:" + request + "," + request.getClass().getSimpleName());
}
public static void main(String[] args) {
RequestWrapper<String> sw = new RequestWrapper<String>("A", String.class);
RequestWrapper<Integer> iw = new RequestWrapper<Integer>(Integer.valueOf(0), Integer.class);
new Service().invoke(sw.getRequest());
new Service().invoke(iw.getRequest());
}
}
But I would need to add one more method to Service class which do something before/after call of invoke method:
public void invoke(RequestWrapper<?> wrapper) {
try {
// ...
invoke(wrapper.getType().cast(wrapper.getRequest()));
invoke(wrapper.getRequest());
} catch(Exception e ) {
// ...
}
}
then the main method would contain:
new Service().invoke(sw);
I understand the reason why the invoke(Object request) is used instead of invoke(String request).
What would be an elegant solution to call proper invoke method and be able to do some common actions before/after it?
To have an interface e.g. Invoker, implement it e.g. StringInvoker, Invoker> and call map.get(wrapper.getType()).invoke(wrapper.getRequest()) is possible solution but I expect something better.
You can check the type and explicitly cast it, for example (I also added Integer so you can see branching on more types):
Class<?> c = wrapper.getType();
if (c == String.class)
invoke((String) wrapper.getRequest()); // Invokes invoke(String)
else if (c == Integer.class)
invoke((Integer) wrapper.getRequest()); // Invokes invoke(Integer)
else
invoke(wrapper.getRequest()); // Invokes invoke(Object)
Note:
If you go on this path, you don't even need to store the request type in the RequestWrapper class because you can just as easily use the instanceof operator on the request itself to check its type. And if you "get rid" of the request type, your current RequestWrapper class will only contain the request so the RequestWrapper is not even needed in this case.
Visitor patter can serves to solve it. Only drawback is that there isn't possible to write:
new Service().invoke(new RequestWrapper<String>("A"));
My implementation:
public class Service {
public void invoke(RequestWrapper<?> wrapper) {
try {
// ...
wrapper.invoke(this);
} catch(Exception e ) {
// ...
}
}
public void invoke(String request) {
System.out.println("String:" + request);
}
public void invoke(Boolean request) {
System.out.println("Boolean:" + request);
}
public static void main(String[] args) {
RequestWrapper<Boolean> rw = new BooleanRequestWrapper(Boolean.TRUE);
new Service().invoke(rw);
}
}
abstract class RequestWrapper<T> {
protected final T request;
public RequestWrapper(T request) {
this.request = request;
}
public abstract void invoke(Service v);
}
class BooleanRequestWrapper extends RequestWrapper<Boolean> {
public BooleanRequestWrapper(Boolean request) {
super(request);
}
public void invoke(Service service) {
service.invoke(request);
}
}