Calling Ilog Jrule Rules Execution server from java client - java

I am trying to execute a rule in IBM Jrule Rules execution server , using a java client. I am having Websphere community Edition V2.1 server, I am able call and execute the rules using JSF deployed in the samae server.
I want to call and execute the rules using a java client. I didn't find any way to do this,
In EJB. we can call EJB from web as well as from java client , by setting Initial Context envionment property. Is there any way similar to this is there, to call Rule Execution server rules, using java client, web part is already working.
import ilog.rules.res.session.IlrPOJOSessionFactory;
import ilog.rules.res.session.IlrStatelessSession;
import ilog.rules.res.session.IlrSessionFactory;
import ilog.rules.res.session.IlrStatefulSession;
import ilog.rules.res.session.IlrSessionRequest;
import ilog.rules.res.session.IlrJ2SESessionFactory;
import ilog.rules.res.session.IlrSessionResponse;
import ilog.rules.res.model.IlrPath;
import ilog.rules.res.session.extension.IlrExtendedJ2SESessionFactory;
import miniloan.Borrower;
import miniloan.Loan;
public class POJOEx {
public static void main(String... arg) {
// create rule session factory
//IlrSessionFactory sessionFactory = new IlrPOJOSessionFactory();
//IlrExtendedJ2SESessionFactory sessionFactory = new IlrExtendedJ2SESessionFactory();
// j2se factory
IlrSessionFactory sessionFactory = new IlrJ2SESessionFactory();
try {
// use stateless session for invocation
IlrStatelessSession statelessSession = sessionFactory.createStatelessSession();
//input parameter
Borrower borrower = new miniloan.Borrower("Joe", 600,
80000);
// in out parameter
Loan loan = new miniloan.Loan(500000, 240, 0.05);
IlrSessionRequest request = sessionFactory.createRequest();
//rule path
request.setRulesetPath(IlrPath.parsePath("/miniloanruleapp/2.0/miniloanrules/1.0"));
request.setUserDat("miniloanruleapp.MiniloanrulesclientRunnerImpl.executeminiloanrules");
request.setInputParameter("borrower", borrower);
request.setInputParameter("loan", loan);
//executing
IlrSessionResponse response = statelessSession.execute(request);
System.out.println("userdata = " + response.getOutputParameters().get("loan"));
System.out.println("outputString = " + (String) response.getUserData());
System.out.println("executionId = " + response.getExecutionId());
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
I am getting below error.
ilog.rules.res.xu.ruleset.impl.archive.IlrRulesetArchiveInformationNotFoundException: Cannot get the information about the ruleset /miniloanruleapp/2.0/miniloanrules/1.0
can anybody suggest where to specify Rules execution server url, username and password. like we specify InitialContext values in EJB.

Let me clarify what is RES because it seems there is a misunderstanding here, it may be me.
RES is used in Ilog terminology to describe multiple things:
- The web interface that allows you to manage your ruleapp.
- The actual application that you deploy on your WebSphere CE (or else) in order to execute the rules.
- The .jar files that allows you to execute the ruleapp locally.
You, AFAIK, cannot connect RES using a local JAVA application.
What you have coded is calling the rule engine contained in the RES*.jar files in order to execute your ruleapp locally.
There is no way you can use your JAVA application like you are using your EJB application.
You have to use a webservice or else which is feasible if you put the ruleapp name as a parameter of the web service for instance.
You are using miniloan so you probably know the example using the web interface where you can tell which version of the ruleset to use.
It will be the same if you want to programmatically manage your ruleapp deployed on RES (real application on your application server) you will need to use MDB. Nothing else.
It is disapointing, I know because I went through that, but there is no way I know (at least) to do that. This is not the behaviour you have to follow.
To make it work then put your ruleapp in the classpath (or root of your JAVA application in eclipse) and run it... Then you will execute your rules.
RES doesn't provide the same tools than RTS where you can access RTS from any JAVA application in order to manipulate your rule project.
You are 100% correct there is no way to tell the J2SE connection what is the server URL and hence no way to run your rules from the server.
Hope it helps.

You can absolutely call a Rule Execution Server from J2EE code or as in your case via a remote J2SE call and there is documentation provided to do this. But I do want to clarify a few things regarding the first response.
The Rule Execution Server is the runtime for executing rules. It has a persistence layer (file or database) and a management console that is used to manage it and any other connected Rule Execution Server.
It is this management server you connect to when you using the:
server:port/res URL
You do not connect to an actual RES as you can connect many RES to a single management console. The management console has the details about the persistence layer and a way of extracting the ruleset you wish to execute.
To your question. The reason that you are getting an error is that you have not configured which remote rule execution server you wish to pull the ruleset from, which is why you get the error you see.
To configure the remote connection, you use a file called 'ra.xml' and change the settings to point to your remote res/console.
There is a default ra.xml in the '/executionserver/bin' directory (default to ./IBM/ODM87/ODM/executionserver/bin).
The major aspects in that file to consider would be:
To enable management of Java SE XU instances that are running on different JVM or JMX MBean server, you must configure the XU MBean plug-in with the TCPIP protocol:
<config-property>
<config-property-name>plugins</config-property-name>
<config-property-type>java.lang.String</config-property-type>
<config-property-value>{pluginClass=Management,xuName=default,protocol=tcpip,tcpip.port=TCPIP_PORT,tcpip.host=RES_CONSOLE_HOST,tcpip.retryInterval=INTERVAL}
</config-property-value>
</config-property>
where:
RES_CONSOLE_HOST is the host on which the Rule Execution Server console is deployed.
TCPIP_PORT is the TCP/IP port on which the Rule Execution Server console management server is listening.
INTERVAL is the interval of time, in milliseconds, during which the console tries to reconnect to the management server if a connection fails.
As long as the ra.xml is in the classpath of the application you are running the local J2SE engine should make a call to the remote RES console and request the rule app specified in the provide RuleSet path.
For J2EE, this is similar but you actually execute the rule in the remote RES rather than pull the ruleset locally.
If you check the ODM Samples there is both a J2EE and J2SE sample that demonstrates both techniques.

adding below files in the same folder of *.dsar worked for me
creation_date.txt, display_name.txt, properties.txt

Related

Flyway database migration to run automatically when new war deployed

I would like Flyway to run whenever I deploy a new war to my server.
Does flyway automatically get run when a server is deployed? Do I have to always automate a script which would then the flyway migration command? Or what is the best way to do this?
Server:
The server is a Java Tomcat Server running on Elastic Beanstalk (AWS) that is connected to a MySQL database.
Deployment Process
We run our sql migration scripts on the database manually. Then we upload a new war of the server to Elastic Beanstalk.
This can be useful:
Auto-migration on startup : https://flywaydb.org/documentation/api/
So for Java all it takes is to create scripts (eg. V1__initial_schema.sql, ...), put them under /src/main/resources/db/migration/
and then:
Flyway flyway = new Flyway();
flyway.setDataSource(...);
flyway.migrate();
As the comments said, there may be multiple ways to do this.
ServletContextListener
One common way is to use the hook defined by the Java Servlet spec for being notified when your web app is launching and shutting-down. That hook is the ServletContextListener interface. Add a class to your project implementing the two methods in this interface, one for launch and one for shutdown. In the launch method, run your Flyway code.
The word “context” is the technical term meaning your web app.
contextInitializedYour web app is launching. No incoming web request has yet been handled, and will not be handled until your implementation of this method completes. Run your Flyway migrations here.
contextDestroyedYour web app is shutting down. The last remaining web request has been serviced, and no more will be accepted.
Annotating this class with #WebListener is the easiest of multiple ways to get your Servlet container to register an instance.
Pretty easy.
Your ServletContextListener is guaranteed to be called and run to completion before the first execution of any Servlet (or Filter) in your web app. So this is the perfect place to do setup work that you want finished before your servlets go to work. Flyway seems like a natural fit to me.
Search Stack Overflow for “ServletContextListener” to learn more and see examples, such as my own Question & Answer.
Handling failure
Be aware that stopping a web app’s deployment when something goes wrong (when your ServletContextListener encounters an Exception) is not well-defined in the Servlet spec.
An example might be your Flyway migrations failing for some reason, such as not able to connect to database. At that point you might want to halt deployment of your web app.
See my own Question and Answer and the group of related questions I list in that answer. Tomcat 8.0.33 halts the deployment, and un-deploys the web app, but unfortunately does not report the offending Exception (or at least I could not find any such report in the logs nor in the IDE console while in development mode). The behavior of other Servlet containers may vary.

EJB on a remote client

I have successfully compiled, deployed, and tested a simple, Remote, Stateless Session Beans on my local machine using this tutorial.
The program just prints out "Hello World" in NetBeans output window when run.
However I wish to run the client application on another home machine which doesn't has GlassFish or JavaEE installed.
I read here that, to do this I need to create a stand alone Java Application; however I am unsure about the steps to take to obtain the same result.
I am new to EJB architecture. Any help is greatly appreciated.
It's simple. On the first step create standalone application. For example in main method get remote instance of the bean through InitialContext (I suppose, that you define Stateless bean through Remote Interface). Then you can work with bean. Please, remember remote access through InitialContext is different on the different servers type (jboss,weblogic,glassfish). In final look at link: InitialContext on jboss

Invoke a GWT RPC Service from Java, problems with RPC policy

I need to invoke a GWT RPC service from simple Java code. Yes, I read this
Invoke a GWT RPC service from Java directly
However, my issue is that I do not have access to the web application code (though I could ask and obtain some parts of it), so I cannot just add it to the build path of my Java project. All the info I read from the internet is not clear on what exactly needs to be imported.
The question is: what is the minumum that I should include in my project in order to make the call to the service work (using syncproxy gwt for example)? Will it be enough to redefine the client interfaces inside my code or should I do some compiling work as well?
EDIT: I've done some testing locally with the default web app running on localhost. I created a new java project, imported the sync and async service interfaces and the RPC serialization policy I found in the WAR folder of the web app. This is my testing code
import com.gdevelop.gwt.syncrpc.SyncProxy;
public class serviceCall {
private static final String MODULE_BASE_URL = "http://127.0.0.1:8888/gwttestapp/";
private static final String SERVICE_NAME = "greet";
public static void main(String[] args) {
GreetingService rpcService = (GreetingService) SyncProxy.newProxyInstance(GreetingService.class, MODULE_BASE_URL, SERVICE_NAME, "CB32CC2E454EE7E1088B2E29CEB44F84");
String result = rpcService.greetServer("SyncProxy");
}
}
However the server seems not to recognize the RPC policy, since I get the following exception:
Exception in thread "main" com.google.gwt.user.client.rpc.IncompatibleRemoteServiceException: This application is out of date, please click the refresh button on your browser. ( Blocked attempt to access interface 'GreetingService', which is not implemented by 'com.apptesting.server.GreetingServiceImpl'; this is either misconfiguration or a hack attempt )
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:525)
at com.gdevelop.gwt.syncrpc.SyncClientSerializationStreamReader.instantiate(SyncClientSerializationStreamReader.java:746)
at com.gdevelop.gwt.syncrpc.SyncClientSerializationStreamReader.deserialize(SyncClientSerializationStreamReader.java:816)
at com.google.gwt.user.client.rpc.impl.AbstractSerializationStreamReader.readObject(AbstractSerializationStreamReader.java:119)
at com.gdevelop.gwt.syncrpc.RemoteServiceSyncProxy.doInvoke(RemoteServiceSyncProxy.java:204)
at com.gdevelop.gwt.syncrpc.RemoteServiceInvocationHandler.invoke(RemoteServiceInvocationHandler.java:193)
at com.sun.proxy.$Proxy0.greetServer(Unknown Source)
at serviceCall.main(serviceCall.java:11)
Anybody can help?
Try initiating the rpcService without the .gwt.rpc policy specified. IE, just make the call:
GreetingService rpcService = (GreetingService) SyncProxy.newProxyInstance(GreetingService.class, MODULE_BASE_URL, SERVICE_NAME);
You generally do not need to specify the exact serialization policy as the RPC system should automatically figure it out. In fact, it's better not to specify it because the deployed site will change the serialization policy file as the back-end changes. Take a look at the source and testing wiki (https://code.google.com/p/gwt-syncproxy/wiki/SourceAndTesting) for some guidance on on setup need needs. The source code for the Android testing app may provide you some code guidance on creating a functional standalone (if you ignore the AsyncCallback implementations)
In general answer to your question, for deployment purposes, all you really are the interfaces you specified (*Service & *ServiceAsync). For testing purposes in your development environment, you can mock some *Impl files that will provide you some generic responses for testing (such as in the default web-app). Take a look at the Android Wiki in the sync-proxy project (https://code.google.com/p/gwt-syncproxy/wiki/Android) at the setup section for a quick overview on linking the needed files.
Disclaimer: I'm a developer for the Android syncproxy library

How do I specify a server to get an EJB from?

In java EE, the way you get an EJB from a remote server is by looking it up in JNDI. The specification defines the JNDI name for a given bean type.
However, this seems to be only if you want to get a bean off your local computer. I want to get the bean off a remote server, like most users would. How do I specify the server URL? Do I pass a map to the InitialContext constructor?
Note: There is another question that is pretty much the same, but that has become out of date since the definition of portable JNDI names by the specification.
I want to get the bean off a remote server
Yes, you need specify the IP/port where the remote server (JNDI service) is running/listening.
How do I specify the server URL?
You have to set the propertie: java.naming.provider.url and make it available to the InitialConetxt.
This can be done in different ways:
to use a jndi.properties file
to use system properties
passing the value in a Hashtable when you create a new instance of
InitialContext object.
The concrete value of this and others necessary properties to instantiate the InitialConetct are vendor dependen.
An example for JBoss could be:
java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
java.naming.provider.url=jnp://yourServer:1099
java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
Keep in mind that there is no way that you can get the EJB's stub from a remote server if you don´t indicate the url.
By "Remote" I mean the client and the server are running in different JVM.
You do JNDI lookups of remote EJBs using exactly the same code as you would use when running server-side:
Context context = new InitialContext(); // No properties needed
MyEJB myEjbInstance = (MyEJB) context.lookup("ejb/MyEJB");
Or, of course, you can inject it:
#EJB
private MyEJB myEjbInstance;
To make the naming context work, you must run your application as a Java EE application client. An application client is exactly like a regular standalone Java program, with a standard main method; the only difference is that it needs to be run in a different manner. That manner is not specified in the Java EE Spec, so each application server has its own way of doing it.
GlassFish, for example, requires an application client to include some special jars in the classpath, and set a couple system properties. Specifically, you must include lib/gf-installer.jar and all the jars referenced by its manifest in your classpath, and you must set the org.omg.CORBA.ORBInitialHost and org.omg.CORBA.ORBInitialPort system properties.

How can I store sensitive data in Java configuration files?

I have some code that I want to make public. The code sends email via servers, connects to databases, and other tasks requiring usernames/passwords.
I'd like to store the passwords and such in a seperate configuration file so that I don't have to sanitize my code on every commit.
How can I do this? It would be easy to do in C using #define, but I'm not sure how to accomplish this in Java.
EDIT: The environment I'm using is Glassfish
The basic method is put the information in a properties file and use the Properties class to load it at run time. If you're using a J2EE server, database connections are configured in the server and the code references them by an abstract name.
I think I should add that if you're using a server, how to configure it and how to get the connections to your code will vary by server and J2EE level so post your environment. Using the Properties class is pretty obvious just by looking at the javadoc and the load() methods.
In glassfish, go to the admin console and under Resources create a new connection pool. That defines your database connection and will share a pool of those connections among your applications. Now under JDBC Resources, create a new entry that maps that pool to a name. The name is usually something like jdbc/myappname.
For a J2EE5 or later application, you can now add this as a class level variable:
#Resource(mappedName="jdbc/myappname") DataSource myDS;
At runtime the server will inject that resource to your database pool. Then when you need a connection, you can do this inside any method:
Connection conn = myDS.getConnection();
The result is your code doesn't have to care at all about the database connection information or managing a pool of connections. You can deploy the identical code on development and production servers, and they will get an appropriate connection. In order to get the injection, it has to be a class the server creates like an EJB, servlet, tag library handler, or JSF managed bean.

Categories

Resources