java.lang.RuntimeException: Unexpected global [result] - drools

I have this class, that reads rule files, insert facts and run rules.
public class RuleRunner {
private KieServices kieServices = KieServices.Factory.get();
public enum RuleType {
XLS,
DRL;
}
private void prepareSession(String ruleResource, RuleType type) {
KieFileSystem kieFileSystem = kieServices.newKieFileSystem();
Resource resource = kieServices.getResources().newClassPathResource(ruleResource);
switch(type) {
case XLS: {
resource.setResourceType(ResourceType.DTABLE);
break;
}
case DRL: {
resource.setResourceType(ResourceType.DRL);
break;
}
}
kieFileSystem.write(resource);
KieBuilder kieBuilder = kieServices.newKieBuilder(kieFileSystem);
kieBuilder.buildAll();
if (hasErrors(kieBuilder)) {
System.out.println("Failed to build!");
return;
}
}
private boolean hasErrors(KieBuilder builder) {
if (builder.getResults().getMessages().size() > 0) {
return true;
}
return false;
}
public void runRules(Object[] facts, GlobalVariable[] variables, String ruleResource, RuleType type) {
prepareSession(ruleResource, type);
KieContainer kieContainer = kieServices.newKieContainer(kieServices.getRepository().getDefaultReleaseId());
KieSession kieSession = kieContainer.newKieSession();
for (GlobalVariable variable: variables) {
kieSession.setGlobal(variable.getVariableName(), variable);
}
for(Object fact: facts) {
kieSession.insert(fact);
}
kieSession.fireAllRules();
kieSession.dispose();
}
}
And I have this rule
package com.pack.drools.apps;
import com.pack.drools.apps.domain.Person;
import com.pack.drools.apps.domain.GlobalVariable;
global GlobalVariable result
rule "if person has less that 10 cash then hes poor"
when
$person:Person(cash < 10)
then
result.setResult(-1);
end
rule "if person has more than 90 cash then hes rich"
when
$person:Person(cash > 90)
then
result.setResult(-2);
end
rule "if person has more than 10 and less than 90 then hes average"
when
$person:Person(cash >= 10 && cash <= 90)
then
result.setResult(-3);
end
However when I try to run my application
package pack.rup.drools.apps;
import pack.rup.drools.apps.core.RuleRunner;
import pack.rup.drools.apps.core.RuleRunner.RuleType;
import pack.rup.drools.apps.domain.GlobalVariable;
import pack.rup.drools.apps.domain.Person;
public class Main {
private static final String DEFAULT_PACKAGE = "pack/rup/drools/apps/";
private static final String XLS_FILE = DEFAULT_PACKAGE + "rule.xls";
private static final String DRL_FILE = DEFAULT_PACKAGE + "rule.drl";
public static void main(String[] args) {
RuleRunner ruleRunner = new RuleRunner();
// build fact
Person person = new Person();
person.setName("John");
person.setCash(100);
GlobalVariable result = new GlobalVariable();
result.setVariableName("result");
// ruleRunner.runRules(new Object[] { person }, new GlobalVariable[] { result }, XLS_FILE, RuleType.XLS);
ruleRunner.runRules(new Object[] { person }, new GlobalVariable[] { result }, DRL_FILE, RuleType.DRL);
System.out.println("Rule result: " + result.getResult());
}
}
my log looks like this
10:13:00.974 [main] INFO o.d.c.k.b.impl.KieRepositoryImpl - KieModule was added: MemoryKieModule[releaseId=org.default:arti
fact:1.0.0-SNAPSHOT]
10:13:00.982 [main] INFO o.d.c.k.b.impl.ClasspathKieProject - Found kmodule: file:/D:/workTestProjects/simpleDroolsApps/sda
-core/build/resources/main/META-INF/kmodule.xml
10:13:00.982 [main] DEBUG o.d.c.k.b.impl.ClasspathKieProject - KieModule URL type=file url=/D:/workTestProjects/simpleDrools
Apps/sda-core/build/resources/main
10:13:01.026 [main] WARN o.d.c.k.b.impl.ClasspathKieProject - Unable to find pom.properties in /D:/workTestProjects/simpleD
roolsApps/sda-core/build/resources/main
10:13:01.027 [main] WARN o.d.c.k.b.impl.ClasspathKieProject - As folder project tried to fall back to pom.xml, but could no
t find one for null
10:13:01.027 [main] WARN o.d.c.k.b.impl.ClasspathKieProject - Unable to load pom.properties from/D:/workTestProjects/simple
DroolsApps/sda-core/build/resources/main
10:13:01.027 [main] WARN o.d.c.k.b.impl.ClasspathKieProject - Cannot find maven pom properties for this project. Using the
container's default ReleaseId
10:13:01.027 [main] DEBUG o.d.c.k.b.impl.ClasspathKieProject - Discovered classpath module org.default:artifact:1.0.0-SNAPSH
OT
10:13:01.028 [main] INFO o.d.c.k.b.impl.KieRepositoryImpl - KieModule was added: FileKieModule[releaseId=org.default:artifa
ct:1.0.0-SNAPSHOT,file=D:\workTestProjects\simpleDroolsApps\sda-core\build\resources\main]
10:13:01.035 [main] WARN o.d.c.k.b.impl.AbstractKieModule - No files found for KieBase defaultKieBase, searching folder D:\
workTestProjects\simpleDroolsApps\sda-core\build\resources\main
10:13:01.131 [main] DEBUG o.drools.core.impl.KnowledgeBaseImpl - Starting Engine in PHREAK mode
Exception in thread "main" java.lang.RuntimeException: Unexpected global [result]
at org.drools.core.impl.StatefulKnowledgeSessionImpl.setGlobal(StatefulKnowledgeSessionImpl.java:1163)
at pack.rup.drools.apps.core.RuleRunner.runRules(RuleRunner.java:57)
at pack.rup.drools.apps.Main.main(Main.java:27)
:sda-core:run FAILED

