Implementing RESTlet in existing Java EE application - spring

How can I implement Restlet framework with my Java EE application?
I have already tried my hands with Spring's Restful Webservice but not sure how to get started with Restlet framework.
Is it a better option than Spring MVC's RESTful implementation? What are the pros and cons of these two frameworks.

The strength of Restlet is that it provides complete API for REST, flexibility when using REST principles and also addresses both client and server sides.
Another aspect you can consider is that Restlet is a complete RESTful middleware allowing connecting various and heterogeneous systems using the REST architecture. As a matter of fact, Restlet can be executed on several environments (Java, Java EE, Android, GWT, Google App Engine) and cloud platforms (EC2, GAE, Azure) with the same API in order to provide RESTful applications. It internally addresses specificities and limitations of each environment. It also allows accessing different types of REST services (like OData, S3...), integrating security of different systems (AWS, Google...) and provide support to the SDC technology of Google (accessing intranet resources in a secure way).
Now let's enter in code. The best approach to implement a Restlet application within JavaEE is to use the servlet extension which plays the role of a front controller to this application. You can then define your entities (Application, ServerResource) as usually. You have to create the following things:
Restlet application (a sub class of Application):
public class ContactApplication extends Application {
public Restlet createInboundRoot() {
Router router = new Router(getContext());
router.attach("/contact/{id}",
SimpleContactServerResource.class);
return router;
}
}
One or more server resources:
public class SimpleContactServerResource
extends ServerResource {
private ContactService contactService = (...)
#Get
public Representation getContact(Variant variant) {
Map<String, Object> attributes
= getRequest().getAttributes();
String contactId = (String) attributes.get("id");
Contact contact = contactService.getContact(contactId);
return new JacksonRepresentation<Contact>(contact);
}
(...)
}
Configures the Restlet servlet:
<web-app>
<context-param>
<param-name>org.restlet.application</param-name>
<param-value>org.restlet.gtug.gae.ContactsApplication</param-value>
</context-param>
<servlet>
<servlet-name>ServerServlet</servlet-name>
<servlet-class>org.restlet.ext.servlet.ServerServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ServerServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
Hope it helps you and gives a better view of the framework.

Related

Mapping extension content types in Jersey, not CXF

Quite a while ago, I had worked on a REST service that was implemented using Apache CXF. Earlier this year, I ported it to Jersey, but there is an incompatibility that I didn't notice at the time.
Apache CXF provides a convenient way to do "extension mapping". The clients of the original service were written to expect this. We're now discovering that using extensions in the client with the ported service isn't working, because extension mapping isn't configured in the service. After looking around for a while, I see that Jersey doesn't provide an obvious way to do this.
Short of changing the clients to not provide the extension, what are some possible strategies for "fixing" this in the service? I'm fairly certain that there are no clients that will be using XML.
Assuming you're using Jersey 2.x, there actually is a convenient way to handle this. It is with the ServerProperties.MEDIA_TYPE_MAPPINGS property. If you are using a ResourceConfig subclass for your configuration you can just do
public class JerseyConfig extends ResourceConfig {
public JerseyConfig() {
packages("com.example");
Map<String, MediaType> mappings = new HashMap<>();
mappings.put("json", MediaType.APPLICATION_JSON_TYPE);
mappings.put("xml", MediaType.APPLICATION_XML_TYPE);
property(ServerProperties.MEDIA_TYPE_MAPPINGS, mappings);
}
}
If you are using a web.xml, you can do
<servlet>
<servlet-name>JerseyApplication</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>com.example</param-value>
</init-param>
<init-param>
<param-name>jersey.config.server.mediaTypeMappings</param-name>
<param-value>xml:application/xml, json:application/json</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>

Difference between #Controller and RouterFunction in Spring 5 WebFlux

