Is there any way to configure jms transport for axis2 client programatically? - axis2

I know how to configure jms transport within axis2.xml, but i need to configure it with my specific application properties that could be changed in runtime.

I found solution, hope it will be helpful
package com.mycompany.client.config;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import javax.naming.Context;
import org.apache.axiom.om.OMAbstractFactory;
import org.apache.axiom.om.OMAttribute;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMFactory;
import org.apache.axiom.om.OMNode;
import org.apache.axis2.AxisFault;
import org.apache.axis2.context.ConfigurationContext;
import org.apache.axis2.context.ConfigurationContextFactory;
import org.apache.axis2.description.Parameter;
import org.apache.axis2.description.ParameterInclude;
import org.apache.axis2.description.TransportInDescription;
import org.apache.axis2.description.TransportOutDescription;
import org.apache.axis2.engine.AxisConfiguration;
import org.apache.axis2.transport.TransportListener;
import org.apache.axis2.transport.TransportSender;
import org.apache.axis2.transport.jms.JMSConstants;
import org.apache.axis2.transport.jms.JMSListener;
import org.apache.axis2.transport.jms.JMSSender;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.mycompany.client.config.exceptions.ConfigurationException;
import com.mycompany.client.jms.JMSWebServiceClient;
import com.mycompany.stub.FtthRequestStub;
public class ConfigurationManager {
static Log log = LogFactory.getLog(ConfigurationManager.class);
private static final String DEFAULT_TRANSPORT_PARAMETER_NAME = "default";
public JMSWebServiceClient configureJMSClient() throws Exception {
FtthRequestStub stub;
ConfigurationContext ctx;
boolean isAuthenticationEnabled = false;
Map<String,String> jmsTransportProps = getAxisTransportConfiguration(isAuthenticationEnabled);
String url = buildUrlFromMap(jmsTransportProps);
ctx = ConfigurationContextFactory.createDefaultConfigurationContext();
//transport in
TransportListener tl = new JMSListener();
TransportInDescription transportIn = new TransportInDescription("jms");
addParameterToTransport(jmsTransportProps,transportIn);
transportIn.setReceiver(tl);
// transport out
TransportSender transportSender = new JMSSender();
TransportOutDescription transportOut = new TransportOutDescription("jms");
addParameterToTransport(jmsTransportProps, transportOut);
transportOut.setSender(transportSender);
transportSender.init(ctx, transportOut); //very important call because transport senders are not initialized during createDefaultConfigurationContext() invocation.
AxisConfiguration axisConfiguration = ctx.getAxisConfiguration();
axisConfiguration.addTransportIn(transportIn);
axisConfiguration.addTransportOut(transportOut);
stub = new FtthRequestStub(ctx,url);
String replyTo = getReplyDestination();
if(StringUtils.isNotEmpty(replyTo)) {
stub._getServiceClient().getServiceContext().setProperty(JMSConstants.JMS_REPLY_TO, replyTo);
}
JMSWebServiceClient client = new JMSWebServiceClient(stub);
return client;
}
private void addParameterToTransport(Map<String,String> jmsTransportProps,
ParameterInclude transportInOut) throws ConfigurationException {
try {
Parameter parameter = new Parameter();
parameter.setName(DEFAULT_TRANSPORT_PARAMETER_NAME);
parameter.setValue(buildParameterOMElementFromMap(DEFAULT_TRANSPORT_PARAMETER_NAME, jmsTransportProps, false));
transportInOut.addParameter(parameter);
} catch (AxisFault e) {
throw new ConfigurationException(e.getMessage());
}
}
private static OMElement createRootParameterOMElement(String name) {
OMFactory omFactory = OMAbstractFactory.getOMFactory();
OMElement defaultReceiverParameter = omFactory.createOMElement(new javax.xml.namespace.QName("parameter"));
OMAttribute nameAttribute = omFactory.createOMAttribute("name", null, name);
defaultReceiverParameter.addAttribute(nameAttribute);
return defaultReceiverParameter;
}
private static OMElement buildParameterOMElementFromMap(String rootElementName, Map<String,String> properties, boolean rootIsLocked) {
OMFactory omFactory = OMAbstractFactory.getOMFactory();
//creating root <parameter>
OMElement root = omFactory.createOMElement(new javax.xml.namespace.QName("parameter"));
OMAttribute attribute = omFactory.createOMAttribute("name", null, rootElementName);
root.addAttribute(attribute);
attribute = omFactory.createOMAttribute("locked", null, String.valueOf(rootIsLocked));
root.addAttribute(attribute);
//creating child <parameter> elements
for(String key : properties.keySet())
{
OMElement child = omFactory.createOMElement(new javax.xml.namespace.QName("parameter"));
attribute = omFactory.createOMAttribute("name", null, key);
child.addAttribute(attribute);
attribute = omFactory.createOMAttribute("locked", null, Boolean.FALSE.toString());
child.addAttribute(attribute);
OMNode text = omFactory.createOMText(properties.get(key));
child.addChild(text);
root.addChild(child);
}
return root;
}
private static String buildUrlFromMap(Map<String,String> properties) {
StringBuffer url = new StringBuffer();
url.append(JMSConstants.JMS_PREFIX);
url.append(getDestination()).append("?"); //send destination
for(String key : properties.keySet()) {
url.append(key).append("=").append(properties.get(key)).append("&");
}
return StringUtils.chop(url.toString());
}
private static String getDestination() {
return "testQueue";
}
private static String getReplyDestination() {
return "replyQueue";
}
private Map<String,String> getAxisTransportConfiguration(boolean authenticationEnabled) {
Map<String,String> properties = new HashMap<String,String>();
properties.put(JMSConstants.PARAM_CONFAC_JNDI_NAME, "QueueConnectionFactory");
properties.put(Context.INITIAL_CONTEXT_FACTORY, "org.apache.activemq.jndi.ActiveMQInitialContextFactory");
properties.put(Context.PROVIDER_URL, "tcp://localhost:61616");
if(authenticationEnabled) {
properties.put(JMSConstants.PARAM_JMS_USERNAME, "username");
properties.put(JMSConstants.PARAM_JMS_PASSWORD, "password");
}
return properties;
}
}