It seems that you must use a particular directory when writing DRL or XLS resources to the KieFileSystem. Try
String filename = ...; // code that set filename to (e.g.) rule.drl
kieFileSystem.write( "src/main/resources/" + filename, resource );
Also, in your DRL you have
import com.pack.drools.apps.domain....
whereas in Main.java there is
import pack.rup.drools.apps.domain....
These imports should be from the same package.
Edit To test what globals are in the session:
Globals globals = kieSession.getGlobals();
System.out.println( globals.getGlobalKeys() );

We spent 2 days with my colleague and finally figured out that "Unexpected global" error happens when your DRL is empty because of compilation errors, that's why addGlobal() can't find any global declaration.
Once DRL compiler does not throw any exception on errors, instead you can check it yourself using:
if (kieBuilder.hasErrors()) {
System.out.print( kieBuilder.getErrors() );
}

If you insert a global, you must consume it. For example, if you have:
ArrayList<Thing> myThings = new ArrayList<Thing>();
kSession.setGlobal("myThings", myThings);
In your DRL files, you must have at least one matching:
global ArrayList<Thing> myThings;
Otherwise, you get:
java.lang.RuntimeException: Unexpected global [myThings]
at org.drools.core.impl.StatefulKnowledgeSessionImpl.setGlobal(StatefulKnowledgeSessionImpl.java:1200)
at com.sample.ThingTest.test(ThingTest.java:37)

Related