There are two ways to expose HTTP endpoints in spring 5 now.
#Controller or #RestController by making the controller's class, e.g.
#RestController
#RequestMapping("persons")
public class PersonController {
#Autowired
private PersonRepo repo;
#GetMapping("/{id}")
public Mono<Person> personById(#PathVariable String id){
retrun repo.findById(id);
}
}
Route in #Configuration class by using RouterFunctions:
#Bean
public RouterFunction<ServerResponse> personRoute(PersonRepo repo) {
return route(GET("/persons/{id}"), req -> Mono.justOrEmpty(req.pathVariable("id"))
.flatMap(repo::getById)
.flatMap(p -> ok().syncBody(p))
.switchIfEmpty(notFound().build()));
}
Is there any performance difference in using anyone approach? Which one should I use when writing my application from scratch.
Programming Paradigm: Imperative vs Functional
In the case with the #Controller or #RestController annotations, we agree with the annotation-based model where we use annotations for mappings (and not only) and as a result side effects (that is not allowed in the functional world) to make our API works. Such side effects could be #Valid annotation that provides inbuilt bean validation for requests' bodies or #RequestMapping with the root path for the whole controller.
On the other hand, with the router functions, we get rid of annotations that consist of any side effects in terms of API implementation and delegate it directly to the functional chain: router -> handler. Those two are perfectly suited for building the basic reactive block: a sequence of events and two protagonists, a publisher and a subscriber to those events.
MVC Legacy: Servlets Stack vs Netty Stack
When we are talking about #Controller I would say that we usually will think in term of synchronous Java world: Servlets, ServletContext, ServletContainerInitializer, DispatcherServlet etc. Even if we will return Mono from a controller to make our application reactive we still will play in terms of Servlet 3.0 specification that supports java.nio.* and running on the same servlets containers such as Jetty or Tomcat. Subsequently, here we will use corresponding design patterns and approaches for building web apps.
RouterFunction on the other hand was inspired by the true reactive approach that originates from the async Java world - Netty and its Channel Model.
Subsequently new set of classes and their APIs for reactive environment emerged: ServerRequest, ServerResponse, WebFilter and others. As for me, they were designed by the Spring team in accordance with the previous years of maintaining the framework and understanding new web systems requirements. The name for those requirements is Reactive Manifesto.
Use Case
Recently my team faced the issue that it is impossible to integrate Swagger with RouterFucntion endpoints. It could upvote for #Controlers, but the Spring team introduced their solution - Spring REST Docs that could be easily connected to reactive WebTestClient. And I use here word 'connected' cause it follows true reactive meaning behind: instead of Swagger with its overloaded configurations and side-effect annotations, you easily could build your API docs in tests without touching your working code at all.
Update 2020: Despite since now Spring Webflux already could be integrated with Swagger subsequently using OpenAPI specification, it still lacks configuration simplicity and transparency that, in my humble opinion, is the consequence of being a part of the archaic MVC approach.
Closure (opinion)
Cause of no performance impact it's likely to hear something similar to 'it is absolutely based on individual preference what to use'. And I agree that it's individual preference indeed among two options: moving forward or moving backwards when you let yourself stay in the same domain for a decade. I think that reactive support for #Controller was done by the Spring team to make it possible for old projects to somehow be in tune with requirements of time and have at least the opportunity for the migration.
If you are going to create a web application from scratch then do not hesitate and use the introduced reactive stack.
Though it's a bit late, but this may be useful for future readers.
By switching to a functional route declaration:
you maintain all routing configuration in one place
you get almost the same flexibility as the usual annotation-based approach in terms of accessing incoming request parameters, path variables, and other important components of the request
you get an ability to avoid the whole Spring Framework infrastructure being run which may decrease the bootstrapping time of the application
Regarding point 3, there are some cases where the whole functionality(IoC, annotation processing, autoconfiguration) of the Spring ecosystem may be redundant, therefore decreasing the overall startup time of the application.
In the era of tiny microservices, Amazon Lambdas, and similar cloud services, it is important to offer functionality that allows developers to create lightweight applications that have almost the same arsenal of framework features. This is why the Spring Framework team decided to incorporate this feature into the WebFlux module.
The new functional web framework allows you to build a web application without starting the whole Spring infrastructure. The main method in that case should be somewhat like the following(note, there is no #SpringBootApplication annotation)
class StandaloneApplication {
public static void main(String[] args) {
HttpHandler httpHandler = RouterFunctions.toHttpHandler(
routes(new BCryptPasswordEncoder(18))
);
ReactorHttpHandlerAdapter reactorHttpHandler = new ReactorHttpHandlerAdapter(httpHandler);
HttpServer.create()
.port(8080)
.handle(reactorHttpHandler)
.bind()
.flatMap(DisposableChannel::onDispose)
.block();
}
static RouterFunction<ServerResponse> routes(PasswordEncoder passwordEncoder ) {
return
route(
POST("/check"),
request -> request
.bodyToMono(PasswordDTO.class)
.map(p -> passwordEncoder
.matches(p.getRaw(), p.getSecured()))
.flatMap(isMatched -> isMatched
? ServerResponse
.ok()
.build()
: ServerResponse
.status(HttpStatus.EXPECTATION_FAILED)
.build()
)
);
}
}

Two separate AuthN methods for one Grails app

I have a Grails application running that uses an external CAS login method and uses a local user list for authorization. I am using the spring-security and spring-security-cas plugins and everything is working great.
I am now implementing a RESTful API under a sub-domain of the application (/api) and want to provide security for that as well. I have read that setting up HTTP basic AuthN is easy with Grails, but have found nothing on using 2 security paradigms within one application. Aside from separating the API to a separate application, is there a way to implement a separate authentication method for just the /api sub-domain on my application?
Any feedback would be greatly appreciated. Thanks!
I found no simple way to accomplish this, so I ended up using IP-based access control for the API (since only a few people will be using it). I did this by editing the web.xml file in my grails app and adding a Remote Address Filter:
<filter>
<filter-name>Remote Address Filter</filter-name>
<filter-class>org.apache.catalina.filters.RemoteAddrFilter</filter-class>
<init-param>
<param-name>allow</param-name>
<param-value>**IP ADDRESSES HERE**</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>Remote Address Filter</filter-name>
<url-pattern>/api/*</url-pattern>
</filter-mapping>
I also had to disable CAS authentication for the api, which I accomplished by adding permissions in the interceptUrlMap in Config.groovy:
'/api/**': ['IS_AUTHENTICATED_REMEMBERED', 'IS_AUTHENTICATED_ANONYMOUSLY']

How to consume REST URLs using Spring MVC?

I have developed few RESTful methods and exposed them via Apache Cxf
I'm developing the client side application using Spring MVC and I'm looking for a simple example to demonstrate how to call/consume these REST methods using Spring MVC
I know how to do it using Apache http client but prefer to use Spring MVC in case such this has already been implemented there.
Spring provides simple wrapper to consume RESTful services called RestTemplate. It performs path variable resolution, marshalling and unmarshalling:
Map<String, Integer> vars = new HashMap<String, Integer>();
vars.put("hotelId", 42);
vars.put("roomId", 13);
Room room = restTemplate.getForObject(
"http://example.com/hotels/{hotelId}/rooms/{roomId}",
Room.class, vars);
Assuming Room is a JAXB object which can be understood by The RestTemplate.
Note that this class has nothing to do with Spring MVC. You can use it in MVC application, but also in a standalone app. It is a client library.
See also
REST in Spring 3: RestTemplate
Use path variables to consume REST data. For example:
https://localhost/products/{12345}
This pattern should give you the detail of the product having product id 12345.
#RequestMapping(value="/products/{productId}")
#ResponseBody
public SomeModel doProductProcessing(#PathVariable("productId") String productId){
//do prpcessing with productid
return someModel;
}
If you want to consume Rest Service from another service then have a look at:
http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/web/client/RestTemplate.html
and
http://www.informit.com/guides/content.aspx?g=java&seqNum=546

writing hessian service

I am new to Spring and Hessian and never used them before.
I want to write a small Hello World Program which clearly shows how this service works.
I am using Maven for list project details and dependencies.
The resources for hessian available online are not complete step-by-step guide.
would appreciate if I get help form someone who has worked writing hessian services
The steps for implementing a Hessian-callable service are:
Create a Java interface defining methods to be called by clients.
Write a Java class implementing this interface.
Configure a servlet to handle HTTP Hessian service requests.
Configure a HessianServiceExporter to handle Hessian service requests from the servlet by delegating service calls to the Java class implementing this interface.
Let's go through an example. Create a Java interface:
public interface EchoService {
String echoString(String value);
}
Write a Java class implementing this interface:
public class EchoServiceImpl implements EchoService {
public String echoString(String value) {
return value;
}
}
In the web.xml file, configure a servlet:
<servlet>
<servlet-name>/EchoService</servlet-name>
<servlet-class>org.springframework.web.context.support.HttpRequestHandlerServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>/EchoService</servlet-name>
<url-pattern>/remoting/EchoService</url-pattern>
</servlet-mapping>
Configure an instance of the service class in the Spring application context:
<bean id="echoService" class="com.example.echo.EchoServiceImpl"/>
Configure the exporter in the Spring application context. The bean name must match the servlet name.
<bean
name="/EchoService"
class="org.springframework.remoting.caucho.HessianServiceExporter">
<property name="service" ref="echoService"/>
<property name="serviceInterface" value="com.example.echo.EchoService"/>
</bean>
The client has to create a proxy of the remote interface. You could simply write a JUnit-Test:
HessianProxyFactory proxyFactory = new HessianProxyFactory();
proxyFactory.setHessian2Reply(false);
proxyFactory.setHessian2Request(false);
com.example.echo.EchoService service = proxyFactory.create(
com.example.echo.EchoService, "http://localhost:8080/<optional-context/>remoting/EchoService");
Assert.equals(service.echoString("test"), "test");

Resources