JavaFX2: Consume Restful services - web-services

I am trying to work on an architecture to consume RESTFul services from a JavaFX application. The requirement is to use spring's rest template(Not too pressed for this. If spring does not work then probably I can look at jersey or resteasy.
My setup is as below:
My main class has a dropdown listing values from a RESTFul service.
The architecture to hit the RESTFul services is as below:
I have a client class that gives me the instance of the service class that hits the rest services.
In the service class, I have various methods that I hit on the RESTFul service.
public MyService1()
{
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
MyConfig.class);
context.registerShutdownHook();
}
#Autowired
private RestOperations restTemplate;
private final Logger LOG = LoggerFactory.getLogger(MyService1.class);
public List<MyObject> getMyObjects() throws IOException
{
HttpEntity<MultiValueMap<String, HttpEntity<?>>> request = new HttpEntity<MultiValueMap<String, HttpEntity<?>>>(
createParts(), createMultiPartHeaders());
Map<String, String> vars = new HashMap<String, String>();
List<MyObject> myObjects = restTemplate.getForObject(
"http://localhost:8080/my-webservices/objects", List.class, vars);
return myObjects;
}
With the above setup, I get the exception:
Exception in Application start method
Exception in thread "main" java.lang.RuntimeException: Exception in Application start method
at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:403)
at com.sun.javafx.application.LauncherImpl.access$000(LauncherImpl.java:47)
at com.sun.javafx.application.LauncherImpl$1.run(LauncherImpl.java:115)
at java.lang.Thread.run(Thread.java:722)
Caused by: java.lang.NoClassDefFoundError: Could not initialize class org.springframework.beans.factory.BeanCreationException
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:581)

It seems like you have not added the dependency library containing "BeanCreationException" class. Please add the jar file of spring as dependency for that JavaFX Project.

Related

Automatic NTLM Authentication for WSO2 ESB

