Cucumber.runtime.CucumberException: Annotations differs on glue classes found - spring-boot

When I want to run Features scenario of cucumber, I faced following exception:
Caused by: Cucumber.runtime.CucumberException: Annotations differs on glue classes found

The problem occurs because all testStep classes should have same count of annotations as following :
Check number of annotation in all TestStep classes that should be same
private void checkAnnotationsEqual(Class<?> stepClassWithSpringContext, Class<?> stepClass) {
Annotation[] annotations1 = stepClassWithSpringContext.getAnnotations();
Annotation[] annotations2 = stepClass.getAnnotations();
if (annotations1.length != annotations2.length) {
throw new CucumberException("Annotations differs on glue classes found: " + stepClassWithSpringContext.getName() + ", " + stepClass.getName());
} else {

Related

error is prompted when I use #target in spring aop

I find the same question in there but didn`t find a useful answer, so I support more details. My code is the following.
#Target(ElementType.TYPE)
#Retention(RetentionPolicy.RUNTIME)
public #interface DS {
String value();
}
public class AnnotationAspect {
#Around("#target(com.yh.application.DS)")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
String dsName = getDataSourceAnnotation(joinPoint).value();
System.out.println("enter in aspect:" + dsName);
return joinPoint.proceed();
}
here is a demo,
just run the application you can see the error stack trace
Unable to proxy interface-implementing method
[public final void org.springframework.boot.web.servlet.RegistrationBean.onStartup
(javax.servlet.ServletContext) throws javax.servlet.ServletException]
because it is marked as final: Consider using interface-based JDK proxies instead!
seems I need to change the aop proxy type to JDK, but when I did this, another error is prompted.
The bean 'dispatcherServlet' could not be injected as a 'org.springframework.web.servlet.DispatcherServlet' because it is a JDK dynamic proxy
Does anyone help me? thank you!
R.G's solution is correct, you ought to limit the pointcut scope. BTW, looking at your aspect code, I noticed this contrived way of getting the annotation value:
private DS getDataSourceAnnotation(ProceedingJoinPoint joinPoint) {
Class<?> targetClass = joinPoint.getTarget().getClass();
DS dsAnnotation = targetClass.getAnnotation(DS.class);
if (Objects.nonNull(dsAnnotation)) {
return dsAnnotation;
}
else {
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
return methodSignature.getMethod().getAnnotation(DS.class);
}
}
I suggest you just bind the annotation to an advice method parameter like this:
package com.yh.application;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
#Aspect
#Component
public class AnnotationAspect {
#Before("#target(ds) && within(com.yh..*)")
public void interceptDS(JoinPoint joinPoint, DS ds) {
System.out.println(joinPoint + " -> DS value = " + ds.value());
}
}
Update:
I forgot to explain why you were getting the error in the first place: Pointcuts like this(), target(), #this(), #target() can only be determined dynamically during runtime because they access active object instances. Hence, all possible Spring components (also internal ones) are being aspect-woven, which is also the reason why the workaround to limit the aspect scope by using statically evaluated pointcut designators like within() help you avoid the problem.
But actually, using a statically evaluated pointcut designator in the first place, if it is a viable alternative, is the best idea. It is also faster than weaving the world, creating dozens or hundreds of proxies, and then to dynamically evaluate pointcuts over and over again. Luckily, in this case such an alternative exists: #within().
#Aspect
#Component
public class AnnotationAspect {
#Before("#within(ds)")
public void interceptDS(JoinPoint joinPoint, DS ds) {
System.out.println(joinPoint + " -> DS value = " + ds.value());
}
}

Logging not working in web application using Spring AOP

using Spring AOP, I'm trying to put logging in my web application for an object called corelation like below :-
LoggingCorrelationEnrichingAspect.java:-
#Aspect
#Component
public class LoggingCorrelationEnrichingAspect {
private static final Logger logger = getLogger(LoggingCorrelationEnrichingAspect.class);
#Around("#annotation(Correlated)")
public Object wrapWithCorrelationContext(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
logger.info("Entering "+ proceedingJoinPoint.getSignature().getName() +" with Correlation Id:: "
+ ((Map)proceedingJoinPoint.getArgs()[0]).get(CommerceConnectorConstants.HttpHeaders.CORRELATION_ID).get());
return ((Mono<?>) proceedingJoinPoint.proceed());
}
}
Correlated.java:-
#Inherited
#Target({ElementType.METHOD, ElementType.TYPE})
#Retention(RetentionPolicy.RUNTIME)
public #interface Correlated {}
In my main REST Controller operation, using #Correlated annotation, I'm trying to log this corellation like below :-
#Correlated
#GetMapping(path = "/products}", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public Mono<ProductBeanResponse> getProducts(
#RequestHeader(name = Test.HttpHeaders.TENANT_ID, required = true) UUID tId,
#RequestHeader(name = Test.HttpHeaders.CORRELATION_ID, required = true) UUID correlationId
----
---
}
However, when I test my service using PostMan tool and see the applicaiton logs, the corelation id is never logged :-
logger.info("Entering "+ proceedingJoinPoint.getSignature().getName() +" with Correlation Id:: "
+ ((Map)proceedingJoinPoint.getArgs()[0]).get(CommerceConnectorConstants.HttpHeaders.CORRELATION_ID).get());
Please advise is this a configuration issue in Spring AOP.
Thanks
This can get working in either of below two ways
Provide fully qualified name of Correlated in the pointcut definition as #Around("#annotation(com.x.y.z.Correlated)")
Update the Aspect method signature to include the Correlated as second argument
#Around("#annotation(correlated)")
public Object wrapWithCorrelationContext(ProceedingJoinPoint proceedingJoinPoint, Correlated correlated ) throws Throwable {
logger.info("Entering "+ proceedingJoinPoint.getSignature().getName() +" with Correlation Id:: "
+ ((Map)proceedingJoinPoint.getArgs()[0]).get(CommerceConnectorConstants.HttpHeaders.CORRELATION_ID).get());
return ((Mono<?>) proceedingJoinPoint.proceed());
}
Let know in comments if anything else is required.
P.S.: Also as pointed out by M. Deinum make sure to remove object cast.

Consider defining a bean of type 'net.corda.core.messaging.CordaRPCOps' in your configuration

Unable to use CordaRPCOps implementation methods in my CustomController,
#RequestMapping(value="/peers", produces = MediaType.APPLICATION_JSON)
public Map<String, List<String>> peers() throws Exception
{
CordaRPCOps proxy=rpc.getParameterValue("proxy");
Party myIdentity= proxy.nodeInfo().getLegalIdentities().get(0);
return ImmutableMap.of("peers", rpcOpsImpl.networkMapSnapshot()
.stream()
.filter(nodeInfo -> nodeInfo.getLegalIdentities().get(0) != myIdentity)
.map(it -> it.getLegalIdentities().get(0).getName().getOrganisation())
.collect(toList()));
}
getting error while building runPartyAServer as,
APPLICATION FAILED TO START
Description:
Field services in net.corda.server.controllers.CustomController required a bean of type 'net.corda.core.messaging.CordaRPCOps' that could not be found.
Action:
Consider defining a bean of type 'net.corda.core.messaging.CordaRPCOps' in your configuration.
As the error message says, you must define a bean of type CordaRPCConnection/CordaRPCOps.
Something similar to:
#Bean
private fun connect(): CordaRPCConnection {
val hostAndPort = NetworkHostAndPort(configuration.host, configuration.port)
val client = CordaRPCClient(hostAndPort)
val connection = client.start(configuration.user, configuration.password)
return connection;
}
We do not provide any DI container integration by default.

logging at package level using spring AOP

I am trying to implement logging and exception framework for my application using spring AOP. I have defined beans for classes in ApplicationContext and using interceptors to log entry, exit and exceptions if any.
My query is : Do I need to create bean for every class in my ApplicationContext or is it possible to generalise this at a package level. If I have 30 classes in my package, I should create 30 beans in my AppContext, rather I would prefer doing it at a package level if it is possible. Kindly help me in this regard.
You need to use #Around advice. Here define the pointcut such that each class and method of the package are covered / intercepted. See sample below -
#Aspect
public class AllMethodLogging {
#Around(execution("* com.x.y..*.*(..)"))
public Object intercept(ProceddingJoinPoint pjp){
String name = pjp.getSignature().getName();
try {
logger.info("started " + name);
Object obj = pjp.proceed();
logger.info("finished " + name + " successfully");
return obj;
} catch (Throwable t) {
logger.error(name + " finished with Exception - " + t.getMessage());
throw t;
} finally {
// do some more logging if required else skip
}
}
}
The pointcut execution("* com.x.y..*.*(..)") means that any method within com.x.y package, and its sub-package, with all visibility should be intercepted by this advice.
See docs here for more examples to customize your pointcut as per your needs.

Can Guice be configured to hide the class path in stack traces?

Guice's stack traces can get so verbose that they are very painful to read. Here's an example:
1) No implementation for java.util.Set<com.mydomain.myapp.android.activities.catbrowser.generalizedbrowser.listview.helpers.databaseitem.itemmanipulators.ItemManipulator<com.mydomain.myapp.flash.Cat>> annotated with #com.google.inject.assistedinject.Assisted(value=) was bound.
while locating java.util.Set<com.mydomain.myapp.android.activities.catbrowser.generalizedbrowser.listview.helpers.databaseitem.itemmanipulators.ItemManipulator<com.mydomain.myapp.flash.Cat>> annotated with #com.google.inject.assistedinject.Assisted(value=)
...
If I could hide the classpath, it would look like:
1) No implementation for Set<ItemManipulator<Cat>> annotated with #Assisted(value=) was bound.
while locating Set<ItemManipulator<Cat>> annotated with #Assisted(value=)
Is there any way to configure Guice to do this?
So the answer is no.
If you take look at guice source code you will find com.google.inject.internal.Errors class that is responsible for building error messages. In this class it is coded that the Key is converting the following way:
new Converter<Key>(Key.class) {
public String toString(Key key) {
if (key.getAnnotationType() != null) {
return key.getTypeLiteral() + " annotated with "
+ (key.getAnnotation() != null ? key.getAnnotation() : key.getAnnotationType());
} else {
return key.getTypeLiteral().toString();
}
}
}
Next step is to take a look at TypeLiteral#toString method:
#Override public final String toString() {
return MoreTypes.typeToString(type);
}
Where MoreTypes#typeToString is a static method that cannot be configured
public static String typeToString(Type type) {
return type instanceof Class ? ((Class) type).getName() : type.toString();
}

Resources