Camel context not starting in hello world app - java

I am attempting to run camel within spring. Below are the files i have..
POM xml file which have relevant dependencies.
<properties>
<spring.version>3.2.11.RELEASE</spring.version>
<camel.version>2.14.1</camel.version>
</properties>
<?xml version="1.0" encoding="UTF-8"?>
<dependencies>
<!-- camel core -->
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-core</artifactId>
<version>${camel.version}</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-spring</artifactId>
<version>${camel.version}</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-metrics</artifactId>
<version>${camel-version}</version>
</dependency>
<!-- Spring 3 dependencies -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
</dependencies>
Main context file (main-context.xml).
<camel:camelContext trace="false" id="mc-service-camel-context" threadNamePattern="Camel (#camelId#) thread ##counter# - #name#">
<camel:contextScan/>
</camel:camelContext>
A route that looks like this
#Component
public class MyRoute extends RouteBuilder {
#Override
public void configure() throws Exception {
from("timer://runOnce?repeatCount=1&delay=5000")
.log("Hello World!!")
.end();
}
}
And finally a main class that looks like this.
public static void main(String[] args) throws InterruptedException {
AbstractXmlApplicationContext appContext = new ClassPathXmlApplicationContext("main-context.xml");
Thread.sleep(100000);
}
Issue is i don't see the log "Hello World". Could someone give me some feedback on what i am missing..

I had to enable Component scanning.
<context:annotation-config/>
<context:component-scan base-package="com.mycompany.app*" />

Related

Springboot Actuator Refresh does not reload #Value properties in #ConfigurationProperties