I have a WCF Web Service sitting on a client's IIS server secured with NTLM authentication - I have no control over the authentication configuration on that server.
I need to integrate my WSO2 ESB server with this service, but I can't find a way to get the ESB to authenticate automatically. I have successfully pushed requests through the ESB to the service with web applications, but I was prompted to provide my Windows credentials during that process - I would like for this to not happen.
I have attempted to set up an NTLM proxy on my server, but couldn't figure this out either.
Any guidance would be much appreciated.
Strainy
Ok, i found your answer. As you know, WSO2 ESB uses Axis2 for web services. You must add NTLM configuration in Axis2 config file (ESB_HOME/repository/conf/axis2/axis2.xml).
This links, describes the configuration.
http://wso2.com/library/161/
http://axis.apache.org/axis2/java/core/docs/http-transport.html
There were a few components to getting this working correctly. It's hard to find it all written down in one place, so I'll attempt to provide an end-to-end overview here.
I first had to use a class mediator within my WSO2 ESB in-sequence to handle the sending and the NTLM authentication. The class mediator references a custom class which takes the message context from the mediation flow (called the Synapse message context) and extracts the SOAP envelope. I then loaded the Synapse SOAP envelope into an Axis2 message context object. I then used an Axis2 client along with the message context to submit my authenticated request to the server. The authentication for NTLM through Axis2 comes from the JCIFS_NTLMScheme class, which you can reference here.
Note: you'll have to play with the logging configuration in that class to make it work with WSO2. I just removed the " org.sac.crosspather.common.util* " libraries and altered any logging I saw to use the Apache Commons logging capability
Create a Custom Mediator Project in WSO2 Developer Studio
Create a new project in Developer studio. Right click the project node in the project explorer and select "New > Mediator Project".
This will generate a bit of boilerplate code for you - that is, a class which extends AbstractMediator and which implements an "mediate()" method which Synapse will call when it comes to executing the logic defined within your sequence.
public class NTLMAuthorisation extends AbstractMediator {
public boolean mediate(MessageContext context){
//Mediation Logic
return true;
}
}
Expose Some Variables/Properties to the User
The class mediator looks for variables which are publicly accessible and exposes them in the WSO2 configuration. This is helpful before you can create a re-usable mediator which adapts itself to properties or values defined in the WSO2 Carbon Web UI. Here we need to expose seven variables: soapAction, SoapEndpoint, domain, host, port, username, and password. Expose the variables by defining your instance variables, along with their accessors and mutators.
This is all really quite useful for using the WSO2 Secure Vault to store your NTLM password and fetching other configuration from a system registry with properties.
public class NTLMAuthorisation extends AbstractMediator {
private String soapAction;
private String soapEndpoint;
private String domain;
private String host;
private int port;
private String username;
private String password;
public boolean mediate(MessageContext context) {
//Mediation Logic
return true;
}
public void setSoapAction(String _soapAction){
soapAction = _soapAction;
}
public String getSoapAction(){
return soapAction;
}
public void setSoapEndpoint(String _soapEndpoint){
soapEndpoint = _soapEndpoint;
}
public String getSoapEndpoint(){
return soapEndpoint;
}
public void setDomain(String _domain){
domain = _domain;
}
public String getDomain(){
return domain;
}
public void setHost(String _host){
host = _host;
}
public String getHost(){
return host;
}
public void setPort(int _port){
port = _port;
}
public int getPort(){
return port;
}
public void setUsername(String _username){
username = _username;
}
public String getUsername(){
return username;
}
public void setPassword(String _password){
password = _password;
}
public String getPassword(){
return password;
}
}
The Custom Mediation Logic
Make sure you created an JCIFS_NTLMScheme class from here and have added the org.samba.jcifs dependency to your Maven dependencies like so:
<dependency>
<groupId>org.samba.jcifs</groupId>
<artifactId>jcifs</artifactId>
<version>1.3.17</version>
</dependency>
Now you can use the following mediate method in your custom mediator class:
public boolean mediate(MessageContext context) {
//Build NTLM Authentication Scheme
AuthPolicy.registerAuthScheme(AuthPolicy.NTLM, JCIFS_NTLMScheme.class);
HttpTransportProperties.Authenticator auth = new HttpTransportProperties.Authenticator();
auth.setUsername(username);
auth.setPassword(password);
auth.setDomain(domain);
auth.setHost(host);
auth.setPort(port);
ArrayList<String> authPrefs = new ArrayList<String>();
authPrefs.add(AuthPolicy.NTLM);
auth.setAuthSchemes(authPrefs);
//Force Authentication - failures will get caught in the catch block
try {
//Build ServiceClient and set Authorization Options
ServiceClient serviceClient = new ServiceClient();
Options options = new Options();
options.setProperty(org.apache.axis2.transport.http.HTTPConstants.AUTHENTICATE, auth);
options.setTransportInProtocol(Constants.TRANSPORT_HTTP);
options.setTo(new EndpointReference(soapEndpoint));
options.setAction(soapAction);
serviceClient.setOptions(options);
//Generate an OperationClient from the ServiceClient to execute the request
OperationClient opClient = serviceClient.createClient(ServiceClient.ANON_OUT_IN_OP);
//Have to translate MsgCtx from Synapse to Axis2
org.apache.axis2.context.MessageContext axisMsgCtx = new org.apache.axis2.context.MessageContext();
axisMsgCtx.setEnvelope(context.getEnvelope());
opClient.addMessageContext(axisMsgCtx);
//Send the request to the server
opClient.execute(true);
//Retrieve Result and replace mediation (synapse) context
SOAPEnvelope result = opClient.getMessageContext(WSDLConstants.MESSAGE_LABEL_IN_VALUE).getEnvelope();
context.setEnvelope(result);
} catch (AxisFault e) {
context.setProperty("ResponseCode", e.getFaultCodeElement().getText());
return false; //This stops the mediation flow, so I think it executes the fault sequence?
}
return true;
}
Package as an OSGi Bundle and Deploy to the Server
At this stage you should be able to your custom mediator project within the project explorer in WSO2 Developer Studio and from the context menu select Export Project as Deployable Archive. Follow the prompts to save the JAR file somewhere on your system. After generating the JAR file, locate it and transfer it to the [ESB_HOME]/repository/components/dropins directory. You may need to restart the server for it to detect the new external library.
Using the Custom Mediator
In your sequence, you should now be able to add a class mediator and reference your custom class using the package name and class name together, for example: org.strainy.ntlmauthorisation.

