I am attempting to set up Swagger + Swagger UI in a pre-build project which uses neither the Jersey 2 container Servlet nor the Filter configuration (with web.xml) as stated in the official docs.
My main class looks like this:
public class Application {
public static void main(String[] args) {
URI uri = UriBuilder.fromUri("//localhost/").scheme("http").port(8080).build();
ResourceConfig resourceConfig = new ResourceConfig();
final HttpServer httpServer = JdkHttpServerFactory.createHttpServer(uri, resourceConfig, false);
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
httpServer.stop(0);
}));
httpServer.start();
}
}
I want to use package scanning and the Swagger UI to keep track of my API. All answers i found stated you should either extend the Application class or use a Filter configuration with a web.xml file. Please give me a hint on how to add Swagger to the existing project which was given to me.
I am new to JAX-RS and a bit confused... so I ask for understanding. :)
You could try to just extend the Application class in your existing one.
You can also do this operation without using any api. Just call the report with the parameters you want with REST call to your jasper server.
Related
On every request made to the Restlet resources, I see the following logs in Google App Engine Logs
21:38:50.059 javax.servlet.ServletContext log: ExampleAPIs: [Restlet] ServerServlet: component class is null
21:38:51.568 javax.servlet.ServletContext log: ExampleAPIs: [Restlet] Attaching application: com.example.api.ExampleAPIConfig#68ec99 to URI: /example/v1
Why does it say Component is null?
I agree that I did not define Components rather used ServerResources and mapped them to the router in the Application class. But thats how it is supposed to be done as per the Restlet GAE Edition documentation.
Application class for wiring routes
public Example extends Application {
#Override
public Restlet createInboundRoot() {
router = new Router(getContext());
CorsService corsService = new CorsService();
corsService.setAllowedOrigins( new HashSet<String>(Arrays.asList("http://example.com")));
corsService.setAllowedCredentials(true);
getServices().add(corsService);
router.attach("/xyz", XYZ.class);
}
}
Server Resource which handles and returns a JSON Representation
public class XYZ extends ServerResource {
private static final Logger logger = Logger.getLogger("API:Xyz");
#Get(":json")
public Representation handleGetRequest() {
..
return new JsonRepresentation("{\"code\": 4008, \"description\": \"Something blah something\"}");
}
}
Is there something I am doing wrong ?
Did you configure your servlet configuration file as explained in document (below link).
I think servlet is not bound to a class.
https://restlet.com/technical-resources/restlet-framework/guide/2.3/editions/gae
Update
Ok so if you deeper in documentation :
https://restlet.com/technical-resources/restlet-framework/javadocs/2.0/jee/ext/org/restlet/ext/servlet/ServerServlet.html
https://restlet.com/technical-resources/restlet-framework/javadocs/2.0/jee/api/org/restlet/Component.html
You can see that component is optional but can be usefull, but maybe in GAE implementation it doesn't have one by default.
I need to perform some clean up steps after shutting down a jersey server. To my mind this could be easily accomplished by implementing a ServletContextListener. The question of course is how to add this listener to the application. I have seen examples where this is done in the file web.xml like this:
<listener>
<listener-class>org.SomeCompany.SomePackage.server.MyListener</listener-class>
</listener>
where the MyListener class looks as follows:
#WebListener
public class MyListener implements ServletContextListener {
The problem is that this approach only works for deployment as a war file. However, I do also ship my software as a standalone jar file which creates a Grizzly web server to deploy the servlet:
HttpServer httpServer = GrizzlyHttpServerFactory.createHttpServer(BASE_URI,
new MyServerConfig());
The class MyServerConfig subclasses from ResourceConfig and uses the various register methods. I would like to add the listener programmatically as well, but calling register doesn't seem to do the job. Any ideas how to fix this?
The first thing you are going to need to configure Grizzly as a servlet container. This is not the default behavior. You are only creating an HTTP Server. So the first thing you will need to is Grizzly servlet dependency
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-grizzly2-servlet</artifactId>
<version>${jersey2.version}</version>
</dependency>
So here's the deal with this. With this artifact, instead of the Grizzly HttpServer with GrizzlyHttpServerFactory, you would instead use the GrizzlyWebContainerFactory. The only thing is, if you look though the factory API methods, there really isn't a place to register any listeners, and from what I tested, the #WebListener annotation will not automatically get picked up. What we need access to is the Grizzly WebAppContext that Jersey uses to create the Grizzly servlet container.
The way I was able to get it to work, was just to grab some code from the GrizzlyWebContainerFactory.create source code, and just create the container myself. It's really not much code. Most of the source code does checks as it needs to be universal. But in a single use case (with no init-params), you can pretty much cut the code down to this
private static HttpServer create(URI u, Servlet servlet) throws IOException {
String path = u.getPath();
path = String.format("/%s", UriComponent.decodePath(u.getPath(), true)
.get(1).toString());
WebappContext context = new WebappContext("GrizzlyContext", path);
context.addListener(MyListener.class);
ServletRegistration registration;
registration = context.addServlet(servlet.getClass().getName(), servlet);
registration.addMapping("/*");
HttpServer server = GrizzlyHttpServerFactory.createHttpServer(u);
context.deploy(server);
return server;
}
Then just call HttpServer server = create(BASE_URI, new ServletContainer(resourceConfig));
As an aside, for your use case (I just re-read the question :-), Jersey also has Event Listeners. You can write an ApplicationEventListener and listen for the destroy event, and do all your processing there.
I'm trying to create a Framework on top of Restlet and my question would be, is it possible to have a ServerResource to be "injected" from outside the org.restlet.Application code?
The standard way is to have a resource injected here:
public class FrameworkApplication extends Application {
private static final String ROOT_URI = "/";
/**
* Creates a root Restlet that will receive all incoming calls.
*/
#Override
public Restlet createInboundRoot() {
Router router = new Router(getContext());
router.attach(ROOT_URI, RootServerResource.class);
return router;
}
}
However since I am building a framework the use of FrameworkApplication is through including it as a dependency:
<dependency>
<groupId>com.mycompany</groupId>
<artifactId>myframework</artifactId>
<version>0.0.1</version>
</dependency>
Going back to the question, I want to know if it is possible to have a ServerResource to be added in the Restlet routing like this:
public class PluggableResource extends ServerResource {
#Get("json")
public String represent() {
// stuff
return resp;
}
}
In the case of dependency injection, the solution was to do, SelfInjectingServerResource now can I make such a SelfAttachingServerResource?
I don't know what you exactly want to do but auto-discovering support of server resources isn't supported in Restlet. You need to implement by your own within a dedicated implementation of the class Application of Restlet. The method createInboundRoot would be responsible to scan the classpath to detect server resources. Moreover you need to add more metadata for server resources (with annotations for instance) to specify the attachement path.
However, the JAX-RS support provides this feature. It provides a set of annotations to make easy to identify server resources and provide metadata like attachement path, methods and exchanged media types for methods. Here is a sample of use: http://restlet.com/technical-resources/restlet-framework/guide/2.3/extensions/jaxrs. The classes for server resources need to be register by hand but you can go further. As a matter of fact, you can scan the classpath to detect classes having the annotation Path. See this link for the way to implement such ferature: Scanning Java annotations at runtime. In this case, they will be autodetected based on annotations. Is something can suit your needs?
Hope it helps.
Thierry
I've been going through this tutorial and they added a web service class instance to a hashSet, like this:
public class MessageApplication extends Application {
private Set<Object> singletons = new HashSet<Object>();
public MessageApplication() {
singletons.add(new MessageRestService());
}
#Override
public Set<Object> getSingletons() {
return singletons;
}
}
I do not understand what the purpose of it is... I thought you could just access the web service with a URL
You made a class, this class is able to handle web requests. But this class has to be hosted somewhere. This means, this class has to be activated by a URL route. In this case you're using JBOSS.
In the first option of the tutorial, MKyong shows you how to configure RESTEasy Bootstrap (a bootstrap to load references) to map the URL with your class. This is done in web.xml and configures some kind of scanner that will map a certain URL with your class.
The second option is not using RESTEasy Bootstrap and you have to add your class to a collection of long living objects in your application manually. This is done defining the Application (MessageAplication) and defining it in the web.xml.
Yes, you can access the webservice via a URL, but the server needs to know what to do with calls to a certain URL.
Yours is one way (the bootstrap version) of telling the application server where to look for JAX-RS resources: http://www.mastertheboss.com/resteasy/resteasy-tutorial (Step #4)
There is a (newer) alternative, depending on which server and RESTeasy-version you use, which relies on autoscanning for certain annotations. For RESTeasy on JBoss, it's described at the bottom of the tutorial-page I linked.
I had a java project and after lots of research I managed to convert it to a Dynamic Web Project in Eclipse. Now I want to add a new Web Service to it. I have already developed a class. I want to convert it to a standard Web service so I can call it from my silverlight application. Here's my current class:
public class MyWebService
{
#Resource
WebServiceContext context;
#WebMethod
public String ProcessQuery(#WebParam(name="query") String q)
{
MessageContext messageContext = context.getMessageContext();
HttpServletRequest request = (HttpServletRequest) messageContext.get(SOAPMessageContext.SERVLET_REQUEST);
// now you can get anything you want from the request
}
public static void main(String[] args) throws Exception
{
String address = "http://127.0.0.1:8023/_WebServiceDemo";
Endpoint.publish(address, new MyWebService());
new DocumentServer();
System.out.println("Listening: " + address);
}
}
How can I do it in Eclipse? Please post a link to a tutorial or a quick step by step guide. I'm a .Net developer and I'm very new to Java.
Thank you.
PS: So basically I want to publish this service in a standard way rather than calling this main function and using Endpoint.publish() method.
The Eclipse wiki has a tutorial using the Web Tools Platform to do just what you are looking for. It requires WTP and Tomcat, if you don't have those already available to Eclipse. It starts with an unannotated class and finishes with a WSDL and test client. It allows you to view generated SOAP messages.
To create, it instructs you to select the file you want to convert into a web service and run File -> New -> Other... -> Web Services -> Web Service. Then you click Next, move the slider to the Start Service position, and client to Test Client. You select Monitor the Web Service and then click Finish. Then you can play with your Test Client and see your generated WSDL.
Note that the above paragraph is a summary of the tutorial, which you can find in full at the provided link.