Java annotation capturing with reflection will not work when execuete jacoco prepare agent

1.8k views Asked by At

I have a multi module maven project. This has set of classes generated by jaxb using xsd. Example of such class is given below. (Without getters and setters)

@XmlRootElement(name = "IPPAMUser")
public class IPPAMUser {

@XmlElement(name = "UserName", required = true)
protected String userName;
@XmlElement(name = "PAMInstanceID", required = true)
protected String pamInstanceID;
@XmlElement(name = "Product", required = true)
protected String product;
@XmlElement(name = "Password", required = true)
protected String password;
@XmlElement(name = "PasswordAlogo", required = true)
protected String passwordAlogo;
@XmlElement(name = "LastUpdatedOn", required = true)
protected String lastUpdatedOn;
@XmlElement(name = "IsGenerated")
protected boolean isGenerated;
@XmlElement(name = "LastNotifiedOn", required = true)
protected String lastNotifiedOn;
}

One module needs them as a key value pair. So one method has written with reflection to convert them to a list of key value pair. In that name of the field is used as key and value as its value. It is taken as following.

Field[] fields = t.getClass().getDeclaredFields();
    for(Field field : fields) {
        Annotation anotation = field.getAnnotation(XmlElement.class);
        XmlElement xmlElement = (XmlElement) anotation;

        String methodName;
        String parameterValue = "";
        if(field.getType() == boolean.class){
            methodName = "is" + xmlElement.name();
        } else {
            methodName = "get" + xmlElement.name();
        }
        try {
            Method method = t.getClass().getDeclaredMethod(methodName);
            if(method.invoke(t) == null){
                continue;
            }
            parameterValue = method.invoke(t).toString();
        } catch (NoSuchMethodException e) {
            log.error("Method not found. Method : " + methodName, e);
            log.error("Stack trace : {}", AuthUtils.getPrintableStackTrace(e));
        } catch (InvocationTargetException e) {
            log.error("Method invoking failed. Method : " + methodName, e);
            log.error("Stack trace : {}", AuthUtils.getPrintableStackTrace(e));
        } catch (IllegalAccessException e) {
            log.error("Illegal access " + e);
            log.error("Stack trace : {}", AuthUtils.getPrintableStackTrace(e));
        }
  }

There are some test cases that use this conversion. They work fine and execute with maven build. To take code coverage, jacoco-maven-plugin is added. When running it is not generating jacoco.exec file. According to this post execution goals are added to my pom file. After that my unit tests get failed giving an null pointer exception. According to stack trace it is caused when executing "xmlElement.name()", Which means xmlElement is null. So reflection can't get annotation after this execution goal adding.

How can i resolve this problem and get code coverage report using jacoco or any other means.

Thanks in advance.

1

There are 1 answers

0
Tharindu Ranasingha On BEST ANSWER

I figure out solution myself. When jacoco prepare agent it include some synthetic fields to classes. So when it try to get it that synthetic field which does not have desired annotation is included in fields list.

As a best practice within reflection check isSynthetic() for each field you access. This will avoid you from accessing fields added by compiler as well as tools like jacoco. Refer these link for more references.

synthetic field Jacoco synthetic field