FUSE camel + KIE Execution Server integration POC - jboss

Recently, I am starting to look at Fuse Camel, Drools WB and Kie Execution Server Integration for a new project and I am having the following problem.
I am using Fuse 6.2, Drool 6.2.Final for WB and Kie Server.
This is what I have done:
create the Person Drink drool rule from the Fuse Example in Drools-WB and deployed in on the Kie Execution Server using my own Containers : myCheese.
in Fuse Camel, instead of calling the internal Kie-Camel Server, I am using a bean in which setup the header for Comel-jetty to fire the rules :
public void populateRestHeader(Exchange exchange) {
// hard code the message for time being because BatchExecutionHelperd doesn't work. please see below.
String myMessage = "<batch-execution lookup="ksession1"> "
+ "<insert out-identifier="person" > <org.drools.camel.example.Person> john "
+ "51 </org.drools.camel.example.Person> "
+ " ";
// setup the login token
exchange.getIn().setHeader("Authorization", basicToken);
// POST so I can send XML. GET works fine !
exchange.getIn().setHeader(Exchange.HTTP_METHOD, "POST");
// the content
exchange.getIn().setHeader(Exchange.ACCEPT_CONTENT_TYPE, "application/xml");
exchange.getIn().setBody(myMessage);
}
POST the commands to remote Kie-Server using jetty :
jetty:http://my-server/services/rest/server/containers/myCheese
On the Kie-Server log, I am getting :
15:19:33,140 WARN [org.jboss.resteasy.core.ExceptionHandler] (default task-114) failed to execute: javax.ws.rs.NotSupportedException: Cannot consume content type
at org.jboss.resteasy.core.registry.SegmentNode.match(SegmentNode.java:380) [resteasy-jaxrs-3.0.10.Final.jar:]
at org.jboss.resteasy.core.registry.SegmentNode.match(SegmentNode.java:114) [resteasy-jaxrs-3.0.10.Final.jar:]
Either the "Content-Type" wasn't setup correctly or the body wasn't sent ?
I tried to perform a GET using the same method and this works out nicely !
Received :
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><response type="SUCCESS" msg="Info for container myCheese"><kie-container container-id="myCheese" status="STARTED"><release-id><artifact-id>mycheese</artifact-id><group-id>com.markit</group-id><version>1.0</version></release-id><resolved-release-id><artifact-id>mycheese</artifact-id><group-id>com.markit</group-id><version>1.0</version></resolved-release-id><scanner status="DISPOSED"/></kie-container></response>
Using SoapUI to execute the command without any problem.
<response type="SUCCESS" msg="Container myCheese successfully called.">
<results><![CDATA[<execution-results>
<result identifier="person">
<org.drools.camel.example.Person>
<name>john</name>
<age>51</age>
<canDrink>true</canDrink>
<alive>false</alive>
<sex></sex>
<happy>false</happy>
</org.drools.camel.example.Person>
</result>
<fact-handle identifier="person" external-form="0:1:866416565:866416565:1:DEFAULT:NON_TRAIT"/>
</execution-results>]]></results>
</response>
Questions :
a) Any ideas why the error ? Is it correct to set the Exchange.Body as the DATA for the POST ?
b) Instead of using Came-Jetty to POST the commands to Kie-Server, as Kie-Server declare it as REST, can I use CXFRS to do this ? Also, I believes Kie-Server also supports SOAP, but what is its WSDL ? Another other alternatives ?
c) For the BatchExecutionCommands, I was planning to use the following :
public String createCommand() {
BatchExecutionCommandImpl command = new BatchExecutionCommandImpl();
final List<GenericCommand<?>> commands = command.getCommands();
Person person = createTestPerson();
commands.add(new InsertObjectCommand(person, "myPerson"));
commands.add(new FireAllRulesCommand());
command.setLookup("ksession1");
String myXMLMessage = BatchExecutionHelper.newXStreamMarshaller().toXML(command);
return myXMLMessage;
}
But I am getting the Exception in the Fuse log as :
Caused by: java.lang.ClassNotFoundException: org.drools.core.runtime.help.impl.BatchExecutionHelperProviderImpl not found by org.kie.internalapi [281]
at org.apache.felix.framework.BundleWiringImpl.findClassOrResourceByDelegation(BundleWiringImpl.java:1556)
at org.apache.felix.framework.BundleWiringImpl.access$400(BundleWiringImpl.java:77)
at org.apache.felix.framework.BundleWiringImpl$BundleClassLoader.loadClass(BundleWiringImpl.java:1993)
Seems like Kie-Internal Package couldn't access the Drools-Core bundle ?