Proto + Kafka Producer: Error serializing object to JSON: Direct self-reference leading to cycle (through reference chain unknownFields

Stack: Micronaut-Kafka, Proto3, gRPC, BloomRPC
Goal: reiceve a grpc request from BloomRPC and post it to a kafka topic
Context: I coded a gRPC endpoint which receives a simple call successfully but when trying to post such object to Kafka topic I get
12:38:18.775 [DefaultDispatcher-worker-1] ERROR i.m.r.intercept.RecoveryInterceptor - Type [com.mybank.producer.DebitProducer$Intercepted] executed with error: Exception sending producer record for method [void sendRequestMessage(String key,DebitRequest message)]: Error serializing object to JSON: Direct self-reference leading to cycle (through reference chain: com.mybank.endpoint.DebitRequest["unknownFields"]->com.google.protobuf.UnknownFieldSet["defaultInstanceForType"])
io.micronaut.messaging.exceptions.MessagingClientException: Exception sending producer record for method [void sendRequestMessage(String key,DebitRequest message)]: Error serializing object to JSON: Direct self-reference leading to cycle (through reference chain: com.mybank.endpoint.DebitRequest["unknownFields"]->com.google.protobuf.UnknownFieldSet["defaultInstanceForType"])
at io.micronaut.configuration.kafka.intercept.KafkaClientIntroductionAdvice.wrapException(KafkaClientIntroductionAdvice.java:564)
I guess somehow my issue is related to "...Error serializing object to JSON". Do I really have to convert such object to json? Can I not just post it to kafka topic? What I am missing here? Well, I can easily fix this issue by creating a new object and setting each property to it accordingly to the request object like this:
endpoint (controller) method
override suspend fun sendDebit(request: DebitRequest): DebitReply {
var dtoDebiter: Debiter = Debiter()
dtoDebiter.id = request.id.toString()
dtoDebiter.name = request.name
transactionService.postDebitTransaction(dtoDebiter)
return DebitReply.newBuilder().setMessage(postStatus).build()
}
Model created only for conversion (doesn't seem weird this solution???)
class Debiter {
lateinit var id: String
lateinit var name: String
}
So, my straight question is: can I reuse the same autogenerated stub resulted from the proto file as a model both for receiving the request and posting it to kafka topic? If so, what is wrong in code bellow? If not, what is the recommended approach?
Full code:
transaction.proto
syntax = "proto3";
option java_multiple_files = true;
option java_package = "com.mybank.endpoint";
option java_outer_classname = "TransactionProto";
option objc_class_prefix = "HLW";
package com.mybank.endpoint;
service Account {
rpc SendDebit (DebitRequest) returns (DebitReply) {}
}
message DebitRequest {
int64 id = 1;
string name = 2;
}
message DebitReply {
string message = 1;
}
transaction endpoint (controller)
package com.mybank.endpoint
import com.mybank.dto.Debiter
import com.mybank.service.TransactionService
import javax.inject.Singleton
#Singleton
#Suppress("unused")
class TransactionEndpoint(val transactionService: TransactionService) : AccountGrpcKt.AccountCoroutineImplBase(){
override suspend fun sendDebit(request: DebitRequest): DebitReply {
var postStatus: String = transactionService.postDebitTransaction(request)
return DebitReply.newBuilder().setMessage(postStatus).build()
}
}
transaction service (not really relevant here)
package com.mybank.service
import com.mybank.dto.Debiter
import com.mybank.dto.Transaction
import com.mybank.dto.Transactions
import com.mybank.endpoint.DebitRequest
import com.mybank.producer.DebitProducer
import javax.inject.Inject
import javax.inject.Named
import javax.inject.Singleton
#Singleton
class TransactionService(){
#Inject
#Named("debitProducer")
lateinit var debitProducer : DebitProducer
fun postDebitTransaction(debit: DebitRequest) : String{
debitProducer.sendRequestMessage ("1", debit)
return "posted"
}
}
kafka producer
package com.mybank.producer
import com.mybank.dto.Transaction
import com.mybank.dto.Transactions
import com.mybank.endpoint.DebitRequest
import io.micronaut.configuration.kafka.annotation.KafkaClient
import io.micronaut.configuration.kafka.annotation.KafkaKey
import io.micronaut.configuration.kafka.annotation.Topic
#KafkaClient
public interface DebitProducer {
#Topic("debit")
fun sendRequestMessage(#KafkaKey key: String?, message: DebitRequest?) {
}
}
build.gradle
plugins {
id "org.jetbrains.kotlin.jvm" version "1.3.72"
id "org.jetbrains.kotlin.kapt" version "1.3.72"
id "org.jetbrains.kotlin.plugin.allopen" version "1.3.72"
id "application"
id 'com.google.protobuf' version '0.8.13'
}
version "0.2"
group "account-control"
repositories {
mavenLocal()
jcenter()
}
configurations {
// for dependencies that are needed for development only
developmentOnly
}
dependencies {
kapt(enforcedPlatform("io.micronaut:micronaut-bom:$micronautVersion"))
kapt("io.micronaut:micronaut-inject-java")
kapt("io.micronaut:micronaut-validation")
implementation(enforcedPlatform("io.micronaut:micronaut-bom:$micronautVersion"))
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:${kotlinVersion}")
implementation("org.jetbrains.kotlin:kotlin-reflect:${kotlinVersion}")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlinxCoroutinesVersion")
implementation("io.micronaut:micronaut-runtime")
// implementation("io.micronaut.grpc:micronaut-grpc-runtime")
implementation("io.micronaut.grpc:micronaut-grpc-server-runtime:$micronautGrpcVersion")
implementation("io.micronaut.grpc:micronaut-grpc-client-runtime:$micronautGrpcVersion")
implementation("io.grpc:grpc-kotlin-stub:${grpcKotlinVersion}")
//Kafka
implementation("io.micronaut.kafka:micronaut-kafka")
//vertx
implementation("io.micronaut.sql:micronaut-vertx-mysql-client")
//implementation("io.micronaut.configuration:micronaut-vertx-mysql-client")
compile 'io.vertx:vertx-lang-kotlin:3.9.4'
//mongodb
implementation("org.mongodb:mongodb-driver-reactivestreams:4.1.1")
runtimeOnly("ch.qos.logback:logback-classic:1.2.3")
runtimeOnly("com.fasterxml.jackson.module:jackson-module-kotlin:2.9.8")
kaptTest("io.micronaut:micronaut-inject-java")
testImplementation enforcedPlatform("io.micronaut:micronaut-bom:$micronautVersion")
testImplementation("org.junit.jupiter:junit-jupiter-api:5.3.0")
testImplementation("io.micronaut.test:micronaut-test-junit5")
testImplementation("org.mockito:mockito-junit-jupiter:2.22.0")
testRuntime("org.junit.jupiter:junit-jupiter-engine:5.3.0")
testRuntime("org.jetbrains.spek:spek-junit-platform-engine:1.1.5")
}
test.classpath += configurations.developmentOnly
mainClassName = "account-control.Application"
test {
useJUnitPlatform()
}
allOpen {
annotation("io.micronaut.aop.Around")
}
compileKotlin {
kotlinOptions {
jvmTarget = '11'
//Will retain parameter names for Java reflection
javaParameters = true
}
}
//compileKotlin.dependsOn(generateProto)
compileTestKotlin {
kotlinOptions {
jvmTarget = '11'
javaParameters = true
}
}
tasks.withType(JavaExec) {
classpath += configurations.developmentOnly
jvmArgs('-XX:TieredStopAtLevel=1', '-Dcom.sun.management.jmxremote')
}
sourceSets {
main {
java {
srcDirs 'build/generated/source/proto/main/grpc'
srcDirs 'build/generated/source/proto/main/grpckt'
srcDirs 'build/generated/source/proto/main/java'
}
}
}
protobuf {
protoc { artifact = "com.google.protobuf:protoc:${protocVersion}" }
plugins {
grpc { artifact = "io.grpc:protoc-gen-grpc-java:${grpcVersion}" }
grpckt { artifact = "io.grpc:protoc-gen-grpc-kotlin:${grpcKotlinVersion}" }
}
generateProtoTasks {
all()*.plugins {
grpc {}
grpckt {}
}
}
}
in case it is relevant, here is a piece of the stub autogenerated by proto
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: transaction.proto
package com.mybank.endpoint;
/**
* Protobuf type {#code com.mybank.endpoint.DebitRequest}
*/
public final class DebitRequest extends
com.google.protobuf.GeneratedMessageV3 implements
// ##protoc_insertion_point(message_implements:com.mybank.endpoint.DebitRequest)
DebitRequestOrBuilder {
private static final long serialVersionUID = 0L;
// Use DebitRequest.newBuilder() to construct.
private DebitRequest(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
super(builder);
}
private DebitRequest() {
name_ = "";
}
#java.lang.Override
#SuppressWarnings({"unused"})
protected java.lang.Object newInstance(
UnusedPrivateParameter unused) {
return new DebitRequest();
}
#java.lang.Override
public final com.google.protobuf.UnknownFieldSet
getUnknownFields() {
return this.unknownFields;
}
private DebitRequest(
com.google.protobuf.CodedInputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
this();
...
*** First edition
#KafkaClient(
id="debit-client",
acks = KafkaClient.Acknowledge.ALL,
properties = [Property(name = ProducerConfig.RETRIES_CONFIG, value = "5")]
//How add these two properties in order to use Protobuf Serializer
//kafka.producers.*.key-serializer
//kafka.producers.*.value-serializer
)
public interface DebitProducer {
#Topic("debit")
fun sendRequestMessage(#KafkaKey key: String?, message: DebitRequest?) {
}
*** Second Edition
I tried added the serializer via application.yaml
micronaut:
application:
name: account-control
grpc:
server:
port: 8082
kafka:
producers:
product-client:
value:
serializer: io.confluent.kafka.serializers.protobuf.KafkaProtobufSerializer
gradle.build
//kafka-protobuf-serializer
implementation("io.confluent:kafka-protobuf-serializer:6.0.0")
and now I get during gradle build
Execution failed for task ':extractIncludeProto'.
> Could not resolve all files for configuration ':compileProtoPath'.
> Could not resolve com.squareup.wire:wire-schema:3.2.2.
Required by:
project : > io.confluent:kafka-protobuf-serializer:6.0.0 > io.confluent:kafka-protobuf-provider:6.0.0
> The consumer was configured to find a component, preferably only the resources files. However we cannot choose between the following variants of com.squareup.wire:wire-schema:3.2.2:
- jvm-api
- jvm-runtime
- metadata-api
All of them match the consumer attributes:
- Variant 'jvm-api' capability com.squareup.wire:wire-schema:3.2.2 declares a component, packaged as a jar:
- Unmatched attributes:
- Provides release status but the consumer didn't ask for it
- Provides an API but the consumer didn't ask for it
- Provides attribute 'org.jetbrains.kotlin.platform.type' with value 'jvm' but the consumer didn't ask for it
- Variant 'jvm-runtime' capability com.squareup.wire:wire-schema:3.2.2 declares a component, packaged as a jar:
- Unmatched attributes:
- Provides release status but the consumer didn't ask for it
- Provides a runtime but the consumer didn't ask for it
- Provides attribute 'org.jetbrains.kotlin.platform.type' with value 'jvm' but the consumer didn't ask for it
- Variant 'metadata-api' capability com.squareup.wire:wire-schema:3.2.2:
- Unmatched attributes:
- Doesn't say anything about its elements (required them preferably only the resources files)
- Provides release status but the consumer didn't ask for it
- Provides a usage of 'kotlin-api' but the consumer didn't ask for it
- Provides attribute 'org.jetbrains.kotlin.platform.type' with value 'common' but the consumer didn't ask for it
* Try:
Run with --info or --debug option to get more log output. Run with --scan to get full insights.
* Exception is:
org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':extractIncludeProto'.
at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:38)
at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.executeTask(EventFiringTaskExecuter.java:77)
at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:55)
at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:52)
at org.gradle.internal.operations.DefaultBuildOperationExecutor$CallableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:416)
at org.gradle.internal.operations.DefaultBuildOperationExecutor$CallableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:406)
at org.gradle.internal.operations.DefaultBuildOperationExecutor$1.execute(DefaultBuildOperationExecutor.java:165)
at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:250)
at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:158)
at org.gradle.internal.operations.DefaultBuildOperationExecutor.call(DefaultBuildOperationExecutor.java:102)
at org.gradle.internal.operations.DelegatingBuildOperationExecutor.call(DelegatingBuildOperationExecutor.java:36)
at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter.execute(EventFiringTaskExecuter.java:52)
at org.gradle.execution.plan.LocalTaskNodeExecutor.execute(LocalTaskNodeExecutor.java:41)
at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:370)
at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:357)
at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:350)
at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:336)
at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.lambda$run$0(DefaultPlanExecutor.java:127)
at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.execute(DefaultPlanExecutor.java:191)
at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.executeNextNode(DefaultPlanExecutor.java:182)
at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.run(DefaultPlanExecutor.java:124)
at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:48)
at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:56)
Caused by: org.gradle.api.internal.artifacts.ivyservice.DefaultLenientConfiguration$ArtifactResolveException: Could not resolve all files for configuration ':compileProtoPath'.
at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration.rethrowFailure(DefaultConfiguration.java:1265)
at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration.access$1800(DefaultConfiguration.java:141)
at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration$ConfigurationFileCollection.visitContents(DefaultConfiguration.java:1242)
at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration$ConfigurationFileCollection.visitContents(DefaultConfiguration.java:1235)
at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration.visitContents(DefaultConfiguration.java:489)
at org.gradle.api.internal.file.AbstractFileCollection.visitStructure(AbstractFileCollection.java:265)
at org.gradle.api.internal.file.CompositeFileCollection.visitContents(CompositeFileCollection.java:152)
at org.gradle.api.internal.file.AbstractFileCollection.visitStructure(AbstractFileCollection.java:265)
at org.gradle.internal.fingerprint.impl.DefaultFileCollectionSnapshotter.snapshot(DefaultFileCollectionSnapshotter.java:50)
at org.gradle.internal.fingerprint.impl.AbstractFileCollectionFingerprinter.fingerprint(AbstractFileCollectionFingerprinter.java:47)
at ...
ultPlanExecutor.java:182)
at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.run(DefaultPlanExecutor.java:124)
at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:48)
at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:56)

