WARNING: The (sub)resource method contains empty path annotation - java

I have configured rest path like "/v1/" and the endpoint configured in servlet like '/test/'.
Now I removed the "/v1" from the java class "Test".
org.glassfish.jersey.internal.Errors logErrors
WARNING: The following warnings have been detected: WARNING: The (sub)resource method test in com.abc.services.Test contains empty path annotation.
I got the above warning after make this change. How to handle this warning?
And I want this "/v1" removing changes for across 10 rest paths. So anyone help me to run without warnings?

The warning means you have a resource method annotated with #Path("/") or #Path(""). For instance
#Path("test")
public class Test {
#GET
#Path("/")
public String test(){}
}
Not sure why Jersey would give a warning, maybe just to make sure that's what you really want. The reason is that a resource method with #Path("/") is redundant, as it's already implied if you were just to do
#Path("test")
public class Test {
#GET
public String test(){}
}
without the #Path("/"). It works the same. So if you have these, remove them, and it should take away the warnings.

Related

Binary/Qualified name is wrong? Begins with: <any?>$

I am running an annotation processor that I have wrote. It ran fine on JDK 8 and now I am experiencing a problem on JDK 12.
I have a TypeElement and I want to retrieve its binary name to pass to Class.forName.
I use javax.lang.model.util.Elements.getBinaryName(TypeElement) and it returns a garbage value <any?>$OuterClass.InnerClass instead of the expected example3.OuterClass$InnerClass.
I attempted to replace getBinaryName with TypeElement.getQualifiedName (even though it would not quite work for an inner class) but it gives me the same garbage result. I have tried searching for this issue but most search engines strip all the special characters and give me useless results.
The TypeElement was obtained by catching a MirroredTypeException like so:
try {
exampleAnnotation.value();
throw new IllegalStateException("Expected a MirroredTypeException.");
} catch (MirroredTypeException ex) {
return (TypeElement) types.asElement(ex.getTypeMirror());
}
And here is the definition of ExampleAnnotation:
package example1;
#Target(PACKAGE)
#Retention(RUNTIME)
#Documented
public #interface ExampleAnnotation {
Class<? extends Derived> value() default Derived.class;
interface Derived<A extends Annotation> extends Base<A> {
String foo();
}
}
And here is the instance of the annotation that the processor is accessing in package-info.java:
#ExampleAnnotation(OuterClass.InnerClass.class)
package example2;
import example1.ExampleAnnotation;
I have also tried the fully qualified name example3.OuterClass.InnerClass.class but that also results in garbage: <any?>$example3.OuterClass.InnerClass.
I doubt it matters but the annotation processors are still marked #SupportedSourceVersion(SourceVersion.RELEASE_8) and I am running this on Gradle 5.3.1.
I've verified the processorpath contains the jars for packages example1 and example3, including the annotation processors.
I've made no changes to account for the module system so I was thinking maybe that's somehow affecting the code.
Just tried creating a Maven project and am currently unable to reproduce the problem, so there may be an issue with my Gradle configuration, similar to what #Colin Alworth has suggested.
I had recently upgraded to a new version of Gradle and started using the "annotationProcessor" dependencies.
It appears that <any?>$ is prepended to binary/qualified class names (as it appears in the source) if the class isn't on the classpath (or if it isn't imported, or is spelled wrong). I only had the annotation's jar on the processorpath.
To alert consumers of my annotation processor of this mistake, I was able to detect it by comparing TypeElement.asType().getKind() == TypeKind.ERROR immediately after catching the MirroredTypeException.

Spring AOP - Point Cut not getting called