Arr.. got half of the answer. I needs to set the
Exchange.ContentType = "application/xml" !
now works nicely between the Fuse server and remote Kie-server. However, I am still having the problem with the BatchExecutionHelper Exception.

Related

Liberty : Intermediate context does not exist : jms/xyz

I am working on migrating ear application to liberty. It is a web appliation that uses JMS with MQ messaging provider.
For example in my stage.config.xml, we have following properties:
MQQueue(0).CCSID
MQQueue(0).baseQueueName
MQQueue(0).jndiName
MQQueue(0).name
MQQueueConnectionFactory(0).CCSID
MQQueueConnectionFactory(0).channel
MQQueueConnectionFactory(0).connectionPool.ConnectionPool(0).maxConnections
MQQueueConnectionFactory(0).description
MQQueueConnectionFactory(0).host
MQQueueConnectionFactory(0).jndiName
MQQueueConnectionFactory(0).name
MQQueueConnectionFactory(0).port
MQQueueConnectionFactory(0).provider
MQQueueConnectionFactory(0).queueManager
MQQueueConnectionFactory(0).sessionPool.ConnectionPool(0).maxConnections
MQQueueConnectionFactory(0).transportType
<featureManager>
<feature>jsp-2.3</feature>
<feature>localConnector-1.0</feature>
<feature>jndi-1.0</feature>
<feature>jdbc-4.1</feature>
<feature>samlWeb-2.0</feature>
<feature>wasJmsClient-2.0</feature>
<feature>wasJmsClient-1.1</feature>
<feature>wmqJmsClient-1.1</feature>
<feature>jndi-1.0</feature>
<feature>jmsMdb-3.1</feature>
</featureManager>
<featureManager>
<exclude>jsf-2.2</exclude>
</featureManager>
<variable name="wmqJmsClient.rar.location"
value="${server.config.dir}/wmq/wmq.jmsra.rar"/>
<jmsQueue id="1533A.TRANSPORT.ASSIGNMENT.RESP" jndiName="jms/xyz/queue/transportAssignment/response"></jmsQueue>
<jmsQueue id="1533A.TRANSPORT.ASSIGNMENT.RQST" jndiName="jms/xyz/queue/transportAssignment/request"></jmsQueue>
<jmsQueueConnectionFactory jndiName="jms/xyz" id="xyz_qa_QCF">
<connectionManager maxPoolSize="10"/>
<properties.wmqJms providerVersion="unspecified" transportType="CLIENT" applicationName="xyz" channel="CLIENTS.xyz" hostName="host123.GOT.hst.NET" queueManager="xyz141Q" CCSID="1208"/>
</jmsQueueConnectionFactory>
Exception I get : NameNotFoundException: Intermediate context does not exist: jms/xyz
Can anyone please guide on what all parameters/Configurations I have to use in Server.xml for this to work.Kindly help.
There are several issues with your server.xml:
duplicated jndi-1.0 feature
mixed wasJmsClient and wmqJmsClient - if you only use mq than remove was
mixed versions of wasJmsClient - use only one if you need to connect to internal queues also
<exclude> in features - where did you find such construct, I do not believe it is supported
finally you are using jms\xyz once as QCF name, and once as context name. It is incorrect. Change your QCF jndi name to something differnet e.g. jms\xyz\qcf
UPDATE based on comments
Check how you are using JMS classes.
Here is config and code I used for connecting to MQ:
server.xml fragment:
<feature>jms-2.0</feature>
Java code to send message:
#ApplicationScoped
public class JMSHelper {
private static Logger logger = Logger.getLogger(JMSHelper.class.getName());
#Inject
#JMSConnectionFactory("jms/myapp/NotificationQueueConnectionFactory")
private JMSContext jmsContext;
#Resource(lookup = "jms/myapp/NotificationQueue")
private Queue queue;
#Transactional
void invokeJMS(Object json) throws JMSException, NamingException {
String contents = json.toString();
logger.info("Sending "+contents+" to "+queue.getQueueName());
jmsContext.createProducer().send(queue, contents);
logger.info("JMS Message sent successfully!");
}
}
I am assuming you will use the resource adapter, so please start with reading Liberty and the IBM MQ resource adapter in the IBM documentation.
When you start configuring things like documented by IBM and it still does not work, please post the liberty config and the full exception you get, so we can help you again.

