RESTLET on Camel with Jetty - rest

As far as I understand, Camel by default uses the default RESTLET engine. How can I tell Camel to use Jetty instead?
I know there are ways to bundle your application and deploy it in Tomcat or Jetty. If I do that, however, the biggest question becomes how to integrate with RESTLET.
I did some further digging. I took one of the tomcat examples that come with the camel. Then I tried to make it RESTLET capable. It almost works. The problem now is that the parameters are not being passed to the route. I would expect that when calling this server: http://x.x.x.x:8080/rs/user/?name=Paul, I would get: Hello Paul how are you?
However, I simply get: Hello how are you?
My camel configuration is:
<camelContext xmlns="http://camel.apache.org/schema/spring">
<route>
<from uri="restlet:/user/?restletMethods=GET,POST" />
<transform>
<simple>Hello ${header.name} how are you?</simple>
</transform>
</route>
</camelContext>
<bean id="RestletComponent" class="org.restlet.Component" />
<bean id="RestletComponentService" class="org.apache.camel.component.restlet.RestletComponent">
<constructor-arg index="0">
<ref bean="RestletComponent" />
</constructor-arg>
</bean>
And my web.xml is:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:camel-config.xml</param-value>
</context-param>
<servlet>
<servlet-name>RestletServlet</servlet-name>
<servlet-class>org.restlet.ext.spring.SpringServerServlet</servlet-class>
<init-param>
<param-name>org.restlet.component</param-name>
<param-value>RestletComponent</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>RestletServlet</servlet-name>
<url-pattern>/rs/*</url-pattern>
</servlet-mapping>
I am getting a little bit closer with my investigation. It appears that ${in.body} will indeed pass the body of the request to the route. I am still trying to find out what is going on with the header. I even tried using the producer template to call the headers, still it does work. So, this somehow suggests that the way to access the header in RESTLET is different than in the pure servlet? Here is my producer template:
Map<String, Object> headers = new HashMap<String, Object>();
headers.put("name","Paul");
context.createProducerTemplate().requestBodyAndHeaders(
"restlet:http://localhost:8080/camel-example-servlet-tomcat/rs/user/?restletMethod=post", "Halleluia",headers);

Have a look at the org.apache.camel.component.restlet.DefaultRestletBinding class. By default form data is only bound when content type is "application/x-www-form-urlencoded". Also, only URI template values will be bound to headers.
To get at arbitrary query parameters you can do something like:
Request request = exchange.getIn().getHeader(RestletConstants.RESTLET_REQUEST, Request.class);
String value = request.getResourceRef().getQueryAsForm().getFirstValue("foo");
Also, the raw query string will be available in the CamelHttpQuery header.
You can supply your own class which implements RestletBinding (or extend DefaultRestletBinding) by specifying the bean ID of a RestletBinding object in the Camel Registry using the 'restletBinding' endpoint query option. If you are using Spring register a bean like this:
<bean id="myRestletBinding" class="com.example.MyRestletBinding"/>

OK. It appears I had to access the URL parameter with in.header.name instead of header.name. I have no explanation as to why header.name would work in the normal servlet. Also, I managed to get this working only with POST. With GET, the parameters are still not passed to the RESTLET engine or I do not know how to retrieve them. On the contrary, GET works fine when using pure servlet. Solution is good for me and I thus mark this as answered.

I would suggest you to use camel CXFRS component. Have a service class where all REST annotations are declared. You can have the username as path parameter or query parameter.
Syntax would be something like this :
from("cxfrs://http://localhost:9992/service?resourceClasses=com.xyz.web.resources.RESTresource")
REST resource would be your resource class. This will run a REST web service over a jetty web server.

Related

Received sun.net.www.protocol.http.httpurlconnection$httpinputstream as response while calling service which is unable to process

I'm developing workflow application in Apache camel
Business Use case:
Service is exposed at consumer endpoint
Processing with request message
Call external SOAP Service, get the response
check particular tag in response xml and then only call another external SOAP Service
Return the final response to client
Now I got stuck in step 4
My camel Route is
<camelContext xmlns="http://camel.apache.org/schema/spring">
<route streamCache="true">
<from uri="cxf:bean:proxyEndpoint"/>
<process ref="myProcessor"/>
<!-- processing request & logging -->
<setBody>
<!-- set request as body required for calling external web service -->
</setBody>
<to uri="cxf:bean:panEndpoint"/>
<!-- <to uri="file:C:/LOG" /> -->
<!-- <process ref="myProcessor2"/> -->
<log message=">>> ${body}" loggingLevel="INFO"/>
</route>
</camelContext>
I'm able to call external Service but after <to uri="cxf:bean:panEndpoint"/> if I try to log body I'm getting arbitrary value same in case of routing to file.
When I tried to route to Processor and print System.out.println(exchange.getIn().getBody());
I'm getting sun.net.www.protocol.http.httpurlconnection$httpinputstream which I'm unable to parse or process
External Service is called and proper response is receiving as I tried to monitor the scenario using TCP-IP Monitor
Any help will be appreciated.
Tell Camel what type you want the body as, and it uses its type converter to make that happen (if possible).
So if you want the body as a InputStream do
exchange.getIn().getBody(InputStream.class)
If you want it as String, then do
exchange.getIn().getBody(String.class)
Read more here
http://camel.apache.org/type-converter.html
And when working with streams mind about stream caching
http://camel.apache.org/stream-caching.html

Expose RAML contract instead WADL in CXF

I am new in REST world, an in most of CXF examples that I saw there is an configuration to expose WADL in REST services when published.
Something like
Available RESTful services:
Endpoint address: http://localhost:8080/ouat-servicesImpl/api
WADL : http://localhost:8080/ouat-servicesImpl/api?_wadl
Then, when clicked
<application>
<grammars/>
<resources base="http://localhost:8080/ouat-servicesImpl/api">
<resource path="/topics">
<method name="POST">
<request>
<representation mediaType="application/json"/>
</request>
<response>
<representation mediaType="application/json"/>
</response>
</method>
</resource>
</resources>
</application>
I was learning RAML and its benefits in contract creation. Is there any way to expose RAML contract in this CXF "home" service page? Or am I mixing the concepts/ purpose of RAML and WADL? Actually I think both are ways to expose services contract, however in my opinion RAML is more complete
Assuming you package your CXF service as a WAR, here is how you can achieve your goal, based on a real project I'm working on:
Drop RAML and JSON files below the webroot folder: https://github.com/openanalytics/RPooli/tree/master/webapp/src/main/webapp/raml
Template baseUri so it can be injected at runtime: https://github.com/openanalytics/RPooli/blob/master/webapp/src/main/webapp/raml/api_v1.raml#L21
Declare .raml as if it's a JSP so injection can work: https://github.com/openanalytics/RPooli/blob/master/webapp/src/main/webapp/WEB-INF/web.xml#L70
Add the RAML mime-type: https://github.com/openanalytics/RPooli/blob/master/webapp/src/main/webapp/WEB-INF/web.xml#L76-L79
Add a filter to compute the dynamic part of the baseUri: https://github.com/openanalytics/RPooli/blob/master/webapp/src/main/java/eu/openanalytics/rpooli/web/BaseUriInjectionFilter.java
Wire it in web.xml: https://github.com/openanalytics/RPooli/blob/master/webapp/src/main/java/eu/openanalytics/rpooli/web/BaseUriInjectionFilter.java
Bonus point for:
Embedding the RAML API console: https://github.com/openanalytics/RPooli/tree/master/webapp/src/main/webapp/raml/ui
And redirecting to it from the web-app home page: https://github.com/openanalytics/RPooli/blob/master/webapp/src/main/webapp/index.html

Create a REST proxy for SOAP service in wso2 esb

We have a SOAP service that I want to proxy in WSO2 ESB. This is for POC that I am working on. I came across various documents and some explanation on forums but nothing concrete yet. I looked at API option but couldn't get anything to work. Whats the best way to do this? Can the transformation occur in esb itself or is the api the only option? Please advise.
You can better choose RESTAPI option.
Here is the documentation for that
What do you mean by couldn't get this working? This is not a big configuration, you need to define your proxy service such that you send the message (REST message) to the back end as a SOAP message. Here is a sample configuration.
<proxy name="StockQuoteProxy" transports="http https" startOnLoad="true">
<target>
<endpoint>
<address uri="http://localhost:9000/services/SimpleStockQuoteService"
format="soap11"/>
</endpoint>
<outSequence>
<send/>
</outSequence>
</target>
</proxy>
You can call this proxy in REST manner and it will automatically send the message to the backend SOAP service.
you can do it with the sample axis2 client as below.
ant stockquote -Daddurl=http://localhost:8280/services/StockQuoteProxy -Drest=true

how can I stop the application part of the url being passed to my servlet in tomcat6

I am running tomcat6 and have hooked it up in eclipse as a server so I can quickly debug code changes - however I am running into an issue with the routes that are passed to my servlet.
I am running spring mvc3 with my routes annotated on the class eg:
#Controller
#RequestMapping(value="/rest")
public class HandleItController {
...
in web.xml I have
<welcome-file-list>
<welcome-file>welcome.html</welcome-file>
</welcome-file-list>
<servlet-mapping>
<servlet-mapping>handleit</servletmapping>
<url-pattern>/rest</url-pattern>
</servlet-mapping>
However I can only get one of these settings to work as desired at a time.
lets say "Web Project Settings" has Context root set to be appname
now if I GET localhost:8080/appname I will get the welcome page as desired
however if I hit localhost:8080/appname/rest/yadda I get a warning saying
No mapping found for HTTP request with URI [/appname/rest/yadda] in
DispatcherServlet with name 'handleit'
If I change my servlet url-pattern to / then I get request routed through the servlet without the appname prepended and the servlet handles them as expected - however I cannot then hit the welcome page
I need a solution that does not involve hard coding appname into the web.xml or the controller mappings, there must be some way I can serve both the html file and the servlet that is independent of the uri to which my application is deployed - ie stop sending the context part of the url through to the servlet
The URI in the #RequestMapping will be appended to the url-mapping of the dispatcher servlet. So if both the servlet and controller is mapped to rest, the full URI will become /contextpath/rest/rest. If you don't want that, map your controller to /
Edit: The reason it doesn't work when you map your servlet to / is that the Spring dispatcher servlet handles everything under the context root. So to get that to work, you need to configure Spring MVC to serve static files.

Securing Glassfish REST Service with basic auth using annotations

I have been trying to secure an application, which is deployed to glassfish 3 using annotation instead of the deployment descriptor. However, I haven't been able to get it working correctly. If I try to access the service, I end up with a server error 500, which displays this message:
type Exception report
message
descriptionThe server encountered an internal error () that prevented it from fulfilling this request.
exception
javax.servlet.ServletException: javax.ejb.AccessLocalException: Client not authorized for this invocation
root cause
javax.ejb.AccessLocalException: Client not authorized for this invocation
The EJB looks like this:
#Path("/myresource")
#Stateless
#RolesAllowed("user-role")
public class MyResource {
#GET
#Path("/{uuid}")
public Response getData(#PathParam("uuid") final String uuid) {
....
}
}
sun-web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sun-web-app PUBLIC "-//Sun Microsystems, Inc.//DTD GlassFish Application Server 3.0 Servlet 3.0//EN"
"http://www.sun.com/software/appserver/dtds/sun-web-app_3_0-0.dtd">
<sun-web-app>
<security-role-mapping>
<role-name>user-role</role-name>
<group-name>user-group</group-name>
</security-role-mapping>
</sun-web-app>
This is the web.xml:
<web-app id="myservice" version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<display-name>org.test.myservice</display-name>
<servlet>
<servlet-name>Jersey Web Application</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>org.test.myservice.rest</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Jersey Web Application</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>file</realm-name>
</login-config>
<security-role>
<role-name>user-role</role-name>
</security-role>
</web-app>
The file realm in glassfish is set up using the user and role specified in the sun-web.xml and has been working well, when setting up the application security via deployment descriptor.
If I understand this document correctly I do not have to link security role references if their names are the same. http://docs.oracle.com/javaee/5/tutorial/doc/bnbyl.html#bnbyt
Any ideas what I am missing?
Edit
Related to the problem of not being able to specify the required information with annotations, there is a another problem, which caused me to think about this issue. Maybe that will make the initial question a little clearer:
Taken above example, the resource /myresource/* is only available for users with role 'user-role'. However, if there is a second resource at path /myresource/*/thumbnail (translating to /myresource/[uuid]/thumbnail) which should be available without authentication, this is not possible by specifying security-constraints with url-mapping, since it does not seem to be possible to use the wildcard between constants. However, this would be doable by specifying the roles, that are allowed to access a method by annotions. As described above, I haven't been able to do so. How could a mapping like that be done?
You need to use the security-constraint element in web.xml descriptor in order to block specific resources and paths, and to specify the authorization constraints.
This doesn't mean that you can't add more fine-grained controls using Programmatic Security, as explained in Oracle's Java EE 6 Tutorial:
Programmatic security is embedded in an application and is used to make security decisions. Programmatic security is useful when declarative security alone is not sufficient to express the security model of an application.
As per your edited question.
I would use the security-constraint element for blocking the access to all non-registered users. This will force everybody to authenticate, so that your application knows the roles they have.
Then you can fine-grain control the access to the various resources using programmatic security.
With basic authentication I guess there are no other ways. If you want to avoid authentication for basic users, you need to go with form authentication and handle the authentication programmatically behind the scenes, authenticating them even if they aren't aware of, by using HttpServletRequest#login().
In both ways you should be able to setup rights in the way you have described. If you want to handle the unauthorized exception more smoothly, you'd better remove the #RolesAllowed annotation and instead use something like:
#GET
#Path("/{uuid}")
public Response getData(#PathParam("uuid") final String uuid, #Context SecurityContext sc) {
if (sc.isUserInRole("MyRole")) {
return result;
} else {
return notAllowedResult;
}
}
The Roles-Allowed is an EJB construct and not congruent with access to the resource, which is handled by the security constraint.
Unfortunately, the two security concepts do not mesh as well as they should, and instead of getting a 401 if you're not authorized (a web concept), you get the security exception that you are receiving (and EJB concept). In fact, I don't know what error you will receive if you annotate an EJB web service with a RolesAllowed and try to access the web service with an invalid role. I assume you'll get a SOAP fault, in that case.
The EJB security is a system that keeps unauthorized people out, but it's a last ditch effort. It assumes that any decisions to route folks to the method calls is already done up front. For example, there's no high level way to test if a method is allowed or not, rather you can only call it and catch the exception.
So the harsh truth is beyond coarse gatekeepers, you want to leverage Programmatic Security.