Related

RedissonClient is throwing StringIndexOutOfBoundsException: begin 8, end 5, length 22

I have below code for Redis Configuration, i need to use RedissonClient to flush cache after regular intervals.Using timerTask to run flush code. CacheManager and Proxy Manager is used because it is connected to bucket4j Ratelimiting code.
Connection to Docker Redis Image is successful as well. Using redisson version 3.12.5.
Following this doc: https://www.freecodecamp.org/news/rate-limiting-with-bucket4j-and-redis/
import io.github.bucket4j.distributed.proxy.ProxyManager;
import io.github.bucket4j.grid.jcache.JCacheProxyManager;
import java.util.Iterator;
import java.util.Timer;
import java.util.TimerTask;
import javax.cache.CacheManager;
import javax.cache.Caching;
import javax.cache.spi.CachingProvider;
import lombok.extern.log4j.Log4j2;
import org.ehcache.jsr107.EhcacheCachingProvider;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.redisson.jcache.configuration.RedissonConfiguration;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.utility.DockerImageName;
import static java.util.concurrent.TimeUnit.MINUTES;
import static java.util.concurrent.TimeUnit.SECONDS;
#Log4j2
#Configuration
public class RedisConfig {
private static GenericContainer redis = null;
private RedissonClient redisson;
private final Timer timer = new Timer("RedisConfig", true);
private final CleanupRedis clean = new CleanupRedis(this);
public RedisConfig(){
timer.scheduleAtFixedRate(clean, SECONDS.toMillis(2), MINUTES.toMillis(2));
}
#Bean(name = "client")
public RedissonClient client() {
Config config = new Config();
if (redis == null) {
redis = new GenericContainer<>(redisImageName()).withExposedPorts(6379);
redis.start();
}
System.setProperty("spring.redis.host", redis.getHost());
System.setProperty("spring.redis.port", redis.getMappedPort(6379).toString());
config
.useSingleServer()
.setAddress("redis://" + redis.getHost() + redis.getMappedPort(6379));
RedissonClient rdson = Redisson.create(config);
return rdson;
}
#Bean
public CacheManager cacheManager(#Qualifier("client") RedissonClient redissonClient) {
Iterator<CachingProvider> iterator =
Caching.getCachingProviders(Caching.getDefaultClassLoader()).iterator();
while (iterator.hasNext()) {
CachingProvider provider = iterator.next();
if (!(provider instanceof EhcacheCachingProvider)) {
iterator.remove();
}
}
CacheManager manager = Caching.getCachingProvider().getCacheManager();
manager.createCache("cache", RedissonConfiguration.fromConfig(redissonClient.getConfig()));
return manager;
}
private static DockerImageName redisImageName() {
return DockerImageName.parse("docker.io/redis:5.0.3-alpine")
.asCompatibleSubstituteFor("redis:5.0.3-alpine");
}
#Bean
ProxyManager<String> proxyManager(CacheManager cacheManager) {
return new JCacheProxyManager<>(cacheManager.getCache("cache"));
}
protected class CleanupRedis extends TimerTask {
private RedisConfig redisConfig;
CleanupRedis(RedisConfig redisConfig) {
this.redisConfig = redisConfig;
}
#Override
public void run() {
try {
System.out.println("Redisson client call is being made");
RedissonClient redisson = Redisson.create(client().getConfig());
System.out.println("Redisson client is not working");
redisson.getKeys().flushdb();
log.debug("Successfully cleared the Redis Cache");
redisson.shutdown();
} catch (Exception e) {
log.debug("caught exception cleanup availability: {}", e.getMessage());
}
}
}
}