Trouble with Authenticating with remote EJB calls to Wildfly 10

I'm trying to do Remote EJB calls to my Wildfly 10/JBoss 7 EAP server, but keep getting Invalid User error messages on my Wildfly server (my EJB is called LoginManager):
23:04:02,872 ERROR [org.jboss.as.ejb3.invocation] (default task-6) WFLYEJB0034: EJB Invocation failed on component LoginManager for method public abstract java.lang.String ejbs.LoginManagerRemote.echo(java.lang.String): javax.ejb.EJBAccessException: WFLYSEC0027: Invalid User
at org.jboss.as.ejb3.security.SecurityContextInterceptor$1.run(SecurityContextInterceptor.java:69)
at org.jboss.as.ejb3.security.SecurityContextInterceptor$1.run(SecurityContextInterceptor.java:49)
at org.jboss.as.ejb3.security.SecurityContextInterceptor.processInvocation(SecurityContextInterceptor.java:97)
I've added my user to the application-users.properties file using the add-user.sh/bat scripts.
I've tried putting in breakpoints in the Wildfly server itself in the SecurityContextInterceptor class on line 54 and see that the principal is null:
if (holder.skipAuthentication == false) {
holder.securityManager.authenticate(holder.runAs, holder.runAsPrincipal, holder.extraRoles);
I'm not entirely sure if this runAs or runAsPrincipal is the principal/credentials passed by the remote EJB invocation, but I suspect it might be responsible for my problem.
I'm calling the remote ejb as:
Properties p = new Properties();
p.setProperty(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
final Context context = new InitialContext(p);
LoginManagerRemote ejb = (LoginManagerRemote) context.lookup("ejb:ear-1.0/ejbs-1.0//LoginManager!ejbs.LoginManagerRemote");
return ejb.echo("test");
with my jboss-ejb-client.properties as:
remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED=false
remote.connections=default
remote.connection.default.host=localhost
remote.connection.default.port=8080
remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS=false
remote.conncetion.default.connect.options.org.xnio.Options.SASL_DISALLOWED_MECHANISMS=JBOSS-LOCAL-USER
remote.connection.default.username=test
remote.connection.default.password=test
Am I doing something wrong? Am I missing something obvious somewhere? What do I need to do to successfully call a remote EJB?
There's a typo in your jboss-ejb-client.properties
remote.conncetion.default.connect.options.org.xnio.Options.SASL_DISALLOWED_MECHANISMS=JBOSS-LOCAL-USER
Should be remote.connection.default.connect.options etc etc

PrimitiveResourceTypeMap throws exception when trying to use EF as data feed

Short description:
I'm trying to create a WFC data service that will use entity framework to retrieve data from db. The important thing is that the service must be hosted inside sharepoint server. Everything (almost) is ok except that when I'm trying to access deployed service from sharepoint I've got an exception:
The server encountered an error processing the request. The exception message is 'The type initializer for 'System.Data.Services.Providers.PrimitiveResourceTypeMap' threw an exception.'. See server logs for more details. The exception stack trace is:
at System.Data.Services.Providers.PrimitiveResourceTypeMap.get_TypeMap() at System.Data.Services.Providers.ObjectContextServiceProvider.PopulateMetadata(ProviderMetadataCacheItem metadataCacheItem) at System.Data.Services.Providers.BaseServiceProvider.LoadMetadata(Boolean skipServiceOperations) at System.Data.Services.Providers.EntityFrameworkDataService1.CreateInternalProvider(Object dataSourceInstance) at System.Data.Services.DataService1.CreateMetadataAndQueryProviders(IDataServiceMetadataProvider& metadataProviderInstance, IDataServiceQueryProvider& queryProviderInstance, Object& dataSourceInstance, Boolean& isInternallyCreatedProvider) at System.Data.Services.DataService1.CreateProvider() at System.Data.Services.DataService1.HandleRequest() at System.Data.Services.DataService`1.ProcessRequestForMessage(Stream messageBody) at SyncInvokeProcessRequestForMessage(Object , Object[] , Object[] ) at System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke(Object instance, Object[] inputs, Object[]& outputs) at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc& rpc) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc& rpc) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage11(MessageRpc& rpc) at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)
The same service hosted from normal web app works fine.
Is there anyone that had similar issue and has some clues?
I managed to create fully functional WCF data service hosted inside SharePoint 2013 on premise. I got the exception mentioned in question (as well as many others).
By fully functional I mean that my odata requests with filters from CSOM and java script are properly executed and (auto-magically) results in properly formed queries to SQL server database. Works both http and https.
Here is short description what is necessary to have it all working.
A bunch of dll from nuget needs to be deployed to GAC via SharePoint WSP (here is list which worked for me)
a. EntityFramework.dll 6.1.3 for .Net 4.5
b. EntityFramework.SqlServer.dll 6.1.3 for .Net 4.5
c. Microsoft.Data.Edm.dll 5.6.2
d. Microsoft.Data.OData.dll 5.6.2
e. Microsoft.Data.Services.dll 5.6.2
f. Microsoft.Data.Services.Client.dll 5.6.2
g. Microsoft.OData.EntityFrameworkProvider.dll 1.0.0-beta2
h. System.Spatial.dll 5.6.2
Note: The trick is that there is no direct error that some of these dll’s are missing. The exception from question is displayed when there was no System.Spatial.dll in GAC.
Service should look similar to above:
using System.Data.Services;
using System.Data.Services.Providers;
using System.ServiceModel.Activation;
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
public class yourService : EntityFrameworkDataService<YourEntities>
{
public static void InitializeService(DataServiceConfiguration config)
{
config.SetEntitySetAccessRule("*", EntitySetRights.AllRead);
config.SetServiceOperationAccessRule("*", ServiceOperationRights.All);
config.DataServiceBehavior.MaxProtocolVersion = System.Data.Services.Common.DataServiceProtocolVersion.V3;
}
}
Svc file: YourService.svc should be deployed to dedicated feature folder inside ISAPI SP folder
For http – fragment:
<service behaviorConfiguration="WCFServicesBehavior" name=" Namespace.yourservice ">
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
For https: like in http but use mexHttpsBinding binding
Open your endpoint in browser to check if this is working
http://yoursite.local/_vti_bin/name_of_your_feature/yourservice.svc - should return info about service
http://yoursite.local/_vti_bin/name_of_your_feature/yourservice.svc/Name_of_your_entitySet() – should return all entities of given type
Check in SQL Server Profiler if your odata filters are properly translated to SQL queries

HelloWorld using Drools Workbench & KIE Server

Have KIE Drools Workbench 6.2.0 Final installed inside a JBoss 7 Application Server local instance and Kie Server 6.2.0 Final inside a local Tomcat 7 instance.
Using the web based KIE Workbench strictly for evaluation purposes (am using it to code generate Java based Maven projects and am not using a particular IDE such as Eclipse or IntelliJ IDEA):
Created a new repository called testRepo
Created a new project called HelloWorld
Created a new Data Object called HelloWorld with a String property called message:
package demo;
/**
* This class was automatically generated by the data modeler tool.
*/
public class HelloWorld implements java.io.Serializable {
static final long serialVersionUID = 1L;
private java.lang.String message;
public HelloWorld()
{
}
public java.lang.String getMessage()
{
return this.message;
}
public void setMessage(java.lang.String message)
{
this.message = message;
}
public HelloWorld(java.lang.String message)
{
this.message = message;
}
}
Created a new DRL containing the following contents:
package demo;
import demo.HelloWorld;
rule "hello"
when
HelloWorld(message == "Joe");
then
System.out.println("Hello Joe!");
end
When I deploy it to my Kie Server under this URL:
http://localhost:8080/kie-server-6.2.0.Final-webc/services/rest/server/containers/helloworld
I get the following response when I copy and paste the above URL in Google Chrome:
<response type="SUCCESS" msg="Info for container hello">
<kie-container container-id="hello" status="STARTED">
<release-id>
<artifact-id>Hello</artifact-id>
<group-id>demo</group-id>
<version>1.0</version>
</release-id>
<resolved-release-id>
<artifact-id>Hello</artifact-id>
<group-id>demo</group-id>
<version>1.0</version>
</resolved-release-id>
<scanner status="DISPOSED"/>
</kie-container>
</response>
When I try to do a POST using the following payload (using Postman or SoapUI):
<batch-execution lookup="defaultKieSession">
<insert out-identifier="message" return-object="true" entrypoint="DEFAULT">
<demo.HelloWorld>
<message>Joe</message>
<demo.HelloWorld>
</insert>
Received the following:
HTTP Status 415 - Cannot consume content type
type Status report
message Cannot consume content type
description The server refused this request because the request entity is in a format not supported by the requested resource for the requested method.
What am I possibly doing wrong? I went to Deploy -> Rule Deployments and registered my kie-server along with creating a container called helloworld and as one can see from Step # 5, it worked. Perhaps I am not deploying it correctly?
Btw, I used the following Stack Overflow post as a basis (prior to asking this question)...
Most of the search results from Google just explain how to programmatically create Drools projects by setting up Maven based projects. Am evaluating KIE Drools Workbench to see how easily a non-technical person can use KIE Drools Workbench to generate Drools based rules and execute them.
Am I missing a step? Under Tomcat 7, it only contains the following directories under apache-tomcat-7.0.64/webapps/kie-server-6.2.0.Final-webc:
META-INF
WEB-INF
Thanks for taking the time to read this...
What content type are you using in your POST request header?
As far as I remember, that error message happened if you didn't provide a content-type: application/xml in your request's header.
Hope it helps,
are you ok?
The response of Esteban is right, but, you should add a another header, the header that you need to add is "Authorization", and the value of Authorization is the user that you registered to you application realm to your kie-server converted in base64. e.g.:
kieserver:system*01
converted to base64:
a2llc2VydmVyOnN5c3RlbSowMQ==
Anyway, the complete header of my request is like this:
Authorization : Basic a2llc2VydmVyOnN5c3RlbSowMQ==
Content-Type : application/xml
I hope it was helpful.
Sorry for my english! :)
I got it working with using Postman (Chrome app / plugin) with the Authorization tab selected to No Auth. Really cool response!
<response type="SUCCESS" msg="Container helloworld successfully called.">
<results>
<![CDATA[<execution-results>
<result identifier="message">
<demo.HelloWorld>
<message>Joe</message>
</demo.HelloWorld>
</result>
<fact-handle identifier="message" external-form="0:4:1864164041:1864164041:4:DEFAULT:NON_TRAIT"/>
</execution-results>]]>
</results>
</response>

Drools Execution Server pointing to Guvnor repository

I am trying to invoke a drools execution server (5.4.0) running on tomcat6, which is pointing to a previously created snapshot in Guvnor repository (.pkg file).
According to a tutorial I only have to edit the knowledge-service.xml file which is located in /webapps/drools-webapp/WEB-INF/classes of my execution server. Thereby a new resource that is pointing to the Guvnor repository should be added (see below):
<drools:kbase id="kbase1" node="node1">
<drools:resources>
<!-- <drools:resource type="DRL" source="classpath:test.drl"/> -->
<drools:resource type="PKG" source="http://localhost:9080/guvnor-webapp/org.drools.guvnor.Guvnor/package/bonita/LATEST" basic-authentication="enabled" />
</drools:resources>
</drools:kbase>
The URL is pointing to a snapshot that has been created with Guvnor and provides a .pkg-file.
Here the problem:
After I have invoked drools execution server I get an error message that looks like this:
Tomcat log:
INFO: Server startup in 4358 ms
31.10.2012 14:21:07 org.apache.cxf.jaxrs.impl.WebApplicationExceptionMapper toResponse
WARNUNG: WebApplicationException has been caught : bonita.BonitaPerson : bonita.BonitaPerson
---- Debugging information ----
message : bonita.BonitaPerson
cause-exception : com.thoughtworks.xstream.mapper.CannotResolveClassException
cause-message : bonita.BonitaPerson
class : org.drools.command.runtime.rule.InsertObjectCommand
required-type : org.drools.command.runtime.rule.InsertObjectCommand
converter-type : org.drools.runtime.help.impl.XStreamXML$InsertConverter
path : /batch-execution/insert/bonita.BonitaPerson
line number : 3
class[1] : org.drools.command.runtime.BatchExecutionCommandImpl
converter-type[1] : com.thoughtworks.xstream.converters.reflection.ReflectionConverter
version : null
-------------------------------
I think that the redirection from drools execution server to guvnor repository is not working and the class that is necessary is just not found. Even if I shut down my Guvnor server I get the same error message. To me the Guvnor server is never called by the drools execution server...
Can anybody help me to figure out how a proper redirection from drools to guvnor does look like?
Thanks
I had similar issue. Please see this post..
drools-rest-cannotresolveclassexeption
basically your element is incorrect. It should look something like this:
<drools:resource type="PKG" source="http://localhost:9080/guvnor-webapp/rest/package/bonita/LATEST" basic-authentication="enabled" username="admin" password="admin" />
I don't have the reputation points to comment, so that is why I created an answer instead of comment.