Spring Cloud Sleuth Rabbit integration seems to create new TraceId on send

my goal is to maintain the traceId (of a brave.Span) between a rabbitMq sender and consumer. In order to achieve this I use spring-cloud-sleuth autoconfigured in version 2.1.0.RELEASE
When creating a span and eventually sending a message over RabbitTemplate to the broker and receiving it in the same (test) application I would expect spring-cloud-sleuth to maintain the traceId between sender and consumer.
My observation is that when sending a Message over RabbitMq the traceId is not correctly appended to the headers of the message. There is indeed a traceId/context appended and submitted, but it is a new one, different from that I read when creating the span (see code below).
On the consumer the newly created (but unrelated) traceId then is correctly processed and can be read from the Tracer.
#Test
public void messaging_ShouldPreserveTraceId() {
final Span spanProbe = tracer.newTrace().name("TraceIT").start();
spanProbe.start();
final String traceIdBefore = spanProbe.context().traceIdString();
log.info("TRACE CONTEXT BEFORE: " + spanProbe.context());
log.info("TRACE ID BEFORE: " + traceIdBefore);
log.info("TRACE ID BEFORE Parent: " + spanProbe.context().parentIdString());
// send - the actual rabbitTemplate Call (in the producer) happens in the same (main) thread
try{
producer.sendAsString(ROUTING_KEY, "CONTENT");
}finally {
spanProbe.finish();
}
// consume
Awaitility.await().atMost(TEN_MINUTES).until(() -> {
assertThat(consumer.spans(), hasSize(1));
});
// assert
final Span consumerSpan = consumer.spans().get(0);
final String traceIdAfter = consumerSpan.context().traceIdString();
log.info("TRACE CONTEXT AFTER: " + consumerSpan.context());
log.info("TRACE ID AFTER: " + traceIdAfter);
assertEquals(traceIdAfter, traceIdBefore);
}
The consumer (test class field) is:
static class TraceTestListener implements MessageListener {
private final List<Span> spans = new ArrayList<>();
#Autowired
private Tracing tracing;
#Override
public void onMessage(Message message) {
log.info("---> Received MESSAGE: {}", message);
spans.add(tracing.tracer().currentSpan());
}
public List<Span> spans() {
return spans;
}
}
[main ] sl.euth.debug.boot.rabbit.trace.TraceIT.messaging_ShouldPreserveTraceId(114) - TRACE CONTEXT BEFORE: 23ca5b3b9f068716/23ca5b3b9f068716
[main ] sl.euth.debug.boot.rabbit.trace.TraceIT.messaging_ShouldPreserveTraceId(115) - TRACE ID BEFORE: 23ca5b3b9f068716
[main ] sl.euth.debug.boot.rabbit.trace.TraceIT.messaging_ShouldPreserveTraceId(116) - TRACE ID BEFORE Parent: null
[Rabbit-4 ] org.springframework.amqp.rabbit.listener.BlockingQueueConsumer$InternalConsumer.handleDelivery(897) - Storing delivery for consumerTag: 'amq.ctag-HnuJEiuRHAHTYfzypJDW6w' with deliveryTag: '1' in Consumer#6c27e700: tags=[[amq.ctag-HnuJEiuRHAHTYfzypJDW6w]], channel=Cached Rabbit Channel: AMQChannel(amqp://asdasdaa#35.243.142.228:5672/asdasdaa,2), conn: Proxy#33ebe4f0 Shared Rabbit Connection: SimpleConnection#3a88f6fb [delegate=amqp://asdasdaa#35.243.142.228:5672/asdasdaa, localPort= 58539], acknowledgeMode=AUTO local queue size=0
// Please mind how in the received message's headers a different traceId is present
[test_rabbitConsumer1] org.springframework.amqp.rabbit.listener.BlockingQueueConsumer.handle(469) - Received message: (Body:'[B#1989ac6d(byte[7])' MessageProperties [headers={X-B3-SpanId=b335bbaf06a08879, X-B3-Sampled=0, X-B3-TraceId=b335bbaf06a08879}, timestamp=Tue May 21 13:44:57 CEST 2019, contentType=text/plain; charset=utf-8, contentLength=0, receivedDeliveryMode=PERSISTENT, priority=0, redelivered=false, receivedExchange=test-exchange, receivedRoutingKey=test-routing, deliveryTag=1, consumerTag=amq.ctag-HnuJEiuRHAHTYfzypJDW6w, consumerQueue=test-queue])
[test_rabbitConsumer1] org.springframework.cloud.sleuth.log.Slf4jScopeDecorator.log(180) - Starting scope for span: b335bbaf06a08879/46a25dd87dc63878
[test_rabbitConsumer1] org.springframework.cloud.sleuth.log.Slf4jScopeDecorator.decorateScope(102) - With parent: 4663306299116113188
[test_rabbitConsumer1] sl.euth.debug.boot.rabbit.trace.TraceIT$TraceTestListener.onMessage(150) - ---> Received MESSAGE: (Body:'[B#1989ac6d(byte[7])' MessageProperties [headers={}, timestamp=Tue May 21 13:44:57 CEST 2019, contentType=text/plain; charset=utf-8, contentLength=0, receivedDeliveryMode=PERSISTENT, priority=0, redelivered=false, receivedExchange=test-exchange, receivedRoutingKey=test-routing, deliveryTag=1, consumerTag=amq.ctag-HnuJEiuRHAHTYfzypJDW6w, consumerQueue=test-queue])
[test_rabbitConsumer1] org.springframework.cloud.sleuth.log.Slf4jScopeDecorator.log(180) - Closing scope for span: b335bbaf06a08879/46a25dd87dc63878
[main ] sl.euth.debug.boot.rabbit.trace.TraceIT.messaging_ShouldPreserveTraceId(133) - TRACE CONTEXT AFTER: b335bbaf06a08879/46a25dd87dc63878
//💥 Here we would expect the traceId to be 23ca5b3b9f068716
[main ] sl.euth.debug.boot.rabbit.trace.TraceIT.messaging_ShouldPreserveTraceId(134) - TRACE ID AFTER: b335bbaf06a08879
[main ] sl.euth.debug.commons.lib.test.junit.rules.LoggingRule$1.evaluate(77) - Finished test messaging_ShouldPreserveTraceId(sl.euth.debug.boot.rabbit.trace.TraceIT) in 13102 ms

