drools linkage error with multiple threads - multithreading

I have a junit test case which creating two threads to run a application. In this application, there is a method updateStatus which used for fire drools rules. And in this rules file, I have some functions like next :
function Object updateItem() {
.....
}
function boolean isNullOrEmpty(Object obj) {
...
}
function Object getValueFromFact(Object obj) {
....
}
I restart my tomcat, run this unit test, but one thread failed, the error was :
org.apache.cxf.interceptor.Fault: loader (instance of org/drools/rule/JavaDialectRuntimeData$PackageClassLoader): attempted duplicate class definition for name: "com/icil/sofs/booking/rules/GetValueFromFact"
'getValueFromFact' is a function which defined in rules file.
then run it again without restart tomcat, there is no error. then run third time without restart tomcat, there is no error too.
after tried, i found that the 'duplicate class' error only happened at the first time running after restarting tomcat.
i also found that at the first time, 2 threads are execute 'knowldegeSession.execute()' at the "same time", but 2 threads are run 'knowledgeSession.execute()' in sequence at 2nd time and 3rd time.
so why this error 'duplicate class definition' always happened at the first time running after restart tomcat?
and why the error is the function 'getValueFromFact'(this is the 3rd function in rules file) but not the first function 'updateItem'(this is the first function in rules file)?
thanks in advance!

Because there are multiple threads are running 'execute()', and they are loading functions at the 'same time', so this error thrown out.
When calling 'addKnowledgePackages()', drools will load rules, but the functions may not be loaded at this time, they may be loaded when calling 'execute()'.
After debugging, i found that drools will load functions if rules conditions use mvel expression instead of java expression when calling 'addKnowldegePackages()'.
I am using drools 5.5.0.Final, I cannot upgrade drools to 6.0 at present because 6.0 has big difference. But I have to figure out a solution as this problem need to be fixed as soon as possible :
Make your code 'addKnowledgePackages()' can be run when tomcat start, e.g. put it in a static block, as well as change your rules to use mvel expression rather than java expression.

Related

Binding Exception with Ninject

We have a central logging component which I am now trying to use in a WebJob that I am developing. I am basically following this example. My Activator is identical, I have the bindingModule that has my Bind statements in it. One thing I have done differently here is to use the method versions:
Kernel.Bind(typeof(IExternalSystemLogger)).To(typeof(ExternalSystemLogger));
instead of the generic versions in the example. I currently have constructor injection implemented but I have also set up the parameter injection as per the example. Which ever way I try to do this I end up with the error:
Error indexing method 'Functions.ProcessQueueMessage' ---> System.InvalidOperationException: Cannot bind parameter
or
a null reference exception (with parameter injection). Further into the error I am told that
Make sure the parameter Type is supported by the binding
which is the part that I am finding it difficult to resolve. I have looked at the available method calls on the config object available in WebJob.program but none seems to work. What is it I need to call so that I am correctly resolving my type when I am using a QueueTrigger or BlobTrigger?

Elasticsearch 5.2 unit tests

I am writing unit tests for ES5.2, and am having some issues. I need to create a client which connects to a local node for running tests, so I use
esClient = new PreBuiltTransportClient(settings)
.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("localhost"), 9300));
This causes problems
java.lang.IllegalStateException: running tests but failed to invoke RandomizedContext#getRandom
So then I used an annotation on my unit test classes as
#RunWith(com.carrotsearch.randomizedtesting.RandomizedRunner.class)
but this gave me an error
SEVERE: 2 threads leaked from TEST scope at {method_name}):
1) Thread[id=36, name={project_name}writer-thread-0, state=WAITING, group={project_name}-writer]
And the unit tests threw errors as
org.mockito.exceptions.misusing.WrongTypeOfReturnValue
I tried to use the annotation as below on the unit test class
#ThreadLeakScope(ThreadLeakScope.Scope.NONE)
That got rid of some error messages, but there were still concurrency issues in the code.
Anyone knows how to handle this? Is there some explicit thread safety methods I should use?
Excluding com.carrotsearch.randomizedtesting:randomizedtesting-runner from dependencies works.
Example (build.gradle):
dependencies {
testCompile(project(path:':other-project')) {
exclude group:"com.carrotsearch.randomizedtesting", module:"randomizedtesting-runner"
}
}
Why?
If you have randomizedtesting-runner in your classpath, ES will load it:
https://github.com/elastic/elasticsearch/blob/7.10/server/src/main/java/org/elasticsearch/common/Randomness.java#L55
And use it:
https://github.com/elastic/elasticsearch/blob/7.10/server/src/main/java/org/elasticsearch/common/Randomness.java#L102

Azure Function: "Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information"