How to write Spring Interceptor to handle any Web Service exception

I am working on a Web Project which is having few SOAP Web Services that we are developing using CXF 2.7.8(& Spring 3.0.7). I have a requirement to add interceptor which can handle the exception occurred during a method call, extract the root cause and send it to the caller.
We don't have any Controllers in our web project as we don't have UI. The project is hosting few web services only.
I implemented a Spring based interceptor by referring to the sample code/example available on internet. By my interceptor is not being called when I call a webservice method. The same code/interceptor works fine in different web application which has a Controller (and uses Spring MVC flow).
I am not sure why it is not working? Is it because that we don't have Spring MVC based flow and I am trying to use a Spring Interceptor? If yes, then could somebody please suggest as how can I write an interceptor which will be called when some exception occurs. I am using CXF based SOAP web services.
Below is the Interceptor & Spring configuration that I tried:
public class ExceptionHandlerInterceptor extends HandlerInterceptorAdapter {
private static final Logger LOG = Logger
.getLogger(ExceptionHandlerInterceptor.class);
#Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
LOG.info("Before handling the request");
return super.preHandle(request, response, handler);
}
#Override
public void postHandle(HttpServletRequest request,
HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
LOG.info("After handling the request");
super.postHandle(request, response, handler, modelAndView);
}
// #SuppressWarnings({ "unchecked", "rawtypes" })
#Override
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception ex)
throws Exception {
LOG.info("After rendering the view");
System.out.println("Exception is-->" + ex);
super.afterCompletion(request, response, handler, ex);
}
}
And this is the Spring configuration:

JBoss WebServices and EJB