Resource does not have neither a source nor a target path. Impossible to add it to the bundle

I am trying to read .xlsx file with rules using kie api 6.
However I get this exception
java.lang.RuntimeException: Resource does not have neither a source nor a target path. Impossible to add it to the bundle. P
lease set either the source or target name of the resource before adding it.null
at org.drools.compiler.kie.builder.impl.KieFileSystemImpl.write(KieFileSystemImpl.java:83)
at com.project.watch.validator.RuleValidator.isValidRuleKieNew(RuleValidator.java:71)
at com.project.watch.validator.RuleValidator.isValidRule(RuleValidator.java:37)
at com.project.watch.core.WatchDir$ValidateFileRunnable.run(WatchDir.java:177)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:304)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:
178)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:745)
The code looks like this
try {
KieServices ks = KieServices.Factory.get();
KieFileSystem kfs = ks.newKieFileSystem();
kfs.write(ks.getResources().newInputStreamResource(Files.newInputStream(p, StandardOpenOption.READ)));
KieBuilder kb = ks.newKieBuilder(kfs);
if (kb.getResults().getMessages(Level.ERROR).size() != 0) {
logger.lifecycle("Invalid file: {}.", kb.getResults().getMessages());
return false;
}
} catch (Exception e) {
logger.lifecycle("UNEXPECTED ERROR DURING VALIDATION -------------- ", e);
return false;
}
logger.lifecycle("Valid file: {}.", p);
return true;
}
It fails on kfs.write by the way.
I also checked the path to file by displaying it in console
Attempt to process rule file: D:\PROJECT_FOLDER\project\src\testInteg\resources\rules\rule.xlsx
and it is a correct path.
What's the problem? I am using 6.3 Final version.
I recommend this mantra, assuming your String p contains the path name as shown:
FileInputStream fis = new FileInputStream( p );
kfs.write( "src/main/resources/rule.xslx",
kieServices.getResources().newInputStreamResource( fis ) );
There are some other forms for write to the KieFileSystem, but I find that this is easy to use. You may derive the rule.xslx from p, using Java's API for path names.

