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

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

Related

How to connect XMPP bosh server using java smack library?

I have working xmpp client on webapp using strophe.js ,as per my use case scenario i have to switch to different pages rapidly
Current approach is not secure as jid and password is visible in java script ,I was finding work around to implement security in strophe client an trying to make connection time(with bosh) more shorter ,while going through the book "XMPP Programming with JavaScript and jQuery"by jake moffitt i came across one solution which element both of my above problems is to implement session mechanism.which says that we can use strophe attach(jid,sid,rid) to connect to existing connection,so i need SID and RID ,which i can get from application server!!!
book has given an example of automated connection to bosh server when user logged in the web application,author has implement it using an Django project in python,As I am using java as server side language i tried to implement same example using java smcak-4.0.3 and smack-bosh-4.0.3
but unable to connect to bosh server(i am using ejabberd as xmpp server)
my code is as below
BOSHConfiguration config = new BOSHConfiguration(false,"192.168.0.106",5280,"/http-bind/","192.168.0.106");
XMPPBOSHConnection xbc=new XMPPBOSHConnection(config);
xbc.connect();
xbc.login("admin", "admin");
System.out.println(xbc.getConnectionID());
stack trace
java.lang.ClassNotFoundException: org.xmlpull.v1.XmlPullParserFactory
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1720)
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1571)
at org.jivesoftware.smack.SmackConfiguration.processConfigFile(SmackConfiguration.java:352)
at org.jivesoftware.smack.SmackConfiguration.processConfigFile(SmackConfiguration.java:347)
at org.jivesoftware.smack.SmackConfiguration.<clinit>(SmackConfiguration.java:155)
at org.jivesoftware.smack.ConnectionConfiguration.<init>(ConnectionConfiguration.java:67)
When i tried to login to bosh server it fails every time,i am not sure what is wrong here can some one explain me?
One more thing i have find is one can get session identifier(SID) using "xbc.getConnectionID()" but how to find request identifier?
Any help on above problem will be appriciable!!!!
thanks in advance!
I had a similar problem.
I donwload all the smack github I import smack.jar from /lib/ and add the 3 java files from /src/main/java/org/jivesoftware/smack/
I tried to fix it by importing smack-bosh-3.2.2-jar-with-dependencies.jar from /target/. I don't know why this diddn't work.
Finally, I read here that you need to download all the dependencies libraries :
jbosh-0.6.0.jar
xlightweb-2.5.jar
xSocket-2.4.6.jar
xpp3-1.1.3.3.jar
dom4j-1.6.1.jar
So I used smack.jar from /lib/ with all thoses libraries and this problem was solved.
As i said in comments, you need after to retreive RID. I used jbosh sources and add following lines :
In com.kenai.jbosh.BOSHClient class
//I introduced a new property
private Long rid;
//commented the following code
//long rid = requestIDSeq.getNextRID();
//and at that place added
this.rid = requestIDSeq.getNextRID();
//and finally added a new getter for rid
public Long getRid() {
return rid;}
Then in smack-bosh :
In BOSHConnection.java
public Long getRid() {
return client.getRid();}
public String getSid() {
return sessionID;}
Now I'm blocked cause my session is disconected. According to my openFire logs, it's because of overactivity. So I'm looking for a solution to reduce the number of presence messages.
To get latest benefits in Android BOSH you need Smack Releases 4.1.1
SMACK --- smack-tcp smack-sasl-provided smack-resolver-minidns smack-resolver-dnsjava smack-extensions smack-core smack-bosh smack-android-extensions smack-android
You additionally Need
XPP3 1.1.4c delete the javax package from the JAR file for android because android already have javax....QName class
JXMMP, JXMMP CACHE, JBOSH, MINIDNS, DNSJAVA, JSTUN, XBILL DNS
No need for Apache HTTP Client which is already available in android
Unfortunately it comes around some 12 JAR files,
better use Maven Android Project in Eclipse
Otherwise search the above keywords at Maven Central http://search.maven.org/#search and get the JAR files one by one
stack trace
java.lang.ClassNotFoundException: org.xmlpull.v1.XmlPullParserFactory
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1720)
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1571)
at org.jivesoftware.smack.SmackConfiguration.processConfigFile(SmackConfiguration.java:352)
at org.jivesoftware.smack.SmackConfiguration.processConfigFile(SmackConfiguration.java:347)
at org.jivesoftware.smack.SmackConfiguration.<clinit>(SmackConfiguration.java:155)
at org.jivesoftware.smack.ConnectionConfiguration.<init>(ConnectionConfiguration.java:67)
The exception here clearly states that Webapp cant find class org.xmlpull.v1.XmlPullParserFactory. That sounds like you are missing xml-apis library in your classpath, (or some other implementation of XmlPullParser interface).

Using 'SEARCH' or 'PATCH' with jetty

This basically has me at a loss, and has for almost a week. I'm working on a part of company architecture, trying to get REST all set up. There are two methods that are not in the javax.ws.rs package - SEARCH and PATCH. I've created the following interface in our project to implement SEARCH: (mostly a copy/paste from examples)
/** imports and such as appropriate **/
#Target({ElementType.METHOD})
#Retention(RetentionPolicy.RUNTIME)
#HttpMethod("SEARCH")
public #interface SEARCH {
}
The code using this works flawlessly if called against it directly. However, the web service that talks to the main service fails every time with 500 Invalid HTTP method: SEARCH. So, to be clear, there are two web-enabled services. The first that uses the above code works fine. The second, which is supposed to be nothing but a proxy to the first service fails.
The second service that is having the problem runs on jetty. The servlet that is doing the proxying is an extension of org.mortbay.servlet.ProxyServlet - the only overrides are on init and proxyHttpUrl to do a little bit of URL tweaking. I know that the second service doesn't pass the response into the first because I can shut down the first and the second still gives me that error back.
My question is, am I missing configuration pieces to enable "custom" (i.e. not in the javax.ws.rs package) http methods?
First off, that proxy servlet code is very old, from jetty-6 unless I am mistaken. We have released jetty-9 now, and the last three versions of jetty have come from eclipse so the ProxyServlet you ought to be using is the org.eclipse.jetty.servlets.ProxyServlet class.
Now, from jetty-7 on we added some customization to that proxy servlet so you could modify much more of the client exchange...and you might need to make use of that to get additional http methods working. It could be that the http-client only excepts standard http methods in which case we would have to fix that up for your use case (open a bug at bugs.eclipse.org under RT/Jetty if that is the case).