I have a springboot application that ingests an application.properties via #ConfigurationProperties and #PropertySource("classpath:application.properties"). My desire is to reload these properties on the fly for the purposes of support. When I POST to http://localhost:8080/actuator/refresh I get a 200 OK response but the body is empty, which I think implies no #RefreshScopes have been refreshed but I'm not sure. I have read and viewed most docs and SO while trying various things but haven't managed to reload a new value.
Here is my app:
application.properties:
# suppress inspection "UnusedProperty" for whole file
# the name of Camel
camel.springboot.name = IntegrationsCamel
# how often to trigger the timer (millis)
myPeriod = 2000
spring.main.allow-bean-definition-overriding=true
# to turn off Camel info in (/actuator/info)
management.info.camel.enabled=false
# to configure logging levels
logging.level.org.springframework = INFO
logging.level.org.apache.camel.spring.boot = INFO
logging.level.org.apache.camel.impl = DEBUG
logging.level.sample.camel = DEBUG
# Environment
integration.env = DEV
spring.application.name = integration
spring.config.import=aws-parameterstore:
# Client API Auth -- Set by Instance
integration.client.auth.key = tempclientkey
integration.client.auth.secret = tempclientsecret
# Client API Credentials -- Set by Instance
integration.client.endpoint = https://127.0.0.2
integration.client.port = 6060
# AWS Paramstore Config
aws.paramstore.enabled=true
aws.paramstore.prefix=/integration
aws.paramstore.defaultContext=application
aws.paramstore.profile-separator=_
# AWS OAuth
cloud.aws.credentials.instance-profile=true
cloud.aws.credentials.profile-name=default
cloud.aws.credentials.access-key=${AWS_ACCESS_KEY_ID}
cloud.aws.credentials.secret-key=${AWS_SECRET_ACCESS_KEY}
# Non EC2 vars (remove when running live)
cloud.aws.stack.auto=false
cloud.aws.region.static=eu-west-1
AWS_EC2_METADATA_DISABLED=true
logging.level.com.amazonaws.util.EC2MetadataUtils=error
logging.level.com.amazonaws.internal.InstanceMetadataServiceResourceFetcher=error
# DB Vars
spring.datasource.driver-class-name=com.microsoft.sqlserver.jdbc.SQLServerDriver
spring.datasource.url=jdbc:sqlserver://${RDS_HOSTNAME:my-server-domain.com}:${RDS_PORT:1337};databaseName=${RDS_DB_NAME:MYDB}
spring.datasource.username=${RDS_USERNAME:readuser}
spring.datasource.password=${RDS_PASSWORD:${read_pass}}
spring.jpa.properties.hibernate.default_schema=dbo
# Actuator Management
management.endpoints.enabled-by-default=false
management.endpoint.refresh.enabled=true
management.endpoints.web.exposure.include=refresh
All of these are successfully pulled in to the bean
package com.Integration.Configuration;
import lombok.Getter;
import lombok.Setter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.cloud.context.scope.refresh.RefreshScopeRefreshedEvent;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.event.EventListener;
#Getter
#Setter
#RefreshScope
#Configuration
public class ApplicationProperties {
#Value("${integration.env}")
private String env;
#Value("${spring.datasource.url}")
private String DB_URL;
#Value("${rds-username}")
private String DB_USERNAME;
#Value("${rds-password}")
private String DB_ENCRYPTED_PASSWORD;
#Value("${oauth2.key}")
private String OAuth2Key;
#Value("${oauth2.secret}")
private String OAuth2Secret;
#Value("${integration.client.endpoint}")
private String ClientAPIEndpoint;
#Value("${integration.client.port}")
private String ClientAPIPort;
#Value("${integration.client.auth.key}")
private String ClientAPIKey;
#Value("${integration.client.auth.secret}")
private String ClientAPISecret;
public ApplicationProperties() {}
#SuppressWarnings("unused")
#EventListener(RefreshScopeRefreshedEvent.class)
public void onRefresh(RefreshScopeRefreshedEvent event) {
// todo: Bug-#01 #RefreshScope actuator/refresh not updating #Values
System.out.println(this.ClientAPIEndpoint);
}
}
The event listener fires without issue too and it will successfully print the value from application.properties. I have debugged main below and all values are populated without issue.
I suspect the issue is here but I'm not sure what I'm doing wrong in main()
package com.Integration;
import com.Integration.AutoLoader.RouteBuilderAutoLoader;
import com.Integration.Configuration.ApplicationProperties;
import com.Integration.Scheduler.TasksScheduler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ConfigurableApplicationContext;
import org.apache.camel.CamelContext;
import org.apache.camel.impl.DefaultCamelContext;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import java.util.Objects;
#SpringBootApplication
#RefreshScope
#EnableScheduling
public class Integration {
public static String SERVER_ADDR;
protected static CamelContext context;
public static void main(String[] args) throws Exception {
// Spring Boot App Entry
ConfigurableApplicationContext appContext = SpringApplication.run(Integration.class, args);
// Get ApplicationProperties
ApplicationProperties properties = appContext.getBean(ApplicationProperties.class);
SERVER_ADDR = (Objects.equals(properties.getEnv(), "DEV")) ? "0.0.0.0" : "localhost";
// Start Camel Context Engine
context = new DefaultCamelContext();
// Feed Camel our defined routes & start
RouteBuilderAutoLoader.loadRoutes(context);
context.start();
}
}
The last thing I'm unsure of is if I have the necessary dependencies or if I'm missing something here.
<?xml version="1.0" encoding="UTF-8"?>
<!--suppress MavenPackageUpdate -->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.Integration</groupId>
<artifactId>Integration</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Integration</name>
<description>Generic API Integration App</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.5</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring-cloud.version>Hoxton.SR12</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<version>2.6.5</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
<version>2.6.5</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.2.4.Final</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.21</version>
</dependency>
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
<version>9.4.1.jre8</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>2021.0.1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- AWS/Cloud -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-aws</artifactId>
<version>2.2.6.RELEASE</version>
</dependency>
<dependency>
<groupId>io.awspring.cloud</groupId>
<artifactId>spring-cloud-aws-context</artifactId>
<version>2.4.0</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
<version>3.1.1</version>
</dependency>
<dependency>
<groupId>io.awspring.cloud</groupId>
<artifactId>spring-cloud-starter-aws-parameter-store-config</artifactId>
<version>2.4.0</version>
</dependency>
<!-- Camel 3.14.1 Latest LTS version -->
<dependency>
<groupId>org.apache.camel.springboot</groupId>
<artifactId>camel-spring-boot-bom</artifactId>
<version>3.14.1</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-core</artifactId>
<version>3.14.1</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-core-languages</artifactId>
<version>3.14.1</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-bean</artifactId>
<version>3.14.1</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-rest</artifactId>
<version>3.14.1</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-direct</artifactId>
<version>3.14.1</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-netty-http</artifactId>
<version>3.14.1</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-platform-http</artifactId>
<version>3.14.1</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-management</artifactId>
<version>3.14.1</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-endpointdsl</artifactId>
<version>3.14.1</version>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-spring</artifactId>
</dependency>
<dependency>
<groupId>org.jetbrains</groupId>
<artifactId>annotations</artifactId>
<version>RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-inline</artifactId>
<version>4.3.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
</project>
Edit 12/04/2022
Completely redid my classes with #ConfigurationProperties
So when I post to refresh the values in propertySource for AWS automatically update. So eg I change cobaltdlt to cobaltdlttest below, hit refresh, and then I can see the change when I query GET http://localhost:8080/actuator/env
So the refresh is working but it's not reflective in the #Component beans even though the propertySource is updating. In fact the only beans it is working with are the AWS beans.
Have you tried a PropertiesConfiguration bean? See here: https://www.baeldung.com/spring-reloading-properties.
Once configured correctly, it should automatically read changes to your properties file and reload them. Also, there are some limitations that are mentioned in that article that you should be aware of.
#I2obiN. As you have mentioned that ApplicationProperties is getting refreshed by Refresh Scopes, therefore actuator refresh is working properly.
But I noticed that you are using RefreshScope on main application class. IMO this actuator management/refresh will not restart application. You can try to create an extra method that reinitializes Camel Context.
Hope this helps!!
https://www.baeldung.com/java-restart-spring-boot-app#actuators-restart-endpoint
You can invoke the refresh Actuator endpoint by sending an empty HTTP POST to the client's refresh endpoint: http://localhost:8080/actuator/refresh . Then you can confirm it worked by visiting the http://localhost:8080/message endpoint.
And once you refresh, try to rebind immediately by calling the POST endpoint http://localhost:8080/actuator/env
This worked on a spring boot I tried and it reloads the values and you can see it in the stack trace.
I tried doing a field in spring data source with the given payload to Rebind and it reloads Example as the value.
Payload:
{"name":"spring.datasource.userName", "value":"Example"}
In the application.properties, add the following
management.endpoint.env.post.enabled=true
management.endpoint.restart.enabled=true
endpoints.sensitive=true
endpoints.actuator.enabled=true
management.security.enabled=false
management.endpoints.web.exposure.include=*