Jersey client - unmarshall a ClientResponse entity body of type XML to a POJO

I've read through a lot of the examples here and I still can't isolate my coding mistake. I'm trying to use the built-in Jersey-client MessageBodyReaders.
My pojo looks like this:
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "", propOrder = {"name", "complexId", "libraryList", "partitionList", "nextLinks"})
#XmlRootElement(name = "LibraryComplex")
public class YapiLibraryComplex
{
#XmlTransient LibraryComplex libComplex;
String name;
int complexId;
List<Integer> libraryList;
List<String> partitionList;
List<URI> nextLinks;
.
.
.
my service looks like this:
#Path ("/")
public class YAPIWebService
{
#Context Application yapiAppl;
#Context UriInfo uriInfo;
#GET
#Produces ("application/xml")
//#Produces ("MediaType.APPLICATION_XML")
public Response getLibraryComplex()
{
LibraryComplex libComplex = (((YAPIapplication) yapiAppl).getLibComplex());
YapiLibraryComplex yapiLibPlex;
.
.
.
return Response.ok(yapiLibPlex).build();
and my client:
public static void main(String[] args)
{ //client client = new client();
System.out.println("the beginning");
//ClientConfig cc = new DefaultClientConfig();
//cc.getClasses().add(com.sun.jersey.api.core.);
//Client c = Client.create(cc);
Client c = Client.create();
WebResource rsrc = c.resource("http://localhost:7101/");
//ClientResponse response = rsrc.get(ClientResponse.class);
ClientResponse response = rsrc.accept(MediaType.APPLICATION_XML).get(ClientResponse.class);
YapiLibraryComplex libPlex = response.getEntity(YapiLibraryComplex.class);
System.out.println("the libPlex object is " + libPlex.toString());
String entityBody = response.getEntity(String.class);
System.out.println("the response as a string is " + entityBody);
System.out.println("the status is " + response.getStatus());
System.out.println("the links are " + response.getLinks());
System.out.println("the end");
}
}
And my stack trace:
the beginning
Jul 25, 2012 6:47:22 PM com.sun.jersey.core.impl.provider.xml.SAXParserContextProvider getInstance WARNING: JAXP feature XMLConstants.FEATURE_SECURE_PROCESSING cannot be set on a SAXParserFactory. External general entity processing is disabled but other potential security related features will not be enabled. org.xml.sax.SAXNotRecognizedException: http://javax.xml.XMLConstants/feature/secure-processing at oracle.xml.jaxp.JXSAXParserFactory.setFeature(JXSAXParserFactory.java:129)
at com.sun.jersey.core.impl.provider.xml.SAXParserContextProvider.getInstance(SAXParserContextProvider.java:80)
at com.sun.jersey.core.impl.provider.xml.SAXParserContextProvider.getInstance(SAXParserContextProvider.java:54)
at com.sun.jersey.core.impl.provider.xml.ThreadLocalSingletonContextProvider$1.initialValue(ThreadLocalSingletonContextProvider.java:64)
at java.lang.ThreadLocal.setInitialValue(ThreadLocal.java:141)
at java.lang.ThreadLocal.get(ThreadLocal.java:131)
at com.sun.jersey.core.impl.provider.xml.ThreadLocalSingletonContextProvider$2.getValue(ThreadLocalSingletonContextProvider.java:77)
at com.sun.jersey.core.impl.provider.entity.XMLRootElementProvider.readFrom(XMLRootElementProvider.java:113)
at com.sun.jersey.core.provider.jaxb.AbstractRootElementProvider.readFrom(AbstractRootElementProvider.java:111)
at com.sun.jersey.api.client.ClientResponse.getEntity(ClientResponse.java:554)
at com.sun.jersey.api.client.ClientResponse.getEntity(ClientResponse.java:506)
at .tape.acs.yapi.smokeTest.main(smokeTest.java:32) Exception in thread "main" javax.ws.rs.WebApplicationException: javax.xml.bind.JAXBException: Error creating SAXSource - with linked exception: [org.xml.sax.SAXNotSupportedException: SAX feature 'http://xml.org/sax/features/external-general-entities' not supported.]
at com.sun.jersey.core.provider.jaxb.AbstractRootElementProvider.readFrom(AbstractRootElementProvider.java:115)
at com.sun.jersey.api.client.ClientResponse.getEntity(ClientResponse.java:554)
at com.sun.jersey.api.client.ClientResponse.getEntity(ClientResponse.java:506)
at .tape.acs.yapi.smokeTest.main(smokeTest.java:32) Caused by: javax.xml.bind.JAXBException: Error creating SAXSource - with linked exception:[org.xml.sax.SAXNotSupportedException: SAX feature 'http://xml.org/sax/features/external-general-entities' not supported.]
at com.sun.jersey.core.provider.jaxb.AbstractJAXBProvider.getSAXSource(AbstractJAXBProvider.java:205)
at com.sun.jersey.core.impl.provider.entity.XMLRootElementProvider.readFrom(XMLRootElementProvider.java:113)
at com.sun.jersey.core.provider.jaxb.AbstractRootElementProvider.readFrom(AbstractRootElementProvider.java:111)
... 3 more Caused by: org.xml.sax.SAXNotSupportedException: SAX feature 'http://xml.org/sax/features/external-general-entities' not supported.
at oracle.xml.parser.v2.NonValidatingParser.setFeature(NonValidatingParser.java:1975)
at oracle.xml.parser.v2.SAXParser.setFeature(SAXParser.java:270)
at oracle.xml.jaxp.JXSAXParserFactory.newSAXParser(JXSAXParserFactory.java:92)
at com.sun.jersey.core.provider.jaxb.AbstractJAXBProvider.getSAXSource(AbstractJAXBProvider.java:201)
... 5 more Process exited with exit code 1.

Quartz JDBCJobstore doesn't work

I have downloaded Quartz and I am trying to run a sample.
I have a sample that uses JDBCJobStore which doesn't work but this sample works fine with RAMJobStore.
Just when I choose JDBCJobStore and exception get raised.
I am using quartz-1.6.5.
code:
package test;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.SimpleTrigger;
import org.quartz.Trigger;
public class ReportRunner {
public static void main(String[] args) {
try {
SchedulerFactory schedFact = new org.quartz.impl.StdSchedulerFactory();
Scheduler sched = schedFact.getScheduler();
sched.start();
JobDetail jobDetail = null;
SimpleTrigger trigger2 = null;
jobDetail = new JobDetail("Income Report", "Report Generation",
QuartzReport.class);
jobDetail.getJobDataMap().put("type", "FULL");
jobDetail.setDurability(true);
trigger2 = new SimpleTrigger("Income Report", "Report Generation");
trigger2.setStartTime(new java.util.Date(
System.currentTimeMillis() + 4000));
trigger2.setRepeatInterval(5000);
trigger2.setRepeatCount(100);
sched.scheduleJob(jobDetail, trigger2);
} catch (Exception e) {
e.printStackTrace();
}
}
}
package test;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
public class QuartzReport implements Job {
public void execute(JobExecutionContext cntxt) throws JobExecutionException {
System.out.println("Generating report - "
+ cntxt.getJobDetail().getJobDataMap().get("type"));
}
}
config file:
org.quartz.scheduler.instanceName = Sched1
org.quartz.scheduler.instanceId = 1
org.quartz.scheduler.rmi.export = false
org.quartz.scheduler.rmi.proxy = false
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 3
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
org.quartz.jobStore.tablePrefix = QRTZ_
org.quartz.jobStore.dataSource = myDS
org.quartz.dataSource.myDS.driver = com.mysql.jdbc.Driver
org.quartz.dataSource.myDS.URL = jdbc:mysql://192.168.0.4:3306/conference
org.quartz.dataSource.myDS.user = root
org.quartz.dataSource.myDS.password =root
org.quartz.dataSource.myDS.maxConnections 5
this the excpetion showd in runtime , it was logged
org.quartz.JobPersistenceException: Couldn't acquire next trigger: Field 'PRIORITY' doesn't have a default value [See nested exception: java.sql.SQLException: Field 'PRIORITY' doesn't have a default value]
at org.quartz.impl.jdbcjobstore.JobStoreSupport.acquireNextTrigger(JobStoreSupport.java:1778)
at org.quartz.impl.jdbcjobstore.JobStoreTX.acquireNextTrigger(JobStoreTX.java:1218)
at org.quartz.core.QuartzSchedulerThread.run(QuartzSchedulerThread.java:233)
* Nested Exception (Underlying Cause) ---------------
java.sql.SQLException: Field 'PRIORITY' doesn't have a default value
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1056)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:957)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3376)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3308)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1837)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:1961)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2543)
at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1737)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2022)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1940)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1925)
at org.apache.commons.dbcp.DelegatingPreparedStatement.executeUpdate(DelegatingPreparedStatement.java:102)
at org.quartz.impl.jdbcjobstore.StdJDBCDelegate.insertFiredTrigger(StdJDBCDelegate.java:3360)
at org.quartz.impl.jdbcjobstore.JobStoreSupport.acquireNextTrigger(JobStoreSupport.java:1771)
at org.quartz.impl.jdbcjobstore.JobStoreTX.acquireNextTrigger(JobStoreTX.java:1218)
at org.quartz.core.QuartzSchedulerThread.run(QuartzSchedulerThread.java:233)
547 [QuartzScheduler_MyClusteredScheduler-NON_CLUSTERED_MisfireHandler] DEBUG org.quartz.impl.jdbcjobstore.SimpleSemaphore - Lock 'TRIGGER_ACCESS' retuned by: QuartzScheduler_MyClusteredScheduler-NON_CLUSTERED_MisfireHandler
java.sql.SQLException: Field
'PRIORITY' doesn't have a default
value
I guess you can tell where the problem lies by seeing the exception above.
I tried with Quartz 1.6.5 and I did't found any result, but it with with Quartz 1.5., I guess there might be some bug in 1.6.5 for JDBC jobstore.
Mohammad
I had a similar problem, and it was my bad.. because I was using version 2.1.1 and I created tables from docs of 2.2.1, I updated the version in Maven and it is working fine now.