Using aquillian to test jax-rs - do I need a servlet? - ejb

I'm testing my jax-rs services using aquillian and the wildfly embeded container. In this setup, I'm trying to understand how my web services are handled by the server. To set things up, I have the following deployment in my test:
#Deployment
public static WebArchive create() {
return ShrinkWrap.create(WebArchive.class, "rest-service.war")
.addClasses(ProfileService.class,
Profile.class); // classes and other resources into the war
}
So that war gets deployed and its running in an embedable container. However, my test can't find a service at any of the URLs mapped in ProfileService. Is it because my war is missing a servlet? Specifically, a javax.ws.rs.core.Application instance? Or am I misunderstanding how EJB containers expose jax-rs services.

It is because you're missing a class that extends Application, however you don't need to register it as a servlet. As long as its annotated #ApplicationPath it will be picked up by the container.

Related

Spring Boot : Apache CXF SOAP with #RestController for rest ws

I'm working SOAP and REST together into the same application. Rest web service with #RestController and SOAP with apache cxf.
Rest ws and soap have the same path, for example:
Rest: GET http://localhost:8080/ws/person
SOAP: http://localhost:8080/ws/findPerson
For configuring cxf servlet, i create the following method
#Bean
public ServletRegistrationBean cxfServletRegistration() {
return new ServletRegistrationBean(new CXFServlet(), "/ws/*"); }
SOAP Service are running fine after change but REST (#RestController) stop working, but if I disable the method cxfServletRegistration(), the rest WS working fine.
Could you suggest any solution to make all WS working together ?
You can't, because each servlet must "own" its listening basepath. Despite the lack of an explicit registration, RestControllers listen on a base path (default /*) Do you actually need to use #RestController? CXF has REST support via JAX-RS.
Otherwise, I would suggest to separate your REST and SOAP functionality, such as having REST on /model/... and SOAP on /api/... or some such separation.

Grails 3 and Spring #RequestMapping

In Grails 3 I'm trying to use spring-security-oauth, which provides a few endpoints via the #RequestMapping I can see in the mbeans that the path is configured but any request always hits grails and returns a 404.
The requests never seem to hit any of the endpoints configured by the spring-security-oauth lib. Is there anyway to insure the requests hit the endpoints in the jar?
To make sure the endpoints configured by #RequestMapping show in a Grails 3 app using Java config you have to use the following set up in Application.groovy
#ComponentScan("my.org.config")
class Application extends GrailsAutoConfiguration {
static void main(String[] args) {
GrailsApp.run(Application)
}
}
Do not use application.yml in the following way:
grails:
profile: web
spring:
bean:
packages:
- my.org.config
While the beans will be picked up anything with #RequestMapping will not be accessible.

Cannot reach EJB exposed as REST service

I'm trying to expose some EJBs as REST web service using JAX-RS annotations. When I deploy war file containing EJB Jar in WEB-INF/lib to Wildfly 8, I can see in web admin panel EJB Jar as deployed, But I cannot reach REST endpoints and get 404.
This is content of web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<servlet-mapping>
<servlet-name>javax.ws.rs.core.Application</servlet-name>
<url-pattern>/separated/*</url-pattern>
</servlet-mapping>
</web-app>
This is a sample session bean I'm trying to serve as web service and put in jar file:
#Stateless(name = "TestSessionEJB")
#LocalBean
public class TestSessionBean {
#PersistenceContext(unitName = "TestPU")
private EntityManager em;
public AuthenticationSessionBean() {
}
#GET
#Path("ep")
public String testEP() {
return "Hello from testEP()";
}
}
I cannot reach testEP through /<war_file_name>/separated/ep. Added ejb-jar.xml descriptor to WEB-INF/, still no success. I made another service with classes compiled and deployed directly in war file's WEB-INF/classes:
#ApplicationPath("/integrated")
public class TestRestApp extends Application {
}
#Path("/ep")
public class TestRestEp {
#GET
public String doGet() {
return "success";
}
}
Here I can reach doGet() through /<war_file_name>/integrated/ep.
Am I missing something? Can I deploy EJBs as separated jar files and expose them as REST web services with no wrapper?
UPDATE:
I annotated TestSessionBean with ApplicationPath("separated") and made it extending from javax.ws.rs.Application. Still getting 404 but this time It's different; 404 without "Not Found" body. If I make an endpoint path same as an endpoint in TestRestApp, e.g #Path("ep") It maps to endpoint in TestRestApp and I get "success" instead of "Hello from testEP()" by navigating to /<war_file_name>/separated/ep. If I annotate a method in TestSessionBean with a path not defined in TestRestApp result is 404. I cleared my web.xml out of servlet definitions and still same result.
First
Simply annotating an EJB class's method with JAX-RS annotations will not make the method a JAX-RS resource method. You need to make TestSessionBean a root resource class by annotating it with #Path, like you did with TestRestEp. Or you can make this class a Sub-Resource and have a Root resource pass the request to this class. I'd just stick to the former, if you have no idea what the latter means.
Second
Keeping in mind Wildfly (JBoss) modular architceture
Stated in the Resteasy (Wildfly's JAX-RS implementation) Reference Guide:
Resteasy and JAX-RS are automically loaded into your deployment's classpath, if and only if you are deploying a JAX-RS Application.
That being said, your web.xml doesn't create a JAX-RS application. You are basically depending on the (default JAX-RS specified) javax.ws.rs.Application servlet, which is only loaded if the JAX-RS module is loaded into the Server.
When you have an Application subclass, with the #ApplicationPath annotation, this creates a JAX-RS application and the JAX-RS module is loaded into the Server and the classpath will be scanned for resource classes.
Also stated in the JAX-RS spec:
The resources and providers that make up a JAX-RS application are configured via an application-supplied subclass of Application. An implementation MAY provide alternate mechanisms for locating resource classes and providers (e.g. runtime class scanning) but use of Application is the only portable means of configuration.
So I would stick to the Application subclass. No web.xml needed

Where to hook up authentication in Grizzly?

I'm using a Grizzly HttpServer which has two HttpHandler instances registered:
under /api/* there is an Jersey REST - style application offering the API of the product, and
under /* there is an StaticHttpHandler which serves static HTML / JavaScript content (which, among other things, talks to the API under /api/
For authentication I'm currently securing only the API using a Jersey ContainerRequestFilter implementing HTTP Basic Auth, which looks quite similar to what is presented in another SO question.
But as requirements changed, now I'd like to require authentication for all requests hitting the server. So I'd like to move the authentication one level up, from Jersey to Grizzly. Unfortunately, I'm completely lost figuring out where I can hook up a "request filter" (or whatever it is called) in Grizzly. Can someone point me to the relevant API to accomplish this?
The easiest solution would leverage the Grizzly embedded Servlet support.
This of course would mean you'd need to do a little work to migrate your current HttpHandler logic over to Servlets - but that really shouldn't be too difficult as the HttpHandler API is very similar.
I'll give some high level points on doing this.
HttpServer server = HttpServlet.createSimpleServer(<docroot>, <host>, <port>);
// use "" for <context path> if you want the context path to be /
WebappContext ctx = new WebappContext(<logical name>, <context path>);
// do some Jersey initialization here
// Register the Servlets that were converted from HttpHandlers
ServletRegistration s1 = ctx.addServlet(<servlet name>, <Servlet instance or class name>);
s1.addMapping(<url pattern for s1>);
// Repeat for other Servlets ...
// Now for the authentication Filter ...
FilterRegistration reg = ctx.addFilter(<filter name>, <filter instance or class name>);
// Apply this filter to all requests
reg.addMapping(null, "/*");
// do any other additional initialization work ...
// "Deploy" ctx to the server.
ctx.deploy(server);
// start the server and test ...
NOTE: The dynamic registration of Servlets and Filters is based off the Servlet 3.0 API, so if you want information on how to deal with Servlet listeners, init parameters, etc., I would recommend reviewing the Servlet 3.0 javadocs.
NOTE2: The Grizzly Servlet implementation is not 100% compatible with the Servlet specification. It doesn't support standard Servlet annotations, or deployment of traditional Servlet web application archive deployment.
Lastly, there are examples of using the embedded Servlet API here
The "hookup" part can be done using a HttpServerProbe (tested with Grizzly 2.3.5):
srv.getServerConfiguration().getMonitoringConfig().getWebServerConfig()
.addProbes(new HttpServerProbe.Adapter() {
#Override
public void onRequestReceiveEvent(HttpServerFilter filter,
Connection connection, Request request) {
...
}
#Override
public void onRequestCompleteEvent(HttpServerFilter filter,
Connection connection, Response response) {
}
});
For the "linking" to the ContainerRequestFilter you might want to have a look at my question:
UnsupportedOperationException getUserPrincipal

How can I get my WCF Service constructor called?

I'm currently trying to get my head around WCF services for an ASP.NET dev environment, and I believe that I'm doing well save for one thing that has me stumped.
Basically, I've got a WCF service set up (let's take the default, with an added constructor):
public class MyService : IMyService
{
public MyService() { /* blah */ }
public DoWork() { /* blah */ }
}
The IMyService interface defines the DoWork() method as an [OperationContract], as it should.
So I've got this service referenced in another project (let's say a [Unit] Test Project), via Add Service Reference on the VS2010 UI. This creates a reference to a MyServiceClient which exposes my WCF service methods, as it should.
However, when I do this in my test project:
ServiceReference.IMyService service;
service = new ServiceReference.MyServiceClient();
... the MyService() constructor does not get called, basically because I'm instantiating a MyServiceClient, not a MyService per se.
How do I go about getting that constructor called? I'm planning to use that for initialization purposes (perhaps grabbing a layer in a tiered implementation, for example?).
That constructor will be called on the server when you make your request from the client.
Creating a "reference" to a web service (and then using the client classes) is very different to referencing a regular .DLL. All of your service code will run on the server-side, but not until the service is invoked...
The only way for the server-side constructor to be called for each request is to set the InstanceContextMode to PerCall (in the ServiceBehavior attribute).

Resources