Spring cache Caffeine integration without SpringBoot

I want to integrate Caffeine Cache in my Spring 5 application. I know that I need the CaffeineCacheManager, but i dont have the class. The only way i found is to add the SpringBoot Starter Cache package to the pom, but i dont want to use Spring Boot.
I have this Spring packages in my pom:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.2.8.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-core -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.2.8.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.8.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.8.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-web -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>5.3.3.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-config -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>5.3.3.RELEASE</version>
</dependency>
Is any way to have CaffeineCacheManager class wihouth Spring Boot? Thanks.
Actually i am using this code to configure the cache:
#Bean
public CacheManager cacheManager() {
SimpleCacheManager cacheManager = new SimpleCacheManager();
cacheManager.setCaches(Arrays.asList(
new ConcurrentMapCache(
"categorias",
Caffeine.newBuilder().expireAfterWrite(Duration.ofDays(1)).maximumSize(100).build().asMap(),
false
),
new ConcurrentMapCache(
"ciudad",
Caffeine.newBuilder().maximumSize(100).build().asMap(),
false
)
));
return cacheManager;
}
The main spring cache implementation is located in spring-context dependency. You should only setup that cache manager and use #Cacheable annotation.
For examples see: https://www.baeldung.com/spring-cache-tutorial
Let me know if you need code example of connection Caffeine cache with spring cache mechanism.
CaffeineCacheManager configuration:
CaffeineCacheManager is located in
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>5.2.8.RELEASE</version>
</dependency>
And caffeine dependency:
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
<version>2.8.8</version>
</dependency>
Configuration:
#Configuration
#EnableCaching
public class Config {
#Bean
public Caffeine<Object, Object> caffeineConfig() {
return Caffeine.newBuilder().expireAfterWrite(60, TimeUnit.MINUTES);
}
#Bean
public CacheManager cacheManager(Caffeine<Object, Object> caffeine) {
CaffeineCacheManager caffeineCacheManager = new CaffeineCacheManager();
caffeineCacheManager.setCaffeine(caffeine);
return caffeineCacheManager;
}
}