I have an F# Azure Function that is failing, in a bizarre way, and don't know how to approach fixing the issue. I created a minimum repro of the actual case below. The test function is manually triggered and uses FSharp.Compiler.Service as a dependency, as specified in the project.json below:
{
"frameworks": {
"net46":{
"dependencies": {
"FSharp.Compiler.Service": "11.0.6"
}
}
}
}
The run.fsx file looks like this:
open System
open Microsoft.FSharp.Compiler
open Microsoft.FSharp.Compiler.Ast
open Microsoft.FSharp.Compiler.Interactive.Shell
let Run(input: string, log: TraceWriter) =
// code here that uses FsiEvaluationSession
// and runs just fine
log.Info "I RAN"
So far, so good. The part that baffles me is that if I add the following function above Run,
// same dependencies as before
open Microsoft.FSharp.Compiler.Interactive.Shell
let foo (longIdent:LongIdent) =
// version 1
// "FOO"
// version 2
// longIdent.ToString ()
// version 3
longIdent |> List.map string
let Run(input: string, log: TraceWriter) =
// same as before
Uncommenting section 1 alone works fine, uncommenting section 2 alone works fine, uncommenting section 3 causes hell to break loose. The function compiles, but running it causes the following exception:
Exception while executing function: Functions.fsc-1. mscorlib: Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information.
... which is puzzling to me, because
foo isn't even called anywhere
the signature and the 2nd version both use LongIdent, so this type doesn't seem to be the source of the problem.
Any suggestion on how to approach the problem, and what the problem itself might be, would be very appreciated - I don't even know where to start, and the same code runs perfectly fine in a local script.
I believe the reason for this is that Azure Functions SDK depend on FSharp.Compiler.Service (FCS) version 9.0.1. This means that when you try to load a different version of FCS, you will get the already loaded version 9.0.1.
This works as long as the public API of the FCS version you are using matches the public API of version 9.0.1, but when there are differences, it will crash, because your code assumes that the public API looks different. I suppose this might be triggering the issue here, although I'm not 100% sure how (possibly, LongIdent is now a different thing than it was in version 9.0.1?)
The very same issue used to happen with FAKE, which also bundles FCS and prevented loading of different versions. One of the options is to rename the assembly to avoid the clash.
I also got the same error, I solved it by doing the following workaround, please refer if it works for you also.
Right-click on the Project and select properties.
Goto Debug tab and create a profile with the reference to the below
screenshot.
Note: Replace UserName with your username.

Output resources using Groovy ASTTransformer

I've written a number of Java annotation processors that write some arbitrary data to text files that will be included in my class directory / jar file. I typically use code that looks like this:
final OutputStream out = processingEnv
.getFiler()
.createResource(StandardLocation.CLASS_OUTPUT, "", "myFile")
.openOutputStream();
I'm trying to do something similar in a groovy ASTTransformation. I've tried adding a new source file but that (expectedly) must be valid groovy. How do I write arbitrary resources from an ASTTransformation? Is it even possible?
As part of implementing your ASTTransformation, you need to implement the void visit(ASTNode[] nodes, SourceUnit source) method. In it you can call source.getConfiguration().getTargetDirectory() and it will return your build output directory, e.g. /Users/skissane/my-groovy-project/build/classes/groovy/main). You can then write your resources into there, and whatever is packaging them into the JAR (such as Gradle) should pull them from that.
In my case, I wanted to delay writing the resources until OUTPUT phase – since I was creating META-INF/services files, and I wanted to wait until I'd seen all the annotated classes before writing them, or else I'd be repeatedly adding to them for each annotated class – so I also implemented CompilationUnitAware, and then in my setCompilationUnit method I call unit.addPhaseOperation() and pass it a method reference to run during OUTPUT. Note, if you are using a local ASTTransformation, setCompilationUnit will be called multiple times (each time on a new instance of your transformation class); to avoid adding the phase operation repeatedly, I used a map in a static field to track if I'd seen this CompilationUnit before or not. My addPhaseOperation method is called once per an output class, so I used a boolean field to make sure I only wrote the resource files out once.
Doing this caused a warning to be printed:
> Task :compileGroovy
warning: Implicitly compiled files were not subject to annotation processing.
Use -implicit to specify a policy for implicit compilation.
1 warning
Adding this to build.gradle made the warning go away:
compileGroovy {
options.compilerArgs += ['-implicit:none']
}

How to use the method named bindThread in StandardContext class?

Because I found the method named bindThread() is invoked multiple times at class named StandardContext in Tomcat 7 source code, especially in the method named startInternal(). I do not understand why need to call this method multiple times.
Actually the bindThread() is set the thread context classloader, but I don't konw why still use bindThread() and unbindThread() method pair in the startInternal() invoke multiple times.
Web application start and stop normally happens with the container class loader in effect. Some parts of the start (and stop) process (e.g. firing the application listeners) needs to take place with the web application class loader in effect. bindThread() and unbindThread() are the methods that switch to the web application class loader and back again respectively. The various elements of start and stop have to happen in a specific order so it is necessary to switch back and forth between class loaders.

Resources