Suppose I am initializing bean with the following code:
#Configuration
MyConfig {
#Bean
#MyAnnotation // how to know this from bean constructor or method?
MyBean myBean() {
MyBean ans = new MyBean();
/// setup ans
return ans;
}
}
Can I know from withing bean constructor or from withing bean's methods something about #MyAnnotation annotation?
Not from within myBean() method, which is obvious.
Well it's probably not the best or even correct way, but my first guess is to use current stack trace and it seems to work for me:
package yourpackage;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class AspectJRawTest {
public static void main(String[] args) {
System.out.println("custom annotation playground");
ISomething something = new SomethingImpl();
something.annotatedMethod();
something.notAnnotatedMethod();
}
}
interface ISomething {
void annotatedMethod();
void notAnnotatedMethod();
}
class SomethingImpl implements ISomething {
#MyCustomAnnotation
public void annotatedMethod() {
System.out.println("I am annotated and something must be printed by an advice above.");
CalledFromAnnotatedMethod ca = new CalledFromAnnotatedMethod();
}
public void notAnnotatedMethod() {
System.out.println("I am not annotated and I will not get any special treatment.");
CalledFromAnnotatedMethod ca = new CalledFromAnnotatedMethod();
}
}
/**
* Imagine this is your bean which needs to know if any annotations affected it's construction
*/
class CalledFromAnnotatedMethod {
CalledFromAnnotatedMethod() {
List<Annotation> ants = new ArrayList<Annotation>();
for (StackTraceElement elt : Thread.currentThread().getStackTrace()) {
try {
Method m = Class.forName(elt.getClassName()).getMethod(elt.getMethodName());
ants.addAll(Arrays.asList(m.getAnnotations()));
} catch (ClassNotFoundException ignored) {
} catch (NoSuchMethodException ignored) {
}
}
System.out.println(ants);
}
}
Output clearly shows that I got an access to my annotation within object's constructor when it was called from annotated method:
custom annotation playground
I am annotated and something must be printed by an advice above.
[#yourpackage.MyCustomAnnotation(isRun=true)]
I am not annotated and I will not get any special treatment.
[]
Related
(Update: After I reported this, the TestNG team confirmed the bug.)
Normally, ignoring a class can be done with #Ignore or enabled=false
This does not work on a subclass where test methods are defined in its superclass (and where the subclass defines its specific functionality in hook methods). See ChildClassTest below.
Note that #Ignore is specific to JUnit whereas TestNG uses enabled.
Base class
import org.testng.annotations.Test;
public class ParentClassTest {
#Test
public void test1() {
hook();
}
protected void hook() {};
}
Child class
import org.testng.Reporter;
import org.testng.annotations.Ignore;
#Ignore
public class ChildClassTest extends ParentClassTest {
#Override
protected void hook() {
Reporter.log("ChildClassTest#hook()");
}
}
Been doing some brainstorming out of curiosity, and came up with the workarounds below tested with v6.14.2. I personally prefer the first one, being cleaner, more elegant, flexible and easier to maintain and extend.
context
import org.testng.annotations.Test;
import static org.testng.Assert.assertTrue;
public class MyTest {
#Test
public void shouldRun() {
assertTrue(true);
}
#Test
public void shouldNotRun() {
assertTrue(true);
}
#Test
public void shouldNotRunEither() {
assertTrue(true);
}
}
1) Using listeners - create a TestListenerAdapter & annotation to skip methods with certain names: flexible, clear, easy to reuse and identify for removal. The only downside is that you have to pay attention to method names for typos.
Annotation
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
#Retention(RetentionPolicy.RUNTIME)
#Target({ElementType.TYPE})
public #interface SkipMethods {
String[] value() default {};
}
TestListenerAdapter
import org.testng.ITestResult;
import org.testng.SkipException;
import org.testng.TestListenerAdapter;
public class TestSkippingListener extends TestListenerAdapter {
#Override
public void onTestStart(ITestResult result) {
// get the skip annotation
SkipMethods skipAnnotation = result.getMethod().getInstance().getClass().getAnnotation(SkipMethods.class);
// if the annotation exists
if (skipAnnotation != null) {
for (String skippableMethod : skipAnnotation.value()) {
// and defines the current method as skippable
if (skippableMethod.equals(result.getMethod().getMethodName())) {
// skip it
throw new SkipException("Method [" + skippableMethod + "] marked for skipping");
}
}
}
}
}
Test Subclass
import org.testng.annotations.Listeners;
// use listener
#Listeners(TestSkippingListener.class)
// define what methods to skip
#SkipMethods({"shouldNotRun", "shouldNotRunEither"})
public class MyTestSkippingInheritedMethods extends MyTest {
}
Result
2) Override methods from superclass and throw SkipException: pretty clear, no possibility of typo, but not reusable, not easily maintainable & introduces useless code:
import org.testng.SkipException;
public class MyTestSkippingInheritedMethods extends MyTest {
#Override
public void shouldNotRun() {
throw new SkipException("Skipped");
}
#Override
public void shouldNotRunEither() {
throw new SkipException("Skipped");
}
}
Result
I want to get the result of a method and then enqueue them into ActiveMQ. Hence, I decided to create an annotation(say #Enqueue("My_Queue")) that gets the result and send it to My_Queue.
#ResponseBody
#Enqueue("My_Queue")
#RequestMapping("/list")
public MyClass list() {
return myService.getAll();
}
And here is the annotation itself:
#Target(value = ElementType.METHOD)
#Retention(RetentionPolicy.RUNTIME)
public #interface Enqueue {
/**
* The Name Of The Queue
*/
String value() default "General_Message_Queue";
}
So What should I do to create such an annotation(A-Z please)?
Aspects must be what your looking for. Since you're using Spring, have a look as Spring AOP: http://docs.spring.io/spring/docs/current/spring-framework-reference/html/aop.html.
With the advice #AfterReturning and the pointcut #annotation(package.to.Enqueue), you'll be able to access the returned value each time a method annotated with #Enqueue is called: http://docs.spring.io/spring/docs/current/spring-framework-reference/html/aop.html#aop-advice-after-returning.
You'll then be able to send it to the queue.
You need to write below code snap.
Class aClass = MyClass.class;
Annotation[] annotations = aClass.getAnnotations();
for(Annotation annotation : annotations){
if(annotation instanceof Enqueue ){
Enqueue myAnnotation = (Enqueue ) annotation;
if(myAnnotation.name().equals("Enqueue")){
//do your work
System.out.println("value: " + myAnnotation.value());
}
}
}
Update :
Annotations are not "triggered"... you have to write code that looks for their presence and takes action.
The "code" can either be executed at runtime, but is more commonly executed at compile time using the Annotation Processing Tool to alter the source to inject extra, typically cross-cutting, code appropriate for the annotation.
Reference link : https://stackoverflow.com/a/13040933/1326692
Update : By seeing your comments it seems that you want something by which dynamically you can do your stuff before your annotation method call. For this you need to create proxy like given below.
1: MyInterface.java
public interface MyInterface {
void test();
}
2: Enqueue.java
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
#Target(ElementType.METHOD)
#Retention(RetentionPolicy.RUNTIME)
public #interface Enqueue {
public String value() default "General_Message_Queue";
}
3. MyClass.java
import java.lang.reflect.Proxy;
public class MyClass implements MyInterface {
#Enqueue
public void test() {
System.out.println("Inside test");
}
public static void main(String[] args) throws IllegalArgumentException, InstantiationException, IllegalAccessException {
MyInterface test = (MyInterface) getProxyInstance(MyClass.class, MyInterface.class);
test.test();
}
#SuppressWarnings("rawtypes")
public static Object getProxyInstance(Class clazz, Class interfaze) throws IllegalArgumentException,
InstantiationException, IllegalAccessException {
Object proxy =
Proxy.newProxyInstance(MethodInvocationHandler.class.getClassLoader(),
new Class[] {interfaze}, new MethodInvocationHandler(clazz.newInstance()));
return proxy;
}
}
4: MethodInvocationHandler.java
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class MethodInvocationHandler implements InvocationHandler {
private Object proxied;
public MethodInvocationHandler(Object proxied) {
this.proxied = proxied;
}
#Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Method m = proxied.getClass().getMethod(method.getName(), method.getParameterTypes());
if (m.isAnnotationPresent(Enqueue.class)) {
// do your work here
System.out.println("Before " + m.getName() + " call..!");
/** also you can get annotation and access it's properties..! */
Enqueue annotation = m.getAnnotation(Enqueue.class);
System.out.println("name: " + annotation.value());
}
/** also you can get all the annotations if you want */
Annotation[] annotations = method.getDeclaredAnnotations();
for (Annotation annotation : annotations) {
// do your annotation specific work here like this,
if (annotation instanceof Enqueue) {
// do your work here.
}
}
return method.invoke(proxied, args);
}
}
I hope it helps :)
If you are using spring-aop or any third party aop library then you can apply below code.
import java.util.ArrayList;
import java.util.Collection;
import org.apache.log4j.Logger;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
#Aspect
#Component
public class EnqueueServiceMonitor {
private static final Logger LOGGER = Logger
.getLogger(EnqueueServiceMonitor.class);
public EnqueueServiceMonitor() {
}
#AfterReturning(value = "#annotation(com.enqeue.annotation.Enqueue) && args(myClass,..)")
public void doProcess(MyClass myClass,
Exception ex) {
//do the code here. This method will call every time whenever your MyClass.list() method will be called.
//Or other method which have this annotation and return myClass object.
}
}
#ResponseBody
#Enqueue("My_Queue")
#RequestMapping("/list")
public MyClass list() {
return myService.getAll();
}
If your method have different return type then you have to write more aop advice for specific return type.
When I get method from class instance, and want to get #override annotation.
but method has not any annotation.
Is it impossible to get #override annotation?
code is below.
package com.test;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import javax.annotation.Resource;
public class ReflectionTest {
public static void main(String[] args) throws Exception {
ChildHoge childHoge = new ChildHoge();
Method method = childHoge.getClass().getMethod("init");
for (Annotation s : method.getAnnotations()) {
System.out.println(s);
}
Method method2 = childHoge.getClass().getMethod("a");
for (Annotation a : method2.getAnnotations()) {
System.out.println(a); // =>#javax.annotation.Resource(mappedName=, shareable=true, type=class java.lang.Object, authenticationType=CONTAINER, lookup=, description=, name=)
}
}
}
class SuperHoge {
public void init() {
}
}
class ChildHoge extends SuperHoge {
#Override
public void init() {
super.init();
}
#Resource
public void a() {
}
}
#Retention(RetentionPolicy.SOURCE)
public #interface Override {
}
It has RetentionPolicy.SOURCE which are discarded by the compiler, which means it cannot be obtained at runtime. You can see this described in JLS 9.6.4.2.
If an annotation a corresponds to a type T, and T has a
(meta-)annotation m that corresponds to
java.lang.annotation.Retention, then:
If m has an element whose value is
java.lang.annotation.RetentionPolicy.SOURCE, then a Java compiler must
ensure that a is not present in the binary representation of the class
or interface in which a appears.
And the Javadoc for RetentionPolicy also describes this:
public enum RetentionPolicy {
/**
* Annotations are to be discarded by the compiler.
*/
SOURCE,
...
You can use Reflection API to check if the method is overridden or not
e.g.
class.getMethod("myMethod").getDeclaringClass();
If the class that's returned is your own, then it's not overridden; if it's something else, that subclass has overridden it.
I want to test this class which calls a method of interface using anonymous class.
public class ClassToTest
{
public void methodToTest()
{
InterefaceToMock interefaceToMockReference = new InterefaceToMock() {
#Override
public int methodToMock()
{
return 0;
}
};
interefaceToMockReference.methodToMock();
}
}
This is the interface
public interface InterefaceToMock
{
public int methodToMock();
}
I am using this approch to check it methodToMock is called or not
import static org.junit.Assert.*;
import org.junit.Test;
import mockit.FullVerificationsInOrder;
import mockit.Mocked;
import mockit.NonStrictExpectations;
public class TestAClass
{
#Mocked InterefaceToMock interefaceToMockReferenceMocked;
#Test
public void test1()
{
new NonStrictExpectations()
{
{
interefaceToMockReferenceMocked.methodToMock();times=1;
}
};
(new ClassToTest()).methodToTest();
new FullVerificationsInOrder(interefaceToMockReferenceMocked)
{
};
assertTrue(true);
}
}
But test case fails.
Can anyone help.
Your original test was almost correct. It declared the mock field as simply being #Mocked, which merely gives you a single mocked instance implementing the interface, and this is not the one used by the code under test. The JMockit API has another mocking annotation, however, which extends mocking to all implementation classes from a given base type, and by default affects all instances of said classes. So, the test should be changed as follows:
public class TestAClass
{
#Capturing InterfaceToMock anyImplementingInstance;
#Test
public void test1()
{
new ClassToTest().methodToTest();
new Verifications() {{
anyImplementingInstance.methodToMock();
}};
}
}
In the general case, if you have an class and you want to check whether a method on a Mock of that class is called, you use Mockito.verify.
For example:
public class AppTest {
#Test
public void testMe() {
final ITest iTest = Mockito.mock(ITest.class);
final CUT cut = new CUT(iTest);
cut.doStuff();
Mockito.verify(iTest).someStuff();
}
interface ITest {
void someStuff();
}
class CUT {
private final ITest iTest;
CUT(ITest iTest) {
this.iTest = iTest;
}
public void doStuff() {
iTest.someStuff();
}
}
}
Here, the test is whether ITest.someStuff() is called from CUT.doStuff().
Your example is undecipherable...
Hi I'm having a hard time mapping an abstract nested property's fields. Here I have the test case that explains it better:
package com.mycompany.asd;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import ma.glasnost.orika.MapperFactory;
import ma.glasnost.orika.MappingException;
import ma.glasnost.orika.impl.DefaultMapperFactory;
/**
* Tests the mapping of abstract nested property's fields
*/
public class OrikaTest {
private MapperFactory mapperFactory;
#Before
public void createMapperFactoryAndDefineMapping() {
mapperFactory = new DefaultMapperFactory.Builder()
.useAutoMapping(false).build();
mapperFactory.classMap(FakeBeanA.class, FakeBeanB.class)
.field("fieldA", "fieldB.nestedField")
.field("fieldA2", "fieldB.nestedField2") // Problem here.
.register();
}
#Test(expected = MappingException.class)
public void cannotMapAbstractNestedPropertyWhenConcreteTypeIsNotRegistered() {
// We expect to get a MappingException. Indeed, Orika doesn't know how
// to create an
// instance of AbstractNestedField (the type of FakeBeanB.fieldB)
createAnInstanceOfFakeBeanAAndMapItToFakeBeanB();
}
#Test
public void mapAbstractNestedPropertyWhenConcreteTypeIsRegistered() {
// Register concrete type for AbstractNestedType
mapperFactory.registerConcreteType(AbstractNestedType.class,
NestedType.class);
// Orika should be able to create an instance of FieldB abstract type
// (as we have explicitly defined above the concrete type to create and
// the SimpleConstructorResolverStrategy is normally able to create an
// instance of this concrete type)
// Therefore, the mapping should work !
createAnInstanceOfFakeBeanAAndMapItToFakeBeanB();
}
private void createAnInstanceOfFakeBeanAAndMapItToFakeBeanB() {
// Create an instance of FakeBeanA and assign a value to its fieldA
FakeBeanA fakeBeanA = new FakeBeanA();
fakeBeanA.fieldA = 42;
// Try the mapping from fakeBeanA to FakeBeanB
FakeBeanB fakeBeanB = mapperFactory.getMapperFacade().map(fakeBeanA,
FakeBeanB.class);
// Assert the fieldA has been correctly mapped to fieldB.nestedField
Assert.assertEquals(fakeBeanA.fieldA, fakeBeanB.fieldB.nestedField);
}
public static class FakeBeanA {
public int fieldA;
public int fieldA2;
}
public static class FakeBeanB {
public AbstractNestedType fieldB;
}
public static class NestedType extends AbstractNestedType {
public int nestedField2; // NEW ADDED
}
public static abstract class AbstractNestedType {
public int nestedField;
}
}
This is not possible, and does not make sense, what if there is another subclass of AbstractNestedType that does not have nestedField2 ?
What you can do is to use
.customize(new CustomMapper<> {
void mapBToA(FakeBeanA a, FakeBeanB b) {
if(b.fieldB instanceof NestedType) {
a.fieldA2 = ((NestedType)b.fieldB).nestedField2;
}
}});
...