Selenium grid is not working on latest selenium version

After upgrading to latest selenium, Selenium grid is giving an error for RegistrationRequest(). I am getting req.setRole(), req.setConfiguration(), etc. not found. look like RegistrationRequest() class got change in selenium new version but not sure how to use that class and modify my existing code. Any idea how to resolve this?
Here is my code,
package selenium;
import java.net.URL;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.openqa.grid.common.GridRole;
import org.openqa.grid.common.RegistrationRequest;
import org.openqa.grid.internal.utils.configuration.GridHubConfiguration;
import org.openqa.grid.internal.utils.SelfRegisteringRemote;
import org.openqa.grid.web.Hub;
import org.openqa.selenium.remote.DesiredCapabilities;
public class SeleniumGrid {
private static Hub hub;
private static URL remoteURL;
private static RegistrationRequest req = new RegistrationRequest();
private Map<String, Object> nodeConfig = new HashMap<String, Object>();
private static SelfRegisteringRemote remote = new SelfRegisteringRemote(req);
SeleniumBase sb = new SeleniumBase();
public void setup() throws Exception {
hub = getHub("localhost", 4458);
remoteURL = new URL("http://" + hub.getUrl() + ":" + 5555);
// req = setRegRequest();
req.setRole(GridRole.NODE);
req.addDesiredCapability(sb.getCapability());
List<DesiredCapabilities> dc = req.getCapabilities();
for (DesiredCapabilities c : dc) {
System.out.println("Using capabilities: " + c.toString());
}
// nodeConfig.put(req.AUTO_REGISTER, true);
nodeConfig.put(req.HUB_HOST, hub.getHost());
nodeConfig.put(req.HUB_PORT, hub.getPort());
nodeConfig.put(req.PORT, 5555);
// nodeConfig.put(RegistrationRequest.PROXY_CLASS, "org.openqa.grid.selenium.proxy.DefaultRemoteProxy");
nodeConfig.put(req.MAX_SESSION, 1);
// nodeConfig.put(RegistrationRequest.CLEAN_UP_CYCLE, 2000);
nodeConfig.put(req.REMOTE_HOST, remoteURL);
nodeConfig.put(req.MAX_INSTANCES, 1);
nodeConfig.put(req.BROWSER, "firefox");
nodeConfig.put(req.UNREGISTER_IF_STILL_DOWN_AFTER, 20000);
nodeConfig.put(req.HOST, hub.getHost());
System.out.println("Hub Port: " + hub.getHost() + hub.getPort());
System.out.println(req.HOST);
System.out.println(req.HUB_HOST);
System.out.println(req.HUB_PORT);
req.setConfiguration(nodeConfig);
remote.startRemoteServer();
remote.startRegistrationProcess();
}
public RegistrationRequest setRegRequest() {
RegistrationRequest request = new RegistrationRequest();
request.setRole(GridRole.NODE);
request.addDesiredCapability(sb.getCapability());
List<DesiredCapabilities> dc = request.getCapabilities();
for (DesiredCapabilities c : dc) {
System.out.println("Using capabilities: " + c.toString());
}
return request;
}
public Hub getHub(String host, int port) {
GridHubConfiguration config = new GridHubConfiguration();
config.setHost(host);
config.setPort(port);
Hub someHub = new Hub(config);
return someHub;
}
public void tearDown() throws Exception {
remote.stopRemoteServer();
hub.stop();
}
}
Here's a full fledged working example that starts a hub, starts a node, wires up the node to the hub, runs a test against the locally spun off hub, and then goes on to shut down the node and then the hub.
import org.openqa.grid.common.GridRole;
import org.openqa.grid.internal.utils.SelfRegisteringRemote;
import org.openqa.grid.internal.utils.configuration.GridHubConfiguration;
import org.openqa.grid.internal.utils.configuration.GridNodeConfiguration;
import org.openqa.grid.selenium.proxy.DefaultRemoteProxy;
import org.openqa.grid.web.Hub;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.openqa.selenium.remote.server.SeleniumServer;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import java.net.MalformedURLException;
import java.net.URL;
public class SeleniumGrid {
private Hub hub;
private SelfRegisteringRemote remote;
#BeforeClass
public void setup() throws Exception {
hub = getHub("localhost", 4458);
hub.start();
remote = new SelfRegisteringRemote(getNodeConfiguration());
remote.addBrowser(DesiredCapabilities.firefox(), 2);
SeleniumServer server = new SeleniumServer(remote.getConfiguration());
remote.setRemoteServer(server);
remote.startRemoteServer();
remote.startRegistrationProcess();
}
#Test
public void test() throws MalformedURLException {
URL url = new URL(hub.getUrl() + "/wd/hub");
RemoteWebDriver driver = new RemoteWebDriver(url, DesiredCapabilities.firefox());
try {
driver.get("http://www.google.com");
System.err.println("Title " + driver.getTitle());
} finally {
driver.quit();
}
}
#AfterClass
public void tearDown() throws Exception {
remote.stopRemoteServer();
hub.stop();
}
private GridNodeConfiguration getNodeConfiguration() {
GridNodeConfiguration nodeConfiguration = new GridNodeConfiguration();
nodeConfiguration.register = true;
nodeConfiguration.hub = String.format("http://%s:%d", hub.getConfiguration().host, hub.getConfiguration().port);
nodeConfiguration.port = 5555;
nodeConfiguration.proxy = DefaultRemoteProxy.class.getCanonicalName();
nodeConfiguration.maxSession = 1;
nodeConfiguration.cleanUpCycle = 2000;
nodeConfiguration.unregisterIfStillDownAfter = 20000;
nodeConfiguration.role = GridRole.NODE.toString();
nodeConfiguration.port = 5555;
nodeConfiguration.getHubHost();
nodeConfiguration.hub = String.format("http://%s:%d", hub.getConfiguration().host, hub.getConfiguration().port);
return nodeConfiguration;
}
private Hub getHub(String host, int port) {
GridHubConfiguration config = new GridHubConfiguration();
config.host = host;
config.port = port;
return new Hub(config);
}
}