Schedule Task with Jax-RS and CDI

I'm try to understand how to manage scheduled tasks in my project with Jax-RS and CDI.
With Spring I was easily able to achive that with ThreadPoolTaskScheduler or #Scheduled annotation and I'm trying to replicate both ways without success.
First of all, I'm using Wildfly 14 and this seems to cause some issues because I've tryied to inject with #Resource both ManagedScheduledExecutorService and TimerService but Wildfly throws exception of missing dependencies (but the Admin guide didn't help me about that).
Instead of inject resources I've tryied to use a singleton object like this:
#Singleton
public class CacheManager {
private final static Logger log = LogManager.getLogger();
public CacheManager() {
log.error("######## Init" + LocalTime.now());
}
#Schedule(hour = "*", minute = "*", second = "*/1")
private void timeout() {
log.error("######## " + LocalTime.now());
}
}
But the method is never called.
So I'm not understanding what I'm missing. Maybe I have wrongly configured the project so this is my pom.xml dependencies:
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.2</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.10.2</version>
</dependency>
<!-- Import the JAX-RS API, we use provided scope as the API is included in JBoss WildFly -->
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jaxrs</artifactId>
<version>3.10.0.Final</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>jaxrs-api</artifactId>
<version>3.0.12.Final</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-multipart-provider</artifactId>
<version>3.0.12.Final</version>
<scope>provided</scope>
</dependency>
<!-- Import the CDI API, we use provided scope as the API is included in JBoss WildFly -->
<dependency>
<groupId>javax.enterprise</groupId>
<artifactId>cdi-api</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>
<!-- Import the JSF API, we use provided scope as the API is included in JBoss WildFly -->
<dependency>
<groupId>org.jboss.spec.javax.faces</groupId>
<artifactId>jboss-jsf-api_2.2_spec</artifactId>
<version>2.2.14</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.11.2</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.11.2</version>
</dependency>
<dependency>
<groupId>javax.ejb</groupId>
<artifactId>ejb-api</artifactId>
<version>3.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
This is my beans.xml
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd" bean-discovery-mode="annotated">
</beans>
I am using Java 8.
EDIT: the CacheManager is instantiated in the JAX-WS Application
#ApplicationScoped
#ApplicationPath("/rest")
public class JaxRsActivator extends Application {
private static final Logger logger = LogManager.getLogger();
private Set<Object> singletons = new HashSet<Object>();
private HashSet<Class<?>> classes = new HashSet<Class<?>>();
public JaxRsActivator() {
singletons.add(new CorsFilter());
singletons.add(new CacheManager());
}
#Override
public Set<Object> getSingletons() {
return singletons;
}
#Override
public HashSet<Class<?>> getClasses(){
return classes;
}
}
I've found the solutions: #Singleton must be javax.ejb.Singleton and not javax.inject.Singleton.

SseEmitter onError method behaves different in Tomcat and Glassfish/Payara

