Skip to content

Commit

Permalink
DROOLS-1231 - Container is not upgraded until restarted
Browse files Browse the repository at this point in the history
  • Loading branch information
mswiderski committed Jul 21, 2016
1 parent 86e0dea commit 1328793
Show file tree
Hide file tree
Showing 28 changed files with 540 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -86,4 +86,6 @@ public class KieServerConstants {
public static final String CAPABILITY_BPM = "BPM"; // Business Process Management
public static final String CAPABILITY_BPM_UI = "BPM-UI"; // Business Process Management UI
public static final String CAPABILITY_BRP = "BRP"; // Business Resource Planning

public static final String FAILURE_REASON_PROP = "failure-reason";
}
Original file line number Diff line number Diff line change
Expand Up @@ -449,7 +449,7 @@ protected Object mapObject(JsonParser jp, DeserializationContext ctxt) throws IO
} else {
if (isFullyQualifiedClassname(field1)) {
try {
Object value = deserializeObjectMapper.readValue(jp, Class.forName(field1, true, classLoader));
Object value = deserializeObjectMapper.readValue(jp, classLoader.loadClass(field1));
jp.nextToken();

return value;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,13 @@

package org.kie.server.api.marshalling.xstream;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.mapper.MapperWrapper;
import org.drools.core.runtime.help.impl.XStreamXML;
import org.kie.server.api.commands.CallContainerCommand;
import org.kie.server.api.commands.CommandScript;
Expand Down Expand Up @@ -60,10 +64,25 @@ public class XStreamMarshaller

private XStream xstream;
private ClassLoader classLoader;
private Map<String, Class> classNames = new HashMap<String, Class>();

public XStreamMarshaller( final Set<Class<?>> classes, final ClassLoader classLoader ) {
this.classLoader = classLoader;
this.xstream = XStreamXML.newXStreamMarshaller( new XStream( ) );
this.xstream = XStreamXML.newXStreamMarshaller( new XStream( ) {

protected MapperWrapper wrapMapper(MapperWrapper next) {
return new MapperWrapper(next) {
public Class realClass(String elementName) {

Class customClass = classNames.get(elementName);
if (customClass != null) {
return customClass;
}
return super.realClass(elementName);
}
};
}
});
this.xstream.setClassLoader( classLoader );

this.xstream.registerConverter(new BendableScoreXStreamConverter());
Expand Down Expand Up @@ -110,6 +129,7 @@ public XStreamMarshaller( final Set<Class<?>> classes, final ClassLoader classLo
if (classes != null) {
for (Class<?> clazz : classes) {
this.xstream.processAnnotations( clazz );
this.classNames.put(clazz.getName(), clazz);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ public interface KieServerExtension {

void createContainer(String id, KieContainerInstance kieContainerInstance, Map<String, Object> parameters);

void updateContainer(String id, KieContainerInstance kieContainerInstance, Map<String, Object> parameters);

boolean isUpdateContainerAllowed(String id, KieContainerInstance kieContainerInstance, Map<String, Object> parameters);

void disposeContainer(String id, KieContainerInstance kieContainerInstance, Map<String, Object> parameters);

List<Object> getAppComponents(SupportedTransports type);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ protected ServiceResponse<ExecutionResults> callContainer(String containerId, St
if (ks != null) {
Class<? extends Command> type = BatchExecutionCommandImpl.class;
if (classType != null && !classType.isEmpty()) {
type = (Class<? extends Command>) Class.forName(classType, true, kci.getKieContainer().getClassLoader());
type = (Class<? extends Command>) kci.getKieContainer().getClassLoader().loadClass(classType);
}

Command<?> cmd = kci.getMarshaller( marshallingFormat ).unmarshall(payload, type);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,16 @@ public void createContainer(String id, KieContainerInstance kieContainerInstance
// no-op
}

@Override
public void updateContainer(String id, KieContainerInstance kieContainerInstance, Map<String, Object> parameters) {
// no-op
}

@Override
public boolean isUpdateContainerAllowed(String id, KieContainerInstance kieContainerInstance, Map<String, Object> parameters) {
return true;
}

@Override
public void disposeContainer(String id, KieContainerInstance kieContainerInstance, Map<String, Object> parameters) {
// no-op
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -640,8 +640,26 @@ public ServiceResponse<ReleaseId> updateContainerReleaseId(String id, ReleaseId
// would likely not be worth it. At this point a decision was made to fail the execution if a concurrent
// call do dispose() is executed.
if (kci != null && kci.getKieContainer() != null) {


// before upgrade check with all extensions if that is allowed
KieModuleMetaData metaData = KieModuleMetaData.Factory.newKieModuleMetaData(releaseId, DependencyFilter.COMPILE_FILTER);
Map<String, Object> parameters = new HashMap<String, Object>();
parameters.put(KieServerConstants.KIE_SERVER_PARAM_MODULE_METADATA, metaData);
// process server extensions
List<KieServerExtension> extensions = context.getServerExtensions();
for (KieServerExtension extension : extensions) {
boolean allowed = extension.isUpdateContainerAllowed(id, kci, parameters);
if (!allowed) {
String message = (String)parameters.get(KieServerConstants.FAILURE_REASON_PROP);
logger.warn("Container {} (for release id {}) on {} cannot be updated due to {}", id, releaseId, extension, message);
if (messages != null) {
messages.add(new Message(Severity.WARN, message));
}
return new ServiceResponse<ReleaseId>(ServiceResponse.ResponseType.FAILURE, message);
}
logger.debug("Container {} (for release id {}) on {} ready to be updated", id, releaseId, extension);
}
kci.clearJaxbClasses();
kci.disposeMarshallers();
Results results = kci.getKieContainer().updateToVersion(releaseId);
if (results.hasMessages(Level.ERROR)) {

Expand All @@ -653,6 +671,11 @@ public ServiceResponse<ReleaseId> updateContainerReleaseId(String id, ReleaseId
logger.error("Error updating releaseId for container " + id + " to version " + releaseId + "\nMessages: " + results.getMessages());
return new ServiceResponse<ReleaseId>(ServiceResponse.ResponseType.FAILURE, "Error updating release id on container " + id + " to " + releaseId, kci.getResource().getReleaseId());
} else {
// once the upgrade was successful, notify all extensions so they can be upgraded (if needed)
for (KieServerExtension extension : extensions) {
extension.updateContainer(id, kci, parameters);
logger.debug("Container {} (for release id {}) on {} updated successfully", id, releaseId, extension);
}
// store the current state of the server
KieServerState currentState = repository.load(KieServerEnvironment.getServerId());

Expand All @@ -668,6 +691,8 @@ public ServiceResponse<ReleaseId> updateContainerReleaseId(String id, ReleaseId
currentState.setContainers(new HashSet<KieContainerResource>(containers));
repository.store(KieServerEnvironment.getServerId(), currentState);

logger.info("Container {} successfully updated to release id {}", id, releaseId);

messages.add(new Message(Severity.INFO, "Release id successfully updated for container " + id));
return new ServiceResponse<ReleaseId>(ServiceResponse.ResponseType.SUCCESS, "Release id successfully updated.", kci.getResource().getReleaseId());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public ServiceResponse<ExecutionResults> callContainer(String containerId, Strin

Class<? extends Command> type = BatchExecutionCommandImpl.class;
if (classType != null && !classType.isEmpty()) {
type = (Class<? extends Command>) Class.forName(classType, true, kci.getKieContainer().getClassLoader());
type = (Class<? extends Command>) kci.getKieContainer().getClassLoader().loadClass(classType);
}

Command<?> cmd = kci.getMarshaller( marshallingFormat ).unmarshall(payload, type);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ public void createContainer(String id, KieContainerInstance kieContainerInstance
String type = p + "." + c;
try {
logger.debug("Adding {} type into extra jaxb classes set", type);
Class<?> clazz = Class.forName(type, true, kieContainerInstance.getKieContainer().getClassLoader());
Class<?> clazz = kieContainerInstance.getKieContainer().getClassLoader().loadClass(type);

addExtraClass(extraClasses, clazz, filterRemoteable);
logger.debug("Added {} type into extra jaxb classes set", type);
Expand All @@ -116,6 +116,18 @@ public void createContainer(String id, KieContainerInstance kieContainerInstance

}

@Override
public void updateContainer(String id, KieContainerInstance kieContainerInstance, Map<String, Object> parameters) {
disposeContainer(id, kieContainerInstance, parameters);
// just do the same as when creating container to make sure all is up to date
createContainer(id, kieContainerInstance, parameters);
}

@Override
public boolean isUpdateContainerAllowed(String id, KieContainerInstance kieContainerInstance, Map<String, Object> parameters) {
return true;
}

@Override
public void disposeContainer(String id, KieContainerInstance kieContainerInstance, Map<String, Object> parameters) {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,18 @@ public void createContainer(String id, KieContainerInstance kieContainerInstance

}

@Override
public void updateContainer(String id, KieContainerInstance kieContainerInstance, Map<String, Object> parameters) {
// recreate configuration for updated container
disposeContainer(id, kieContainerInstance, parameters);
createContainer(id, kieContainerInstance, parameters);
}

@Override
public boolean isUpdateContainerAllowed(String id, KieContainerInstance kieContainerInstance, Map<String, Object> parameters) {
return true;
}

@Override
public void disposeContainer(String id, KieContainerInstance kieContainerInstance, Map<String, Object> parameters) {
if (!initialized) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
import org.jbpm.services.api.RuntimeDataService;
import org.jbpm.services.api.UserTaskService;
import org.jbpm.services.api.model.DeployedUnit;
import org.jbpm.services.api.model.ProcessInstanceDesc;
import org.jbpm.services.api.query.QueryMapperRegistry;
import org.jbpm.services.api.query.QueryService;
import org.jbpm.services.task.HumanTaskServiceFactory;
Expand All @@ -67,6 +68,7 @@
import org.kie.api.builder.model.KieSessionModel;
import org.kie.api.executor.ExecutorService;
import org.kie.api.runtime.process.ProcessInstance;
import org.kie.api.runtime.query.QueryContext;
import org.kie.api.task.TaskService;
import org.kie.api.task.UserGroupCallback;
import org.kie.internal.runtime.conf.DeploymentDescriptor;
Expand Down Expand Up @@ -351,12 +353,37 @@ public void createContainer(String id, KieContainerInstance kieContainerInstance
// add any query param builder factories
QueryParamBuilderManager.get().discoverAndAddQueryFactories(id, kieContainer.getClassLoader());

logger.info("Container {} created successfully", id);
logger.debug("Container {} created successfully by extension {}", id, this);
} catch (Exception e) {
logger.error("Error when creating container {} by extension {}", id, this);
}
}

@Override
public boolean isUpdateContainerAllowed(String id, KieContainerInstance kieContainerInstance, Map<String, Object> parameters) {
// first check if there are any active process instances
List<Integer> states = new ArrayList<Integer>();
states.add(ProcessInstance.STATE_ACTIVE);
states.add(ProcessInstance.STATE_PENDING);
states.add(ProcessInstance.STATE_SUSPENDED);
Collection<ProcessInstanceDesc> activeProcesses = runtimeDataService.getProcessInstancesByDeploymentId(id, states, new QueryContext());
if (!activeProcesses.isEmpty()) {
parameters.put(KieServerConstants.FAILURE_REASON_PROP, "Update of container forbidden - there are active process instances for container " + id);
return false;
}

return true;
}

@Override
public void updateContainer(String id, KieContainerInstance kieContainerInstance, Map<String, Object> parameters) {
// essentially it's a redeploy to make sure all components are up to date,
// though update of kie base is done only once on kie server level and KieContainer is reused across all extensions
disposeContainer(id, kieContainerInstance, parameters);

createContainer(id, kieContainerInstance, parameters);
}

@Override
public void disposeContainer(String id, KieContainerInstance kieContainerInstance, Map<String, Object> parameters) {
if (!deploymentService.isDeployed(id)) {
Expand All @@ -381,7 +408,7 @@ public void disposeContainer(String id, KieContainerInstance kieContainerInstanc
}
// remove any query param builder factories
QueryParamBuilderManager.get().removeQueryFactories(id);
logger.info("Container {} disposed successfully", id);
logger.debug("Container {} disposed successfully by extension {}", id, this);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,16 @@ public void destroy(KieServerImpl kieServer, KieServerRegistry registry) {
public void createContainer(String id, KieContainerInstance kieContainerInstance, Map<String, Object> parameters) {
}

@Override
public void updateContainer(String id, KieContainerInstance kieContainerInstance, Map<String, Object> parameters) {
// same as createContainer - no op
}

@Override
public boolean isUpdateContainerAllowed(String id, KieContainerInstance kieContainerInstance, Map<String, Object> parameters) {
return true;
}

@Override
public void disposeContainer(String id, KieContainerInstance kieContainerInstance, Map<String, Object> parameters) {
solverServiceBase.disposeSolversForContainer( id, kieContainerInstance );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@ public static void assertSuccess(ServiceResponse<?> response) {
type);
}

public static void assertFailure(ServiceResponse<?> response) {
ServiceResponse.ResponseType type = response.getType();
assertEquals("Expected FAILURE, but got " + type + "! Response: " + response, ServiceResponse.ResponseType.FAILURE,
type);
}

public static void assertResultContainsString(String result, String expectedString) {
assertTrue("Expecting string '" + expectedString + "' in result, but got: " + result, result.contains(expectedString));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.kie.server.testing;
import org.kie.server.testing.Person;

rule "Update person's id"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<kmodule xmlns="http://www.drools.org/xsd/kmodule">
<kbase name="kbase.kjar101" packages="kjar1">
<ksession name="kjar101.session" type="stateful"/>
<kbase name="kbase.kjar1" packages="kjar1">
<ksession name="kjar1.session" type="stateless"/>
</kbase>
</kmodule>
</kmodule>
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.kie.server.testing;
import org.kie.server.testing.Person;

rule "Update person's id"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<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>
<parent>
<groupId>org.kie.server.testing</groupId>
<artifactId>common-parent</artifactId>
<version>1.0.0.Final</version>
</parent>

<artifactId>container-isolation-kjar1</artifactId>
<version>1.0.2.Final</version>
<packaging>kjar</packaging>

<build>
<plugins>
<plugin>
<groupId>org.kie</groupId>
<artifactId>kie-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* Copyright 2015 Red Hat, Inc. and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.kie.server.testing;

public class Person {
private String id;

public String getId() {
return id;
}

public void setId(String id) {
this.id = id;
}

public void updateId() {
id = "Person from kjar102";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<kmodule xmlns="http://www.drools.org/xsd/kmodule">
<kbase name="kbase.kjar1" packages="kjar1">
<ksession name="kjar1.session" type="stateless"/>
</kbase>
</kmodule>
Loading

0 comments on commit 1328793

Please sign in to comment.