I have a SpringBoot Application.
I have defined an Annotation say "Track", and I have annotated few methods in different packages which I want aop to consider.
The annotation has been defined as below :
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.METHOD)
public #interface Track {
}
I have not missed the #EnableAspectJAutoProxy in the #Configuration class of my package.
I have a Pointcut and an Advice defined in the Aspect like below :
#Aspect
#Component
public class MyAspect {
#Pointcut("execution(#Track * *.*(..))")
void annotatedMethod() {
// No Implementation required
}
#Around("annotatedMethod() && #annotation(methodLevelTrack)")
public void adviseAnnotatedMethods(ProceedingJoinPoint proceedingJoinPoint,
Track methodLevelTrack) throws Throwable {
// do some task
proceedingJoinPoint.proceed();
// do some task after the method is executed.
}
}
My intention is: for any method (annotated with #Track) in any package, with any access modifier, and any number of input arguments, and any return type, to follow the aspect's #Around advice.
Now, the interesting situation is as below :
I have a class say "Engine" which calls other classes and downstream systems to perform a long-running operation. Let's define the class as follows :
public class Engine {
// bunch of other autowired objects
public void processTask() {
<autowired_object_A>.someMethod() // this method has been annotated with #Track
<autowired_object_B>.someMethod() // this method has also been annotated with # Track
.... // bunch of other methods in other autowired objects that have been annotated with # Track
someMethodOfEngineClass(); // Now this has been defined in the Engine class as below, but pointcut doesn't recognize this method!
}
#Track
private void someMethodOfEngineClass() {
// do something
}
}
All the "other" autowired objects' methods are getting recognized by pointcut as expected but the method within this Engine class, that has been annotated with #Track, is not recognized. What's the mystery?
I have tried making "someMethodOfEngineClass" method public, return something instead of void and all those combinations and it doesn't work.
What am I missing?
Is it the pointcut definition expression?
I have defined the aspect in one of the sub packages, is aspect supposed to be defined at the top level in the package structure?
Can you folks please suggest something that can work? I am kinda stuck at this.
When you define aop spring creates proxy around the class,
so when the method is called, actually call is delegated to proxy, sth like
your.package.Engine$$FastClassBySpringCGLIB$$c82923b4.someMethodOfEngineClass()
But this works only when a method is called from outside it's class
If you call class method from the same class you are effectively calling it by this.someMethodOfEngineClass()
here -> http://www.nurkiewicz.com/2011/10/spring-pitfalls-proxying.html
you can find more info about proxying
so proxy is bypassed and aop is not working.

SonarQube: Create custom rules to get custom annotations in a class

I'm trying to create a custom SonarQube rule which will detect the usage of a specific custom Java Annotation. Here is the code I found which prints a list of all annotations used in a class.
public class SampleAnnotationCheck extends IssuableSubscriptionVisitor {
#Override
public List<Tree.Kind> nodesToVisit() {
return ImmutableList.of(Tree.Kind.METHOD);
}
#Override
public void visitNode(Tree tree) {
MethodTree methodTree = (MethodTree) tree;
for (AnnotationInstance ai : ((JavaSymbol.MethodJavaSymbol) methodTree.symbol()).metadata().annotations()) {
System.out.println(ai.symbol().name());
}
}
}
Sample Java File:
#GET
#Path(values)
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
method1(...) {...}
#CustomAnnotation(values)
#POST
#Path(values)
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
method2(...) {...}
#PATCH
#Path(values)
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
method3(...) {...}
Expected Output:
GET
Path
Consumes
Produces
CustomAnnotation
POST
Path
Consumes
Produces
PATCH
Path
Consumes
Produces
Actual Output:
GET
Path
Consumes
Produces
!unknownSymbol!
POST
Path
Consumes
Produces
!unknownSymbol!
Path
Consumes
Produces
I'm getting !unknownSymbol! instead of the Custom Annotations' actual names. One of the custom annotations is io.swagger.jaxrs.PATCH.
The other annotation is defined inside a separate package and imported by the sample class.
Do we have to register these custom annotations somewhere for the API to detect?
Please suggest what changes should be made so that we can detect and print the actual Custom Annotation's name.
Thanks in advance!
I assume you are following this guide and running check within your tests https://docs.sonarqube.org/display/PLUG/Writing+Custom+Java+Rules+101 . To provide dependencies to your tests you can either
put jars in target/test-jars directory (see how to do it with maven dependency plugin here https://github.com/SonarSource/sonar-custom-rules-examples/blob/master/java-custom-rules/pom.xml#L147)
in your test provide custom classpath using JavaCheckVerifier.verify(filename, check, classpath)

StrutsTestCase implementation - Compilation error

I am using Struts 2 to create a web application. I am using StrutsTestCase for Junit test case to test the Action class. I have imported struts2-junit-plugin-2.3.4.jar as I am using struts2-core-2.3.4.jar. Inside the testcase method, when i tried to set the request parameters, request variable is not available for use. it is showing compilation error. I am getting 'request cannot be resolve' error. In my test class i am extending StrutsTestCase which has request as protected parameter. But it is not available inside extended method.
My test action looks like this:
import org.apache.struts2.StrutsTestCase;
public class WallPlanningActionTest extends StrutsTestCase {
public void testList() {
request.setParameter("salesOrg",1);
}
You can only get compilation errors if StrutsTestCase which your class is extended is not org.apache.struts2.StrutsTestCase. You could optimize the imports or just use FQCN.
public class WallPlanningActionTest extends org.apache.struts2.StrutsTestCase {
For future readers:
I had the same problem - the protected request field was not accessible. The problem was that i hadn't add the spring libraries. StrutsTestCase uses spring-core-x.y.z and spring-test-x.y.z. It is depended on them an i couldn't find a way to use the unit tests without them.
Other dependencies could be found by opening the struts-junit-plugin jar (as archive). Open the META-INF folder and in there you will find DEPENDENCIES file with a list of all dependencies.
Hope this helps someone.

Understanding annotation in Java

I was trying to go through some online material to learn annotation in java.
In the following code, what happened to my dear "Hello world" string which I passed in this line: #Test_Target(doTestTarget="Hello World !")?
#Target(ElementType.METHOD)
public #interface Test_Target {
public String doTestTarget();
}
above is the annotation defined and below is its usage
public class TestAnnotations {
#Test_Target(doTestTarget="Hello World !")
private String str;
public static void main(String arg[]) {
new TestAnnotations().doTestTarget();
}
public void doTestTarget() {
System.out.printf("Testing Target annotation");
}
}
When I run this code it is only printing Testing Target annotation
Please help me out, I am completely new to annotation.
Annotations are basically bits of data you can attach to fields, methods, classes, etc.
The syntax for declaring annotations in Java is a little awkward. They look a bit like interfaces (they are, after all, declared with #interface), but they aren't really interfaces. I think you might have put the doTestTarget() method in your TestAnnotations class because you thought your annotation was an interface and you needed to implement it. This isn't true - you can delete this method and the call to it from your code if you wish and doing so won't cause you any problems.
Also, you might not have intended to put the annotation on the field str. Annotations apply only to what immediately follows them. As a result, your code doesn't compile, because you've applied your annotation to a field but declared that your annotation can only be applied to methods. Change #Target(ElementType.METHOD) to #Target(ElementType.FIELD) and your code should then compile.
As for what happens to the string Hello World !, it gets written to the .class file and is available to any tool that reads in Java classes. However, it wouldn't necessarily be available in the JVM at runtime. This happens because you didn't specify a #Retention for your #Test_Target annotation. The default value for #Retention is RetentionPolicy.CLASS, which means that the JVM might not bother to load them out of the class file. (See the Javadoc for the RetentionPolicy enum.)
I imagine you want to see some way of reading the value out of this annotation at runtime. If so, I'd recommend adding #Retention(RetentionPolicy.RUNTIME) to your annotation to make sure it will be available at runtime.
To access your annotation and the value contained within it at runtime, you need to use reflection. I've rewritten your TestAnnotations class as follows to give a quick demonstration:
import java.lang.reflect.Field;
public class TestAnnotations {
#Test_Target(doTestTarget="Hello World !")
private String str;
public static void main(String[] args) throws Exception {
// We need to use getDeclaredField here since the field is private.
Field field = TestAnnotations.class.getDeclaredField("str");
Test_Target ann = field.getAnnotation(Test_Target.class);
if (ann != null) {
System.out.println(ann.doTestTarget());
}
}
}
When I run this code, it gives me the following output:
Hello World !
In principle, adding an annotation by itself does not fundamentally alter the programs behaviour.
In your case, you created a new annotation type #Test_Target, which can by used on any method (as indicated by its #Target annotation).
Then you applied this not to a method, but to the str field (which should give a compiler error, I think).
Independently of this, you are creating an object with a doTestTarget method, and invoke it, and get the expected result (i.e. the method is executed).
If you want your annotation to do something more than simply be there and provide some information for the reader of the source, you have to use it - either with an annotation processor at compile time, or using reflection on run time (then you would need also #Retention(RUNTIME) as an annotation on Test_Target.)
In the spirit of learning, another way is to use the annotated class without targeting a method or field.
First declare your interface with the method you need and Retention Policy to Runtime
import java.lang.annotation.*;
#Retention(RetentionPolicy.RUNTIME)
public #interface Test_Target {
public String doTestTarget() default "default string";
}
then annotate the interface created to your class. From your class find the annotated class and then call the method with it.
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
#Test_Target(doTestTarget="Hello World !")
public class TestAnnotations {
public static void main(String[] args) throws Exception
{
AnnotatedElement c = TestAnnotations.class;
if(c.isAnnotationPresent(Test_Target.class))
{
Annotation singleAnnotation = c.getAnnotation(Test_Target.class);
Test_Target tt = (Test_Target) singleAnnotation;
System.out.println(tt.doTestTarget());
}
}
}
the result is:
Hello World !

Categories