My application should show a list of stuff over RESTful WebServices.
This list of stuff is generated via an EJB which is deployed in JBoss AS 6 in a .jar.
My question is, how do I get this list of stuff in order to show it via Web Services?
If I try to inject #EJB in the stateless bean annotated with #WebService, and try to invoke the method that generates the list, I get an error saying that #EJB cannot be resolved (or imported). (fixed it, needed to modify maven dependencies).
Now I get a NullPointerException when I call the supposedly injected EJB...
I am using the webapp archetype from Maven, which contains an EAR, a JAR and a WAR.
I am at a total loss here, been trying to figure this for almost a week.
Thanks in advance!
--EDIT-- code and typo fixed
This is my stateless bean which SHOULD be exposed as a WebService (according to:
http://www.adam-bien.com/roller/abien/entry/restful_calculator_with_javascript_and )
#Stateless
#Path("/MyRESTApplication")
public class HelloWorldResource {
#EJB
private TestBean testBean;
#GET()
#Produces("text/plain")
public String sayHello(String name) {
return testBean.doMoreStuff();
}
}
the doMoreStuff() function simply returns "HELLO!".

Scope 'session' is not active for the current thread

I have two Spring applications: client and server. On server application are services, on client app is view logic. Both apps should communicate through web-services, but this did not work because of error
Request processing failed; nested exception is
org.springframework.remoting.jaxws.JaxWsSoapFaultException: Error
creating bean with name 'scopedTarget.jcrSession': Scope 'session' is
not active for the current thread; consider defining a scoped proxy
for this bean if you intend to refer to it from a singleton; nested
exception is java.lang.IllegalStateException: No thread-bound request
found: Are you referring to request attributes outside of an actual
web request, or processing a request outside of the originally
receiving thread? If you are actually operating within a web request
and still receive this message, your code is probably running outside
of DispatcherServlet/DispatcherPortlet: In this case, use
RequestContextListener or RequestContextFilter to expose the current
request.
On server app i'm using JCR Session (session scoped bean)
<bean name="jcrSession" factory-bean="sessionFactory" factory-method="login" scope="session" destroy-method="logout" >
<aop:scoped-proxy/>
</bean>
in web.xml of server app I have
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
When I access WSDL files produced by server app in browser, everything is OK. When I use server app services locally (e.g. in controller on server app) everything is also OK. So why this error occurs, when I try to access services through web-services from remote app?
Update1
jcrSession is crated by SessionFactory class. Then this jcrSession is autowired to DAO objects using springs #Autowired.
Example of simplified `JcrSessionFactory`:
public class JcrSessionFactory {
private Repository repository;
private Credentials credentials;
private Session session;
public Session login() {
session = repository.login(credentials);
return session;
}
public void logout() {
session.logout();
}
}
Also, same error occured when I tried to autowire service in same app and use it in method annotated by #PostConstruct or in implementation of InitializingBean in method afterPropertiesSet()

Rich client (swing) application which connects to Remote database over http

i have a local client j2se application and backend is derby(javadb) database and dao is jpa eclipselink .
how do i send these database pojo to a remote database which linked with spring ( jsp) application on tomcat server
simply this is a rich client with swing which connects to tomcat deployed web application. The client should receive data and send data through HTTP requests to the server-side of the service,
what would be the best solution ??
01) direct database connection/transaction through socket using Eclipselink
02) web service ??
03) just send post request to spring web application and convert it to POJO and persist to database
how do i achieve this??
DISCLAIMER I am not suggesting you port your app from Spring to EJB. Despite how people like to compare them as exclusively one or the other, you can use them both. Its your app, you can be as pragmatic as you want to be :)
You don't necessarily have to use Web Services if you wanted. You could drop the OpenEJB war file into Tomcat as well and create an Remote EJB to send data back and forth.
Once you drop in OpenEJB you can put a remote #Stateless bean in your app like so:
#Stateless
#Remote
public class MyBean implements MyBeanRemote {
//...
}
public interface MyBeanRemote {
// any methods you want remotely invoked
}
Then look it up and execute it over HTTP from your Swing app like so:
Properties p = new Properties();
p.put("java.naming.factory.initial", "org.apache.openejb.client.RemoteInitialContextFactory");
p.put("java.naming.provider.url", "http://tomcatserver:8080/openejb/ejb");
// user and pass optional
p.put("java.naming.security.principal", "myuser");
p.put("java.naming.security.credentials", "mypass");
InitialContext ctx = new InitialContext(p);
MyBean myBean = (MyBean) ctx.lookup("MyBeanRemote");
Client-side all you need are the openejb-client.jar and javaee-api.jar from the OpenEJB war file and your own classes.
Since it's already a Spring app don't bother trying to use #PersistenceContext to get a reference to the EntityManager so the EJB can use it. Just figure out how to expose the EntityManagerFactory that Spring creates (or you create) to the EJB via any means possible. The direct and ugly, but effective, approach would be a static on the MyBean class and a bit of startup logic that sets it. You'd just be using the EJB for remoting so no need for fancier integration.
If you did really need web services for non-java communication or something, you can add #WebService to the top of your bean and then it will have WSDL and all that generated for it:
#Stateless
#Remote
#WebService(portName = "MyBeanPort",
serviceName = "MyBeanService",
targetNamespace = "http://superbiz.org/wsdl"
endpointInterface = "org.superbiz.MyBeanRemote")
public class MyBean implements MyBeanRemote {
//...
}
public interface MyBeanRemote {
// any methods you want remotely invoked
}
Then you can also use the same bean as a web service like:
Service service = Service.create(
new URL("http://tomcatserver:8080/MyBeanImpl?wsdl"),
new QName("http://superbiz.org/wsdl", "MyBeanService"));
assertNotNull(service);
MyBeanRemote myBean = service.getPort(MyBeanRemote.class);
Both approaches are over http, but the web service approach will be a bit slower as it isn't a binary protocol.