HelloWorld using Drools Workbench & KIE Server - drools

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>

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.

Swagger + jaxrs + embedded jetty + no web.xml

I have maven project with embedded jetty server.
I have already created apis using JAX-RS, which are working properly. Now I want to create swagger documentation for my apis.
To start with swagger I have added servlet configuration as describe below :
#WebServlet(name = "SwaggerConfig")
public class SwaggerServlet extends HttpServlet {
#Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
System.out.println("init SwaggerServlet");
BeanConfig beanConfig = new BeanConfig();
beanConfig.setVersion("1.0.0");
beanConfig.setSchemes(new String[]{"http"});
beanConfig.setHost("localhost:8082");
beanConfig.setBasePath("/api");
beanConfig.setResourcePackage("com.myCompany.myApisResourcePackage");
beanConfig.setScan(true);
}
}
Also, in main method,
along with my jersey configuration I have added following code :
//swagger
ServletHolder swaggerServletHolder = new ServletHolder(SwaggerServlet.class);
swaggerServletHolder.setInitOrder(1);
swaggerServletHolder.setInitParameter("swagger.api.basepath", "http://localhost:8082");
context.addServlet(swaggerServletHolder, "/api/*");
//swagger end
So, the problem is, I am not able to find where swagger.json will be created.
In this case, swagger scans packages as server log says it, but swagger.json still not getting created.
Note: I am currently not adding swagger-ui as I think it is not mandatory for creating swagger.json
I got swagger json by hitting url "localhost:8082/swagger.json". I used same configuration as posted in my question.

FUSE camel + KIE Execution Server integration POC

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.

How to write a REST client, based on CXF, in TomEE?

I would like to use my REST client, developed with CXF, with TomEE/TomEE+ 1.0, but I have a little problem with JAXB JSON marshalling/unmarshalling (with the Jackson library).
I tried both Jersey Client 1.1.13 and CXF WebClient (the version included with Tomee+ 1.0), but, I have the same error at deploy time:
org.apache.openejb.OpenEJBException: No provider available for resource-ref 'null' of type 'javax.ws.rs.ext.Providers' for 'localhost/mywebapp.Comp'
I tried also to copy the 'jackson-jaxrs-json-provieder-2.0.4.jar' jar to the TomEE lib directory, but the error is the same.
I also tried to set the system property 'openejb.cxf.jax-rs.providers' to 'com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider,com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider', but nothing changed.
Here is a sample of the code I use to make a REST call with CXF:
final List<Object> providers = new ArrayList<Object>();
providers.add(new JacksonJaxbJsonProvider());
WebClient wc = WebClient.create(url, providers);
Anyway this code it's never executed, because the error is at deploy time.
My webapp (the version developed with Jersey Client) works on Glassfish 3.1.2.
Where is the problem?
Thank you,
bye,
Demis
Found and fixed this bug:
https://issues.apache.org/jira/browse/TOMEE-339
Try the latest TomEE snapshot.
I use jacskon (yes jars needs to be added and the provider to be set) and it works.
I found a good temporary solution to use the CXF rest client and the Jackson JSON marshalling with TomEE+ 1.0.0.
I moved these libraries from the webapp lib to the TomEE lib directory:
jackson-annotations-2.0.4.jar
jackson-jaxrs-json-provider-2.0.4.jar
jackson-module-jaxb-annotations-2.0.4.jar
jackson-core-2.0.4.jar
jackson-databind-2.0.4.jar
And this is my code to make a rest call:
final ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
objectMapper.configure(SerializationFeature.WRITE_DATE_KEYS_AS_TIMESTAMPS, false);
objectMapper.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true);
objectMapper.configure(SerializationFeature.WRITE_NULL_MAP_VALUES, false);
objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, true);
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
final JacksonJaxbJsonProvider provider = new JacksonJaxbJsonProvider(objectMapper, JacksonJaxbJsonProvider.DEFAULT_ANNOTATIONS);
provider.setAnnotationsToUse(JacksonJaxbJsonProvider.DEFAULT_ANNOTATIONS);
provider.setMapper(objectMapper);
final List<Object> providers = new ArrayList<Object>();
providers.add(provider);
WebClient wc = WebClient.create(_request.getUrl(), providers);
wc = wc.type(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON);
try {
res = (ElasticResponse) wc.invoke(_request.getHttpVerb(), _request.getMessage(), _request.getElasticResponseClass());
} catch (final ServerWebApplicationException _e) {
this._log.log(Level.FINE, "http response code > 400", _e);
}
I hope that with the next release of TomEE I do not need to add the Jackson's libraries to the container but only to the webapp.

Shorten path of REST service in JBoss Seam application

I'm pretty new to JBoss and Seam. My project has a REST service of the style
#Path("/media")
#Name("mediaService")
public class MediaService {
#GET()
#Path("/test")
public Response getTest() throws Exception {
String result = "this works";
ResponseBuilder builder = Response.ok(result);
return builder.build();
}
}
I can reach this at http://localhost:8080/application/resource/rest/media/test. However, I don't like this URL at all and would prefer something much shorter like http://localhost:8080/application/test.
Can you please point me in the right direction on how to configure the application correctly? (Developing using Eclipse)
web.xml will contain seam resource servlet mapping , this should be modified to /*, and if you have more configuration to the path it will be in components.xml ,if it is resteasy seam is configured to use, it will look like the following
<resteasy:application resource-path-prefix="/rest"/>