Unable to initialize AdaptersAPI Object in MobileFirst V8.0 adapter which is leading to NullPointerException

I am developing the adapter in MFP V8. Below is my code to validate username and password:
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import com.ibm.mfp.adapter.api.AdaptersAPI;
import com.ibm.mfp.adapter.api.ConfigurationAPI;
import com.ibm.mfp.security.checks.base.UserAuthenticationSecurityCheck;
import com.ibm.mfp.server.registration.external.model.AuthenticatedUser;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
#Api(value = "Sample Adapter Resource")
#Path("/resource")
public class UserValidationSecurityCheck extends UserAuthenticationSecurityCheck{
private String displayName;
private String errorMsg;
private HashMap<String,Object> adapterReponse = null;
#Context
AdaptersAPI adaptersAPI;
#Override
protected AuthenticatedUser createUser() {
return new AuthenticatedUser(displayName, displayName, this.getName(),adapterReponse);
}
#Override
protected boolean validateCredentials(Map<String, Object> credentials) {
if(credentials!=null && credentials.containsKey("username") && credentials.containsKey("password")){
if (credentials.get("username")!=null && credentials.get("password")!=null) {
String username = credentials.get("username").toString();
String password = credentials.get("password").toString();
if (username.equals(password)) {
JSONObject loginParams = new JSONObject();
loginParams.put("username", username);
loginParams.put("password", password);
HttpUriRequest httpUriRequest = adaptersAPI.createJavascriptAdapterRequest("LoginAndWeeklyCertAdapter1", "login", loginParams);
try {
HttpResponse httpResponse = adaptersAPI.executeAdapterRequest(httpUriRequest);
adapterReponse = adaptersAPI.getResponseAsJSON(httpResponse);
System.out.println(adapterReponse.toString());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return true;
} else {
errorMsg = "Wrong Credentials";
}
}
}
else{
errorMsg = "Credentials not set properly";
}
return false;
}
public boolean isLoggedIn(){
return getState().equals(STATE_SUCCESS);
}
public AuthenticatedUser getRegisteredUser() {
return registrationContext.getRegisteredUser();
}
#Override
protected Map<String, Object> createChallenge() {
Map<String, Object> challenge = new HashMap<String, Object>();
challenge.put("errorMsg", errorMsg);
challenge.put("remainingAttempts", getRemainingAttempts());
return challenge;
}
#ApiOperation(value = "Returns 'Hello from resource'", notes = "A basic example of a resource returning a constant string.")
#ApiResponses(value = { #ApiResponse(code = 200, message = "Hello message returned") })
#GET
#Produces(MediaType.TEXT_PLAIN)
public String getResourceData() {
// log message to server log
logger.info("Logging info message...");
return "Hello from resource";
}
}
When I am submitting the challenge answer I am getting NullPointerException in following line:
HttpUriRequest httpUriRequest = adaptersAPI.createJavascriptAdapterRequest("LoginAndWeeklyCertAdapter1", "login");
because adaptersAPI is null. Do I have to do any extra configuration in order to make that work? How can I initialize AdaptersAPI object?
Note: The login method and the security check both are in same adapter.
Update
I investigated more of time into it and updated the code to given above and observed the following:
1. When validateCredentials() is getting called after submitting the challenge response then I am getting null value in AdapterAPI object.
2. Where as, when I am calling the getResourceData() using the mobilefirst swagger tool then I am getting an object of AdapterAPI.
We cannot inject the adapters API into a security check object(by design - not a bug). The only way we can go is to extract the logic from Adapter into a Java code, without using adapters API.

How to compile and run java source code in memory [duplicate]

This question already has answers here:
Compile code fully in memory with javax.tools.JavaCompiler [duplicate]
(7 answers)
Closed 6 years ago.
I want to treat a String as a Java file then compile and run it. In other words, use Java as a script language.
To get better performance, we should avoid writing .class files to disk.
This answer is from one of my blogs, Compile and Run Java Source Code in Memory.
Here are the three source code files.
MemoryJavaCompiler.java
package me.soulmachine.compiler;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Writer;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.tools.*;
/**
* Simple interface to Java compiler using JSR 199 Compiler API.
*/
public class MemoryJavaCompiler {
private javax.tools.JavaCompiler tool;
private StandardJavaFileManager stdManager;
public MemoryJavaCompiler() {
tool = ToolProvider.getSystemJavaCompiler();
if (tool == null) {
throw new RuntimeException("Could not get Java compiler. Please, ensure that JDK is used instead of JRE.");
}
stdManager = tool.getStandardFileManager(null, null, null);
}
/**
* Compile a single static method.
*/
public Method compileStaticMethod(final String methodName, final String className,
final String source)
throws ClassNotFoundException {
final Map<String, byte[]> classBytes = compile(className + ".java", source);
final MemoryClassLoader classLoader = new MemoryClassLoader(classBytes);
final Class clazz = classLoader.loadClass(className);
final Method[] methods = clazz.getDeclaredMethods();
for (final Method method : methods) {
if (method.getName().equals(methodName)) {
if (!method.isAccessible()) method.setAccessible(true);
return method;
}
}
throw new NoSuchMethodError(methodName);
}
public Map<String, byte[]> compile(String fileName, String source) {
return compile(fileName, source, new PrintWriter(System.err), null, null);
}
/**
* compile given String source and return bytecodes as a Map.
*
* #param fileName source fileName to be used for error messages etc.
* #param source Java source as String
* #param err error writer where diagnostic messages are written
* #param sourcePath location of additional .java source files
* #param classPath location of additional .class files
*/
private Map<String, byte[]> compile(String fileName, String source,
Writer err, String sourcePath, String classPath) {
// to collect errors, warnings etc.
DiagnosticCollector<JavaFileObject> diagnostics =
new DiagnosticCollector<JavaFileObject>();
// create a new memory JavaFileManager
MemoryJavaFileManager fileManager = new MemoryJavaFileManager(stdManager);
// prepare the compilation unit
List<JavaFileObject> compUnits = new ArrayList<JavaFileObject>(1);
compUnits.add(fileManager.makeStringSource(fileName, source));
return compile(compUnits, fileManager, err, sourcePath, classPath);
}
private Map<String, byte[]> compile(final List<JavaFileObject> compUnits,
final MemoryJavaFileManager fileManager,
Writer err, String sourcePath, String classPath) {
// to collect errors, warnings etc.
DiagnosticCollector<JavaFileObject> diagnostics =
new DiagnosticCollector<JavaFileObject>();
// javac options
List<String> options = new ArrayList<String>();
options.add("-Xlint:all");
// options.add("-g:none");
options.add("-deprecation");
if (sourcePath != null) {
options.add("-sourcepath");
options.add(sourcePath);
}
if (classPath != null) {
options.add("-classpath");
options.add(classPath);
}
// create a compilation task
javax.tools.JavaCompiler.CompilationTask task =
tool.getTask(err, fileManager, diagnostics,
options, null, compUnits);
if (task.call() == false) {
PrintWriter perr = new PrintWriter(err);
for (Diagnostic diagnostic : diagnostics.getDiagnostics()) {
perr.println(diagnostic);
}
perr.flush();
return null;
}
Map<String, byte[]> classBytes = fileManager.getClassBytes();
try {
fileManager.close();
} catch (IOException exp) {
}
return classBytes;
}
}
MemoryJavaFileManager.java
package me.soulmachine.compiler;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URI;
import java.nio.CharBuffer;
import java.util.HashMap;
import java.util.Map;
import javax.tools.FileObject;
import javax.tools.ForwardingJavaFileManager;
import javax.tools.JavaFileManager;
import javax.tools.JavaFileObject;
import javax.tools.JavaFileObject.Kind;
import javax.tools.SimpleJavaFileObject;
/**
* JavaFileManager that keeps compiled .class bytes in memory.
*/
#SuppressWarnings("unchecked")
final class MemoryJavaFileManager extends ForwardingJavaFileManager {
/** Java source file extension. */
private final static String EXT = ".java";
private Map<String, byte[]> classBytes;
public MemoryJavaFileManager(JavaFileManager fileManager) {
super(fileManager);
classBytes = new HashMap<>();
}
public Map<String, byte[]> getClassBytes() {
return classBytes;
}
public void close() throws IOException {
classBytes = null;
}
public void flush() throws IOException {
}
/**
* A file object used to represent Java source coming from a string.
*/
private static class StringInputBuffer extends SimpleJavaFileObject {
final String code;
StringInputBuffer(String fileName, String code) {
super(toURI(fileName), Kind.SOURCE);
this.code = code;
}
public CharBuffer getCharContent(boolean ignoreEncodingErrors) {
return CharBuffer.wrap(code);
}
}
/**
* A file object that stores Java bytecode into the classBytes map.
*/
private class ClassOutputBuffer extends SimpleJavaFileObject {
private String name;
ClassOutputBuffer(String name) {
super(toURI(name), Kind.CLASS);
this.name = name;
}
public OutputStream openOutputStream() {
return new FilterOutputStream(new ByteArrayOutputStream()) {
public void close() throws IOException {
out.close();
ByteArrayOutputStream bos = (ByteArrayOutputStream)out;
classBytes.put(name, bos.toByteArray());
}
};
}
}
public JavaFileObject getJavaFileForOutput(JavaFileManager.Location location,
String className,
Kind kind,
FileObject sibling) throws IOException {
if (kind == Kind.CLASS) {
return new ClassOutputBuffer(className);
} else {
return super.getJavaFileForOutput(location, className, kind, sibling);
}
}
static JavaFileObject makeStringSource(String fileName, String code) {
return new StringInputBuffer(fileName, code);
}
static URI toURI(String name) {
File file = new File(name);
if (file.exists()) {
return file.toURI();
} else {
try {
final StringBuilder newUri = new StringBuilder();
newUri.append("mfm:///");
newUri.append(name.replace('.', '/'));
if(name.endsWith(EXT)) newUri.replace(newUri.length() - EXT.length(), newUri.length(), EXT);
return URI.create(newUri.toString());
} catch (Exception exp) {
return URI.create("mfm:///com/sun/script/java/java_source");
}
}
}
}
MemoryClassLoader.java
package me.soulmachine.compiler;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
/**
* ClassLoader that loads .class bytes from memory.
*/
final class MemoryClassLoader extends URLClassLoader {
private Map<String, byte[]> classBytes;
public MemoryClassLoader(Map<String, byte[]> classBytes,
String classPath, ClassLoader parent) {
super(toURLs(classPath), parent);
this.classBytes = classBytes;
}
public MemoryClassLoader(Map<String, byte[]> classBytes, String classPath) {
this(classBytes, classPath, ClassLoader.getSystemClassLoader());
}
public MemoryClassLoader(Map<String, byte[]> classBytes) {
this(classBytes, null, ClassLoader.getSystemClassLoader());
}
public Class load(String className) throws ClassNotFoundException {
return loadClass(className);
}
public Iterable<Class> loadAll() throws ClassNotFoundException {
List<Class> classes = new ArrayList<Class>(classBytes.size());
for (String name : classBytes.keySet()) {
classes.add(loadClass(name));
}
return classes;
}
protected Class findClass(String className) throws ClassNotFoundException {
byte[] buf = classBytes.get(className);
if (buf != null) {
// clear the bytes in map -- we don't need it anymore
classBytes.put(className, null);
return defineClass(className, buf, 0, buf.length);
} else {
return super.findClass(className);
}
}
private static URL[] toURLs(String classPath) {
if (classPath == null) {
return new URL[0];
}
List<URL> list = new ArrayList<URL>();
StringTokenizer st = new StringTokenizer(classPath, File.pathSeparator);
while (st.hasMoreTokens()) {
String token = st.nextToken();
File file = new File(token);
if (file.exists()) {
try {
list.add(file.toURI().toURL());
} catch (MalformedURLException mue) {}
} else {
try {
list.add(new URL(token));
} catch (MalformedURLException mue) {}
}
}
URL[] res = new URL[list.size()];
list.toArray(res);
return res;
}
}
Explanations:
In order to represent a Java source file in memory instead of disk, I defined a StringInputBuffer class in the MemoryJavaFileManager.java.
To save the compiled .class files in memory, I implemented a class MemoryJavaFileManager. The main idea is to override the function getJavaFileForOutput() to store bytecodes into a map.
To load the bytecodes in memory, I have to implement a customized classloader MemoryClassLoader, which reads bytecodes in the map and turn them into classes.
Here is a unite test.
package me.soulmachine.compiler;
import org.junit.Test;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import static org.junit.Assert.assertEquals;
public class MemoryJavaCompilerTest {
private final static MemoryJavaCompiler compiler = new MemoryJavaCompiler();
#Test public void compileStaticMethodTest()
throws ClassNotFoundException, InvocationTargetException, IllegalAccessException {
final String source = "public final class Solution {\n"
+ "public static String greeting(String name) {\n"
+ "\treturn \"Hello \" + name;\n" + "}\n}\n";
final Method greeting = compiler.compileStaticMethod("greeting", "Solution", source);
final Object result = greeting.invoke(null, "soulmachine");
assertEquals("Hello soulmachine", result.toString());
}
}
Reference
JavaCompiler.java from Cloudera Morphlines
How to create an object from a string in Java (how to eval a string)?
InMemoryJavaCompiler
Java-Runtime-Compiler
动态的Java - 无废话JavaCompilerAPI中文指南

Use Drools 6.0 new PHREAK algorithm by using the 5.5. legacy API

Is it possible to try out the new PHREAKS algorithm but using the conventional API from Drools 5.5
* EDIT: to make the question more precise *
conventional 5.5 API
import org.drools.KnowledgeBase;
import org.drools.KnowledgeBaseFactory;
import org.drools.builder.KnowledgeBuilder;
import org.drools.builder.KnowledgeBuilderFactory;
import org.drools.builder.ResourceType;
import org.drools.io.Resource;
import org.drools.io.ResourceFactory;
import org.drools.runtime.StatefulKnowledgeSession;
instead new Drools 6 API
import org.kie.api.KieBase;
import org.kie.api.KieBaseConfiguration;
import org.kie.api.KieServices;
import org.kie.api.builder.KieBuilder;
import org.kie.api.builder.KieFileSystem;
import org.kie.api.builder.KieScanner;
import org.kie.api.builder.Message;
import org.kie.api.builder.ReleaseId;
import org.kie.api.builder.model.KieBaseModel;
import org.kie.api.builder.model.KieModuleModel;
import org.kie.api.builder.model.KieSessionModel;
import org.kie.api.conf.EqualityBehaviorOption;
import org.kie.api.conf.EventProcessingOption;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import org.kie.api.runtime.conf.ClockTypeOption;
It's also possible with the 5 knowledge api in drools 6.0+ by setting a rule engine property:
drools.ruleEngine = phreak
Here's how you set in the 5 knowledge api:
knowledgeBaseConfiguration.setProperty("drools.ruleEngine", "phreak");
I'm copy-pasting the simplest Java code for launching a 6.0 session. Everything else - fact insertion, global definitions,... works using the same API, only with KieSession.
package simple;
import java.io.FileInputStream;
import org.kie.api.KieServices;
import org.kie.api.builder.model.KieModuleModel;
import org.kie.api.builder.model.KieBaseModel;
import org.kie.api.builder.model.KieSessionModel;
import org.kie.api.builder.KieBuilder;
import org.kie.api.builder.KieFileSystem;
import org.kie.api.builder.Results;
import org.kie.api.builder.Message;
import org.kie.api.KieBase;
import org.kie.api.runtime.KieSession;
import org.kie.api.runtime.KieContainer;
public class Main {
private KieSession kieSession;
public void build() throws Exception {
KieServices kieServices = KieServices.Factory.get();
KieFileSystem kfs = kieServices.newKieFileSystem();
FileInputStream fis = new FileInputStream( "simple/simple.drl" );
kfs.write( "src/main/resources/simple.drl",
kieServices.getResources().newInputStreamResource( fis ) );
KieBuilder kieBuilder = kieServices.newKieBuilder( kfs ).buildAll();
Results results = kieBuilder.getResults();
if( results.hasMessages( Message.Level.ERROR ) ){
System.out.println( results.getMessages() );
throw new IllegalStateException( "### errors ###" );
}
KieContainer kieContainer =
kieServices.newKieContainer( kieServices.getRepository().getDefaultReleaseId() );
KieBase kieBase = kieContainer.getKieBase();
kieSession = kieContainer.newKieSession();
}
public void exec(){
kieSession.fireAllRules();
}
public static void main( String[] args ) throws Exception {
Main m = new Main();
m.build();
m.exec();
}
}
Yes, most of the API is still supported. You will need to add the knowledge-api jar to your classpath (https://github.com/droolsjbpm/drools/tree/master/knowledge-api-legacy5-adapter).
The main difference is that Drools 6 no longer uses PKG for deployment. It uses mavenized kjars now. If you are not using PKG files (built by guvnor in Drools 5), you should be fine.
the working code to preserve rules and facts by using the same KieSession and deploy Jars, the code is adapted from here https://github.com/droolsjbpm/drools/blob/master/drools-compiler/src/test/java/org/drools/compiler/integrationtests/IncrementalCompilationTest.java.
package test.drools;
import java.io.UnsupportedEncodingException;
import org.drools.compiler.kie.builder.impl.InternalKieModule;
import org.kie.api.KieBaseConfiguration;
import org.kie.api.KieServices;
import org.kie.api.builder.KieBuilder;
import org.kie.api.builder.KieFileSystem;
import org.kie.api.builder.KieModule;
import org.kie.api.builder.ReleaseId;
import org.kie.api.io.Resource;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
public class Playground4 {
private String newline = System.getProperty("line.separator");
public static void main(String[] args) {
Playground4 pg = new Playground4();
try {
pg.doRules();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
private String generateDRLString(int start, int end) {
StringBuilder sb;
sb = new StringBuilder();
sb.append("package performance.drools;" + newline);
for (int i = start; i <= end; i++) {
sb.append("rule \"R" + i + "\"" + newline);
sb.append("when" + newline);
sb.append("then" + newline);
sb.append("System.out.println(\"rule" + i + " fired!\");" + newline);
sb.append("end" + newline);
}
return sb.toString();
}
int count = 1;
public void doRules() throws UnsupportedEncodingException {
KieServices kieServices = KieServices.Factory.get();
KieBaseConfiguration kieBaseConf = kieServices.newKieBaseConfiguration();
//kieBaseConf.setProperty("drools.ruleEngine", "phreak");
kieBaseConf.setProperty("drools.ruleEngine", "phreak");
ReleaseId releaseId;
KieModule kieModule;
releaseId = kieServices.newReleaseId("performance.drools",
"test-upgrade", "1.$v.0".replace("$v", String.valueOf(count)));
// create session without rules for version 1.1.0
kieModule = createAndDeployJar(releaseId);
KieContainer kieContainer = kieServices.newKieContainer(kieModule
.getReleaseId());
kieContainer.newKieBase(kieBaseConf);
KieSession kieSession = kieContainer.newKieSession();
// Create an in-memory jar for version 1.2.0
count++;
releaseId = kieServices.newReleaseId("performance.drools",
"test-upgrade", "1.$v.0".replace("$v", String.valueOf(count)));
kieModule = createAndDeployJar(releaseId, generateDRLString(1, 3));
kieContainer.updateToVersion(releaseId);
kieSession.insert(new Object());
// Create an in-memory jar for version 1.3.0
count++;
releaseId = kieServices.newReleaseId("performance.drools",
"test-upgrade", "1.$v.0".replace("$v", String.valueOf(count)));
kieModule = createAndDeployJar(releaseId, generateDRLString(4, 12));
kieContainer.updateToVersion(releaseId);
kieSession.fireAllRules();
System.out.println(kieSession.getFactCount());
}
public KieModule createAndDeployJar(ReleaseId releaseId, String... drls) {
KieServices kieServices = KieServices.Factory.get();
byte[] jar = createKJar(kieServices, releaseId, null, drls);
return deployJar(kieServices, jar);
}
KieFileSystem kfs;
public byte[] createKJar(KieServices ks, ReleaseId releaseId,
String pom, String... drls) {
if (kfs == null) kfs = ks.newKieFileSystem();
if (pom != null) {
kfs.write("pom.xml", pom);
} else {
kfs.generateAndWritePomXML(releaseId);
}
for (int i = 0; i < drls.length; i++) {
if (drls[i] != null) {
kfs.write("src/main/resources/r" + 10 * count + i + ".drl", drls[i]);
}
}
KieBuilder kb = ks.newKieBuilder(kfs).buildAll();
if (kb.getResults()
.hasMessages(org.kie.api.builder.Message.Level.ERROR)) {
for (org.kie.api.builder.Message result : kb.getResults()
.getMessages()) {
System.out.println(result.getText());
}
return null;
}
InternalKieModule kieModule = (InternalKieModule) ks.getRepository()
.getKieModule(releaseId);
byte[] jar = kieModule.getBytes();
return jar;
}
public KieModule deployJar(KieServices ks, byte[] jar) {
// Deploy jar into the repository
Resource jarRes = ks.getResources().newByteArrayResource(jar);
KieModule km = ks.getRepository().addKieModule(jarRes);
return km;
}
}