Hazelcast's executor service and replacing java classloaders - classloader

To send tasks to other members of a cluster, our implementation does:
hazelcastInstance.getExecutorService("ourname").submitToMembers(new CallableTask<>(task), members);
Our implementation uses a plugin system. When a plugin is (re)started, it will use a new ClassLoader instance, specific to that plugin.
We are experiencing problems with plugins that are issuing cluster tasks, and get reloaded. Specifically, it appears that when a plugin is reloaded on a cluster node that has once executed a task that was using classes provided by that plugin, subsequent tasks that arrive at that cluster node will cause ClassCastException ("X cannot be cast to X").
Our hypothesis: It appears as if Hazelcast is keeping a reference to the ClassLoader it used to instantiate classes for the execution of the first task, which prevents that ClassLoader to be garbage collected when we unload the plugin. That old ClassLoader appears to be used for the execution of the second task, where we would prefer/expect the new ClassLoader to be used. As there are now instances of the same class loaded by different ClassLoaders, ClassCastExceptions occur.
Is there any truth to this? How can we resolve these issues?

Related

multiple embedded process engine instances using shared database across multiple applications in camunda?

Hello every one I am trying my hands on camunda and would like to say so far the tool seems awesome, but one thing I can't figure out is what shall happen when I bootstrap a process engine (with the same name) across multiple different applications. such as imagine this code is written in many applications but the camunda database url is same in processes.xml which basically means same processes.xml is read for each process application.
// instantiate the process application
MyProcessApplication processApplication = new MyProcessApplication();
// deploy the process application
processApplication.deploy();
// interact with the process engine
ProcessEngine processEngine = BpmPlatform.getDefaultProcessEngine();
processEngine.getRuntimeService().startProcessInstanceByKey(...);
// undeploy the process application
processApplication.undeploy();
Where the class MyProcessApplication could look like this:
#ProcessApplication(
name="my-app",
deploymentDescriptors={"path/to/my/processes.xml"}
)
public class MyProcessApplication extends EmbeddedProcessApplication {
}
now if I instantiate a process instance via the repository service in one application will I be able to reference it another application if I query for it via the repository service? cause I think repository service is accessed via ProcessEngine and surely the process engine object in another application is different from the one that started the process instance? right? but the database is shared so will process instance be available? need help as I cant get my head around this may be i am missing some fundamental knowledge so please do enlighten me.

Why do embedded Jetty examples do server.dump(System.err)?

All the examples of embedded Jetty I see do server.dump(System.err). I can't find any docs on what that does or why.
When you see server.dump(System.err) this is a dump of the state of the Server object to the System.err console appendable.
Jetty operates on a LifeCycle model, where every component can be started and stopped and has the ability to track its state.
The Server object is a specialized ContainerLifeCycle which operates like all other LifeCycle objects but also has child beans that follow the LifeCycle behaviors.
The call server.dump(System.err) is actually the ContainerLifeCycle.dump(Appendable) call for the Server.
This top level Server dump is called The Jetty Dump Tool.
See https://www.eclipse.org/jetty/documentation/current/jetty-dump-tool.html for details, including a sample output.

Unable to launch task from a spring cloud data flow stream

