EventHandler in external java file not getting triggered - spring-boot

I have an Aggregate class which has
CommandHandler that receives a CreateAccountCommand
1 EventSourceHandling that receives AccountCreatedEvent
Correspondingly, in other package, I’ve #EventHandler for the AccountCreatedEvent. However, it is not getting invoked.
#Component
class EventHandlingComponent {
#Autowired AccountRepository repo;
#EventHandler
public void on(AccountCreatedEvent event )
{
// save to repository ;
}
}
I’m using spring boot application with this added as dependency
<dependency>
<groupId>org.axonframework</groupId>
<artifactId>axon-spring-boot-starter</artifactId>
<version>4.5.3</version>
<exclusions>
<exclusion>
<groupId>org.axonframework</groupId>
<artifactId>axon-server-connector</artifactId>
</exclusion>
</exclusions>
</dependency>
I'll be really thankful if someone can point me what mistake I'm making.

Is the event handler class in a package that is a subpackage from the package of the main class? If not, the scanner will not find the class by default. In this case you will have to configure which packages Spring boot should scan (using the scanBasePackages property in the SpringBootApplication annotation).

Related

Using Spring StateMachine in an EJB container

I'm trying to use Spring's state machine library inside of a JavaEE application running in a container to manage instances of a class named RunInfo. But I'm not sure how to integrate the two together.
I tried adding the following dependencies:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
<version>2.2.11.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.statemachine</groupId>
<artifactId>spring-statemachine-core</artifactId>
<version>2.4.1</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>5.7.2</version>
</dependency>
on spring-boot-autoconfigure and then adding the following configuration class:
#Configuration
#EnableAutoConfiguration
#ComponentScan(basePackages = {"com.ourdomain"})
public class StateConfiguration {}
I then wrote a simple state machine configuration:
#Configuration
#EnableStateMachine(name = "runInfoStateMachine")
public class RunInfoStateMachineConfiguration extends EnumStateMachineConfigurerAdapter<RunInfoState, RunInfoEvent> {
and state handler:
#Component
public class RunInfoStateHandler extends LifecycleObjectSupport {
// ...
#Autowired private StateMachine<RunInfoState, RunInfoEvent> stateMachine;
}
based on another project that I manage (which is a pure Spring Boot app).
The state handler is created, but the state machine reference is never injected; i.e., stateMachine in the above code is always null.
How does one integrate the Spring StateMachine framework into an EJB application?

Connect to both ActiveMQ and IBM MQ

I am using the following Maven dependency and class in my Spring Boot application to send messages to ActiveMQ:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-activemq</artifactId>
</dependency>
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.annotation.EnableJms;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.stereotype.Component;
#Component
#EnableJms
public class MQSender {
#Autowired
private JmsTemplate jmsTemplate;
public void sendMsgActiveMQ(String msg) {
jmsTemplate.convertAndSend("DEV.QUEUE1", msg);
}
/* public void sendMsgIBMMQ(String msg) {
jmsTemplate.convertAndSend("DEV.QUEUE1", msg);
}*/
}
How could I use the same class or any other class within the same application to send messages to IBM MQ as well? If I add the add the below dependency how will the #Autowired JmsTemplate behave?
<dependency>
<groupId>com.ibm.mq</groupId>
<artifactId>mq-jms-spring-boot-starter</artifactId>
<version>2.5.0</version>
</dependency>
You can get the IBM MQ client jars file with Maven dependency:
<dependency>
<groupId>com.ibm.mq</groupId>
<artifactId>com.ibm.mq.allclient</artifactId>
<version>9.1.0.6</version>
</dependency>
As to your #Autowired question, your problem is ambiguity by type. You will need JMS connections factories for the two brokers that have the same type. The article here has some good suggestions.
I prefer to only #Autowire in test cases, where the application context is small. For a practical application, I prefer explicit initialization. (maybe I'm just used to it). In any event, have a look here github for some examples that may have be useful.

NoClassDeffFoundError: org/springframework/data/jpa/repository/Repository

I am using JpaRepository, here is my code
public Interface EmpRepository extends JpaRepository<Employee, Integer> {}
class EmployeeServicImpl {
private EmpRepository empRepository;
#Autowired
EmployeeServicImpl (EmpRepository theRepository) {
this.empRepository = theRepository;
}
}
added below dependencies in my pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
While start the application, resolution of declared constructor of bean from class loader : NoClassDeffFoundError : /org/springframework/data/jpa/repository/Repository
Some points,
Keep your repository interface in a separate package.
Use #Repository on your repository.
Use #Service or #Component annotation at EmployeeServicImpl class.
It appears as when you're starting the application, Spring is trying to find EmpRepository dependency to instantiate your service but is not able to find the repository since it is not declared as a #Repository by you.
Further, reason for using #Service is so that EmployeeServicImpl becomes available to Spring too.

Custom annotation with Spring AOP as a library is not working

I am trying to create a spring boot library with Custom annotation and Spring AOP. When I used this library with new spring boot application. Then Its not working. Even I am not getting any error.
Library Sample -
Custom Annotation
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 HttpLogger {
}
Spring AOP class
#Aspect
class LoggingAspect {
#Around("#annotation(com.demo.commonlogging.aspect.HttpLogger)")
public Object inControllers(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
return loggingAdvice(proceedingJoinPoint); // Method for implementation
}
}
pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
Using mvn clean install for creating library
Now new library is imported in springboot application.
And new Custom annotation is used in controllers
Controllers
#RestController
#RequestMapping(value = "/rest/test")
public class RestApiTestControllers {
#GetMapping
#HttpLogger
public String get(){
return "Hello !";
}
}
Please help here.
Seems like you are missing #Component from LoggingAspect also make call to proceed proceedingJoinPoint.proceed(); and return it's value.
So your code should look like:
#Aspect
#Component
class LoggingAspect {
#Around("#annotation(com.demo.commonlogging.aspect.HttpLogger)")
public Object inControllers(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.out.println("Before call");
Object returned = proceedingJoinPoint.proceed();
System.out.println("After call");
return returned;
}
}
Hope this helps!

SpringBoot 2 + Junit5: null with #Value

I have an application with SpringBoot2 and Junit5, and now I'm trying to make a test. I have a this class called OrderService that looks like this:
#Component
public class OrderService {
#Value("#{'${food.requires.box}'.split(',')}")
private List<String> foodRequiresBox;
#Value("#{'${properties.prioritization}'.split(',')}")
private List<String> prioritizationProperties;
#Value("${further.distance}")
private Integer slotMeterRange;
#Value("${slot.meters.long}")
private Double slotMetersLong;
As you can see, the class has many #Value annotations that extracts values from application.properties file.
In the POM file I have these dependences:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.1.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.1.0</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>RELEASE</version>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-launcher</artifactId>
<version>1.1.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<version>2.0.5.RELEASE</version>
</dependency>
Tn the test/resources folder I have the application.properties file with this information:
properties.prioritization:vip,food
food.requires.box:pizza,cake,flamingo
further.distance:2
slot.meters.long:0.5
The test file looks like this:
#ExtendWith(SpringExtension.class)
#TestPropertySource(locations="classpath:application.properties")
public class OrderServiceTest {
OrderService orderService;
#BeforeEach
void before(){
orderService = new OrderService();
}
#Test
void findAll() {
Order order = new Order().withDescription("2x Pizza with Salad\\n2x Kebab with Fries\\n1x Hot dog with Fries\\n2x Pizza with Fries");
assertTrue(orderService.orderHasFood.test(order));
}
}
But the test throws NullPointerException when it tries to use foodRequiresBox, so there is a problem to read the application.properties file.
Could you tell how can I read the application.properties file for the tests?
1st Solution
I would recommend to use Spring's internal annotation called #SpringJUnitConfig
This annotation is actually the same as #ExtendWith(SpringExtension.class) BUT you can configure your spring application contexts for your test in the same way you used to use #ContextConfiguration.
Or if you want a full Spring Boot Test you could just combine:
#SpringJUnitConfig
#SpringBootTest
public class OrderServiceTest {
...
}
2nd Solution
Another way is to not use Spring at all, but mock all the internal stuff with e.g. Mockito and write a plain simple Unit Test.
You could then set your normally via Spring injected annotated #Value fields via org.springframework.test.util.ReflectionTestUtils.
I'd recommend using org.springframework.test.util.ReflectionTestUtils (as indicated in #mrkernelpanic second solution) using the setField() method, in order to avoid initializing the full Spring context.
Here is a snippet:
// ReflexionTestUtils.setField(targetObject, "targetFieldName", valueToInject);
ReflexionTestUtils.setField(orderService, "foodRequiresBox", "pizza,cake,flamingo");

Resources