Calling Ilog Jrule Rules Execution server from java client

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

How to pass data from an application to a JCA resource adapter?

I want to configure a self-written JCA 1.6 inbound resource adapter (RA). My big problem is that the RA needs to get access to some (dynamic) configuration data living in the application that uses the RA.
Now I know that this is against the original idea of the whole JCA idea but unfortunately I cannot change this design as quickly as I'd like/have to.
The data I need to get to the RA is
the port it's supposed to listen on,
the license used for the whole application (the feature the RA supplies requires extra licensing)
additional configuration data stored in a db
I've come up with four ideas:
Use the asadmin create-resource-adapter-config. Due to the fact that glassfish doesn't seem to restart apps depending on the RA, we need to restart the application after this. While this attempt is suitable for the port, it won't fit for the other data.
Use administered objects to give my application a means to pass data in to the RA. This idea is mentioned here. I guess this does it, but the spec states in chapter 13.4.2.3 that
Note, administered objects are not used for setting up asynchronous message
deliveries to message endpoints. The ActivationSpec JavaBean is used to hold all
the necessary activation information needed for asynchronous message delivery
setup.
But I cannot get any dynamic data to the ActivationSpec object (neither through a DeploymentDescriptor nor through annotations). Or did I miss something here? :-)
Use JDBC directly to access the data (also grabbed the idea from here). While this is presumably the best idea, it does not work for the mentioned licensing data as it is not stored in the db.
The last idea I had was to put a method in the MessageDrivenBean (through my interface) that is used to fetch data from within the RA. That method could be called from the RA and would supply the data. But: I just think that is quite abusive as it couples the RA to the app.
Dear community, what are your thoughts on this one? I'm afraid it's not so easy to find answers to these questions, so I'd be quite happy about opinions!
Thanks and cheers,
Julius
In the ra.xml there is the possibility to define config-properties. In Websphere these then show up as editable fields in a table of custom properties for the selected resource adapter. I'm working on a similar problem, I also need to pass hostname / port info to an RA. Unfortunately I haven't figured out how to read the contents of these fields from within the RA however.
The solution I finally came up with is to use the #ConfigProperty annotation. This means I use option one of my question above.
So my ResourceAdapter class looks like this:
public class Hl7ResourceAdapter implements ResourceAdapter {
#ConfigProperty
private Integer port = null;
// Rest from ResourceAdapter interface omitted here...
// Use port here to open socket...
}
The #ConfigProperty fields can now be set through either
a resource-adapter-config
the ra.xml deployment descriptor
Now in order to reconfigure these settings I use glassfish's REST interface to change these settings programmatically (one could also use the asadmin create-resource-adapter-config command). I circumvent the problem, that glassfish does not restart the application that uses the resource adapter by simply restarting it myself through REST. (To be precise: I disable the application and then reenable it to get around another bug in glassfish)
A few additional notes:
We deploy the resource adapter's .rar file into the .ear of the application using it.
We have a separate application outside glassfish (standalone) that calls the REST interface to do such things as restart the resource adapter application etc. It is obvious that an application cannot restart itself properly.
Hope this helps. kutuzof, will this get you any further?

Servlets + JAX-WS

I'm trying to expose a web service method via JAX-WS annotations. Many examples I've seen reference the EndPoint.publish() method to quickly stand up the service in a standalone app (ex from Java Web Services: Up and Running, 1st Edition):
public class TimeServerPublisher {
public static void main(String[ ] args) {
// 1st argument is the publication URL
// 2nd argument is an SIB instance
Endpoint.publish("http://127.0.0.1:9876/ts", new TimeServerImpl());
}
}
One thing that I'm missing is how to accomplish essentially the same thing but in an existing app. Would I make a servlet to handle this? What is the proper way to publish this service in an existing WAR file?
In a container you don't have to publish like this. The container will do the publish. If you plan to use it in JBoss server try JBossWS otherwise for Tomcat or any other server Axis2 may be the better choice.
Read more from the following links.
http://jbossws.jboss.org/mediawiki/index.php?title=JBossWS
http://ws.apache.org/axis2/
This depends on what WS stack you are using.
If you are using Java 6 then that includes the JAX-WS reference implementation, then you can consult the documentation about JAX-WS RI WAR contents.
As #Jerrish and #andri coments, there are different aproaches and solutions, depending on your concerns.
The idea behind is that you don't need to set the configuration (port, etc) when will be published your web service. The best approach could be to set this via configuration files (XML, properties, etc) or using #Annotations.
For example, if you're accustomed to use frameworks like Guice or Spring, you know that is possible/recommended to start the context of your application publishing or initializing some objects, factories, datasources, etc and publishing webservices is another task that can be done in this time, because will be available when you will start your application, isn't?.
By the way, I've good experiences with CXF and another solution could be Spring Web Services another powerful solution for creating web services.

Categories

Resources