I'm implementing server sent events in Spring MVC application with Payara 5. However, when there is error on emitter.send() (when client disconnected) emitter's onError method doesn't get called. When I try the same code on Spring Boot with embedded Tomcat everything works normal. Spring dependency versions are same on both applications.
#GetMapping("/listen-sse")
public SseEmitter sseEmitter() {
SseEmitter emitter = new SseEmitter(0L);
emitter.onError(e -> System.out.println("OnError"));
ExecutorService service = Executors.newCachedThreadPool();
service.execute(() -> {
while (true) {
try {
Thread.sleep(2000);
emitter.send("Hello");
} catch (IOException | InterruptedException e) {
System.out.println("Exception");
break;
}
}
});
service.shutdown();
return emitter;
}
My dependencies in Spring MVC application:
<dependencies>
<!--Spring resources-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.1.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.1.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>5.1.8.RELEASE</version>
</dependency>
<!-- Spring + aspects -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.1.8.RELEASE</version>
</dependency>
</dependencies>

Spring 3 with Drools 6 maven inconcistency

I have a problem integrating Drools with Spring. I am trying to make a simple Hello World spring example, I reached a moment where my simple project refuses to compile.
To work with Drools annotations like #KSession I need the drools-spring package, but it seems incompatible with Spring 3. As builder I use Maven. Here is how my .pom's looks like:
<dependencies>
<!-- Drools -->
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-compiler</artifactId>
<version>6.0.0.Final</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-core</artifactId>
<version>6.0.0.Final</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-decisiontables</artifactId>
<version>6.0.0.Final</version>
</dependency>
<dependency>
<groupId>org.kie</groupId>
<artifactId>kie-api</artifactId>
<version>6.0.0.Final</version>
</dependency>
<dependency>
<groupId>org.kie</groupId>
<artifactId>kie-internal</artifactId>
<version>6.0.0.Final</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-spring</artifactId>
<version>6.0.0.Beta2</version>
</dependency>
<!-- Inject -->
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>
<!-- Spring 3 dependencies -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>3.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>3.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>3.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>3.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>3.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>3.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>3.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>3.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>3.2.4.RELEASE</version>
</dependency>
</dependencies>
I use very simple case of controller class:
#Controller
#RequestMapping(value = "/")
public class BaseController extends AbstractController {
private static final Logger log = Logger.getLogger(BaseController.class);
#Autowired
#KSession("ksession-rules")
KieSession mySession;
#RequestMapping(value = "/test")
public #ResponseBody
String test() {
Fact myFact = new Fact();
myFact.setFactNumber(20); //According to my rule when myFact.number>20
//then result will be set to "Hello World"
mySession.insert(myFact);
mySession.fireAllRules();
return myFact.getResult();
}
}
At this point I receive an error:
"The hierarchy of the type BaseController is inconsistent".
I noticed that if I remove drools-spring from the dependency list the project compiles successfully. However without that package I cannot deploy my project, because the deployer demands the drools' class responsible for interpreting #KSession and that class is located in drools-spring package.
After some investigation it appears that my Drools session configuration seems to have
nothing to do with the error above, so for the sake of succinctness I will not quote them. Instead of that I will mark that even if I don't make any modifications to the spring configuration and remove the KieSession from my example, making it a simple spring hello world example, I receive one and the same error out of my IDE (Eclipse): "The hierarchy of the type BaseController is inconsistent" and if I remove the drools-spring dependency the problem disappears.
It seems to me as dependency conflict.
Does anyone experienced similar problems with drools+spring?
Can someone suggest a solution to the problem?
Am I doing something wrong?
Thanks for the help!
After some research I found two things.
Drools' drools-spring package declares its own spring dependencies that are overriding my spring dependencies, which leads to spring malunctions. What I did is to manually remove the spring dependencies from drools-spring .pom file.
Another mistake that I had in the upper example is that I didn't have kie-spring as dependency. Kie-spring is mandatory for one drools bean KModuleBeanFactoryPostProcessor, which is responsible to read my kmodule-kbase-ksession configuration from the spring configuration.
After resolving these two problems my project compiles now and I can see in the code that KModuleBeanFactoryPostProcessor defines that my configuration is being read and analized as I expected it to be.

Categories

Resources