I registered my task app in Spring Cloud Data Flow, created a definition for it and the status shows 'unknown'. I created the stream and trying to launch the task through task-sink and I get an error:
java.lang.IllegalStateException: failed to resolve MavenResource:
How to launch a task from the task-sink? Am I missing something? Any help is appreciated. Another question I have is how do I access the payload sent via TaskLaunchRequest in my task?
S1 http | step1: transformer-rabbit | log
S2 :S1.step1 > filter --expression=payload.contains('CUSTADDRMODRQ_V15') | task-processor | task-sink
task-sink is launching the task provided by the uri in the TaskLaunchRequest. It is looking for the resource as shown in the log
OUT Using manager EnhancedLocalRepositoryManager with priority 10.0 for /home/vcap/.m2/repository
OUT Using transporter HttpTransporter with priority 5.0 for https://repo.spring.io/libs-snapshot and finally failing.
The task is deployed in our repository and as mentioned I registered and created the definition for it as well.
This one is in cf environment and I am using SCDF server 1.0.0.M4.
In the application.properties for the task-sink i am providing maven.remote.repositories.snapshots.url=**
task create fis-ifx-event-task --definition "fis-event-task"
My goal is launching the task from the stream.
Thanks for the information. I am in fact using the BUILD-SNAPSHOT as I am unable to enable taks in 1.0.0M4 version. Here is the one I am using spring-cloud-dataflow-server-cloudfoundry-1.0.0.BUILD-20160808.144306-116. I am able to register and create task definitions. The status of the task definition is showing as 'unknown' even when I am using the sample task module provided by your team. But when I initiate the flow of the stream and when task-sink tries to launch the task, it is unable to find the maven resource. When I create the task definition, does the task module gets deployed? I don't see any app in Pivotal Apps Manager. As mentioned earlier, I provided maven.remote.repositories.snapshot.url in the application.properties file for the task-sink application. Another thing I observed is when I launch the task manually from dataflow shell it gives an error CF-UnprocessableEntity(10008): The request is semantically invalid: Unknown field(s): 'staging_disk_in_mb', 'staging_memory_in_mb' and also a message saying 'Source is empty'. Presently the task is supposed to print the timestamp and is not dependent on any input.
TaskProcessor code:
#EnableBinding(Processor.class)
#EnableConfigurationProperties(TaskProcessorProperties.class)
public class TaskProcessor {
#Autowired
private TaskProcessorProperties processorProperties;
public TaskProcessor() {
}
#Transformer(inputChannel = Processor.INPUT, outputChannel = Processor.OUTPUT)
#ELI(level = "info", eventType = ELIEventType.INBOUND)
public Object setupRequest(String message) {
Map<String, String> properties = new HashMap<String, String>();
properties.put("payload", message);
TaskLaunchRequest request = new TaskLaunchRequest(processorProperties.getUri(), null, properties, null);
return new GenericMessage<>(request);
}
}
TaskSink code:
#SpringBootApplication
#EnableTaskLauncher
#EnableBinding(Sink.class)
#EnableConfigurationProperties(TaskSinkProperties.class)
public class FisIfxEventTaskSinkApplication {
public static void main(String[] args) {
SpringApplication.run(FisIfxEventTaskSinkApplication.class, args);
}
}
I provided the stream I am using earlier in the post. Sink is receiving the TaskLaunchRequest with uri and payload as you can see here and unable to launch the task.
OUT registering [40, java.io.File] with serializer org.springframework.integration.codec.kryo.FileSerializer
2016-08-10T16:08:55.02-0600 [APP/0]
OUT Launching Task for the following resource TaskLaunchRequest{uri='maven://com.xxx:fis.ifx.event-task:jar:1.0-SNAPSHOT', commandlineArguments=[], environmentProperties={payload={"statusCode":0,"fisT
opic":"CustomerDataUpdated","payloadId":"CUSTADDRMODR``Q_V15","customerIds":[1597304]}}, deploymentProperties={}}
Before I begin, you have a number of questions here. In the future, it's better to break them up into multiple questions so that they are easier to find by other users and easier to answer. That being said:
A little context on the current state of things
In order to understand how things will work, it's important to understand the current state of things. The current releases of the software involved are:
Pivotal Cloud Foundry (PCF) - 1.7.12. This version is required for any task support.
Spring Cloud Task (SCT) - 1.0.2.RELEASE
Spring Cloud Data Flow CF (SCDF) - 1.0.0.BUILD-SNAPSHOT (current as of the date of this post).
Currently PCF 1.7.12+ has all the capabilities to run tasks. You can create v3 applications (the type of application used to launch a task), run it as a task, etc. However, the tooling around that functionality is not currently complete. There is no support for v3 applications in Apps Manager or the CLI. There is a plugin for the CLI that is more of a dev tool that can be used to help with some functions (it will show you logs, etc), but it is not fully functional and requires a specific version of the CLI to work [1]. This is one of the reasons that the task functionality within PCF is still considered experimental.
Spring Cloud Task is currently GA and supports all the functionality needed to effectively run tasks on CF. However, it's important to note that SCT doesn't handle orchestration so the actual launching of tasks on CF is the responsibility of either the user, or Spring Cloud Data Flow (the easier route).
Spring Cloud Data Flow's Cloud Foundry server implementation currently has functionality to launch tasks on PCF in the latest snapshots. We have validated this against 1.7.12 as well as the development branch of 1.8.
The task workflow within SCDF
Tasks are fundamentally different from stream applications within the context of SCDF. When you create a stream definition, you are given the option to deploy it. What this does is it actually downloads the Spring Boot über jars and deploys them to PCF as long running processes. If they go down, PCF, will relaunch them as expected, etc.
Tasks on the other hand, are not deployed. They are launched. The difference is that while you create a task definition, there is nothing deployed until you click launch. And when the task completes, the software is shut down and cleaned up. So while a stream definition may have states, it's really a one to one relationship between the definition and the deployed software. Where with a task, you can launch a task definition as many times as you want.
Your issues
Reading through your post, I see a few things that you are struggling with. Let me see if I can help:
Task Definitions within SCDF and launching them via a stream - When launching a task from a stream, the task registry within SCDF is not used. The sink expects the URL for the resource to be within the TaskLauchRequest.
Apps Manager and tasks - As mentioned above, there is no support for v3 applications in Apps Manager yet so you won't be able to see your tasks there.
Viewing the logs - In order to debug what's going wrong with launching your task on CF, you're going to want to view the logs. To do so, use the v3 CLI plugin mentioned above to view them. It's important to note that you can only tail live logs with the plugin, not view logs that have previously been rendered. Because of that, when testing, you'll want to tail the logs as soon as the app is created, before it's launched.
Error in SCDF Shell - The error you received from the SCDF shell (CF-UnprocessableEntity(10008):...) leads me to wonder if you have both the correct version of PCF (1.7.12+) and the correct version of the following other libraries:
spring-cloud-deployer-cloudfoundry - The latest snapshots
cf-java-client - 2.0.0.M10+
reactor-core - 3.0.0.RC1+
I hope this helps!
[1] https://github.com/cloudfoundry/v3-cli-plugin
Task support is not available in 1.0.0.M4 release of SCDF's CF-server. In this release, the task commands/REST-APIs should be disabled - see here. And for that reason, you wouldn't see any docs related to Tasks in the 1.0.0.M4 reference guide.
That said, the Task support is available/enabled in the BUILD-SNAPSHOT release. If you're locally building the CF-server and upon pushing it to CF, you could take advantage the task commands in the shell to create and launch task definitions.

CloudFoundry Instance Environment Variable?

I have a Java web app that persists some things to a database and I would like to know what instance processed the order. A quick google and SO search wasn't fruitful in answering my question:
Is there an environment variable or something that my application can use to glean an instance number from for persisting?
I assume that by "what instance" you mean that you have multiple instances of your Java application, and you want some way of knowing which of the multiple instances actually made the request to the database.
Googling "Cloud Foundry Instance Environment Variable" leads me to this first result. You can see one of the listed variables is CF_INSTANCE_INDEX. Those docs are for Pivotal's hosted Cloud Foundry service, I guess the OSS docs have worse SEO, but they also document this.
Do note that application instances are ephemeral. Instance #0 might be killed and restarted for any number of reasons (usually either because your application crashes, or the underlying application execution software/OS are being upgraded in a rolling deploy fashion so your instances are being transparently moved around to avoid downtime), in which case the new instance #0 will obviously be an entirely different process, possibly running on a different machine, in a different datacenter.
From the logs, you can see the APP instance
2015-11-13T11:44:42.000+00:00 [App/0] OUT 11:44:42.675 [main] INFO blah blah
2015-11-13T11:45:42.000+00:00 [App/1] OUT 11:45:42.676 [main] INFO blah2
here App/0 is instance 0 & App/1 is instance 1.
Or if you want to access the instance in the code,
Look out for the env var, CF_INSTANCE_*
eg; CF_INSTANCE_INDEX, CF_INSTANCE_IP, CF_INSTANCE_PORT etc

Using JDO in Elastic Beanstalk results in ClassNotPersistenceCapableException

I implemented an application with Elastic Beanstalk. Since some classes shall be persisted, I use (Apache's) JDO annotations in combination with DataNucleus.
When running the application on a local server everything works fine, meaning I can persist plain old Java objects to the connected Amazon RDS. When deploying the same application to Elastic Beanstalk I receive following error message:
org.datanucleus.api.jdo.exceptions.ClassNotPersistenceCapableException: The class "edu.kit.aifb.cloudcampus.dom.mgmt.Dozent" is not persistable. This means that it either hasnt been enhanced, or that the enhanced version of the file is not in the CLASSPATH (or is hidden by an unenhanced version), or the Meta-Data/annotations for the class are not found.
NestedThrowables:
org.datanucleus.exceptions.ClassNotPersistableException: The class "edu.kit.aifb.cloudcampus.dom.mgmt.Dozent" is not persistable. This means that it either hasnt been enhanced, or that the enhanced version of the file is not in the CLASSPATH (or is hidden by an unenhanced version), or the Meta-Data/annotations for the class are not found.
org.datanucleus.api.jdo.NucleusJDOHelper.getJDOExceptionForNucleusException(NucleusJDOHelper.java:380)
org.datanucleus.api.jdo.JDOPersistenceManager.jdoMakePersistent(JDOPersistenceManager.java:731)
org.datanucleus.api.jdo.JDOPersistenceManager.makePersistent(JDOPersistenceManager.java:751)
I am wondering why this is happening, since I have programmaticaly enhanced my classes with following lines of code
public void enhanceJDOClasses(String...clazzes) {
JDOHelper.getEnhancer().addClasses(clazzes).enhance();
}
Is there any recommended way to handle this in another way or did anybody experience similar exceptions? Any help is appreciated.
So the enhanced version of the class is not in the current classLoader. That command doesn't put it there, just enhances the classes, and once a class (unenhanced) is loaded in a ClassLoader it can't be replaced. You can however set the classLoader to the enhancer