Why does Restlet on GAE says Component is NULL - java

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.

Related

Configure Swagger UI + Jersey 2 with JdkHttpServerFactory

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.

Does #RestController have a way to do filter or interceptor without Servlet and HttpServletRequest?

Is there a way to use spring-boot Restful without "HttpServletRequest" to retrieve client's request and others ?
Like, to intercept a calling to server, has to do a scan, how to do it without Servlet API support?
It is a little strange but really donot know if there is a calling convertion that has already implemented this function. Can it be done by following annoation definitions?
#RequestMapping
consumes: It defines an array of consumable media types of mapped
request.
produces: It defines an array of producible media types of mapped request.
headers: It defines the acceptable headers of mapped request.
params: It defines the parameters of the mapped request, narrowing the primary mapping.
path: It defines path mapping URIs in servlet environment.
name: It assigns a name to this mapping.
value: It defines primary mapping expressed by this annotation.
Thanks :)
If You use Spring boot release between 1.2 - 2.0
You may use Spring Boot Actuator trace endpoint.
You can see last 100 incoming request with trace endpoint.
Add this dependency in your pom file.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
Add this configurations in application.properties.
endpoints.actuator.enabled=true
endpoints.trace.enabled=true
endpoints.trace.sensitive=false
management.trace.include=request-headers,response-headers,cookies,errors,parameters
then make request http://yourhost:yourport/trace (etc. http://localhost:8080/trace)
see the logs.
If you want to save logs,
you can create your custom trace repository :
#Component
public class customTrace implements TraceRepository {
private final TraceRepository lastOneHundretLogs = new InMemoryTraceRepository();
#Override
public List<Trace> findAll() {
return null;
}
#Override
public void add(Map<String, Object> map) {
}
}
logs is in the lastOneHundretLogs object.you can take it.
As an alternative ,you can log requests with logger
#Component
public class InMemoryTraceRepository implements TraceRepository {
private static final Logger HTTP_LOGGER = LoggerFactory.getLogger("http-logger");
// For security matters it's better to not expose Traces on HTTP
#Override
public List<Trace> findAll() {
return null;
}
#Override
public void add(Map<String, Object> map) {
Trace trace = new Trace(new Date(), map);
String traceInfo = trace.getInfo().toString();
HTTP_LOGGER.info(traceInfo);
}
}

How do I find base URL during Spring MVC startup?

fellow programmers who lurks here at Stack Overflow.
Today's question: How can I get the absolute baseUrl in Spring MVC Framework, from startup?
I'm working with Spring MVC Framework for an application, and I'm in this situation: Let's say that I need to make objects of class Foo, inserted into a list. Every object contains an unique self-link (I'm using org.springframework.hateoas.Link for the real application, but that's beside the point).
Example code:
class Foo{
private int ID;
private String absoluteUrl;
public Foo(int ID, String baseUrl){
this.ID = ID;
this.absoluteUrl = baseUrl + ID;
}
public void setAbsoluteUrl(String baseUrl){
this.absoluteUrl = baseUrl + this.ID;
}
}
If I run it through a factory, it could look something like this:
public List<Foo> GenerateFooList(String baseUrlFetchedBySpring){
List<Foo> list = new ArrayList();
for (int i = 0; i<100; i++){
list.add(new Foo(i, baseUrlFetchedBySpring);
return list;
}
Resulting baseadresses I would expect during the test phase would be "http://localhost:8000" (or hypothetically, at production, "http://www.fooExample.com").
My issue: I need to get the baseUrl from Spring MVC Framework, at startup.
The Spring MVC application I'm working with is configured by annotations only. I have found out that one can get an absolute url by using HttpServletRequest.getRequestURL().toString(), but to my understanding the application receives these after startup, while I need the baseUrl from the beginning. After all, the Spring API describes HttpServletRequest as: "Defines an object to provide client request information to a servlet", in other words a request sent from a client after startup.
I could of course add a static baseUrl by writing a private final String in the code:
private final String BASE_URL = "http://www.fooExample.com/"
But in case of changes on the application's base-url over time, it would be better if the base url could be set automaticly by Spring MVC. Let's say that I have a Cache-class, that uses dependency injection:
#Repository
class FooCache{
List<Foo> list;
SpringObject springObject; // = ???????????
#Autowired
public FooCache(SpringObject springObject){
this.springObject = springObject; // = ???????????
initCache();
}
public void initCache(){
for (int i = 0; i<100; i++){
list.add(new Foo(i, springObject.getAbsoluteBaseUrl()); // method = ???????????
}
}
This is more of what I am looking for: The cache is only set once, at the beginning, using an object from Spring that contains the information I need. Most likely, it's a config-class that is part of the framework, but after searching for a while on the Internet, what I mostly find is HttpServletRequest-related solutions.
What Spring class/object and method am I truly looking for? Or what other suggestions do you have to fetch the base_url from the beginning?
I need the absolute base url for this one, not something relative.
There is no single "base URL" for your application. Think about it - you can access your production server:
via different domain names
via IP
SSH to it and access via "localhost"
via HTTP and HTTPS
If you don't want to or cannot reflect the "base URL" of the request, my suggestion would be to have one "canonical base URL" configured per environment eg. in the properties. But that's up to you if it makes sense in your case.
If you're using java config and Servlet 3.0+ style (without web.xml), you could have a WebApplicationInitializer implementation such as:
public class MyWebApplicationInitializer implements WebApplicationInitializer {
#Override
public void onStartup(ServletContext container) {
ServletRegistration.Dynamic registration = container.addServlet("dispatcher", new DispatcherServlet());
registration.setLoadOnStartup(1);
registration.addMapping("/example/*");
}
}
with this arrangement, you could use servletContext.getContextPath() to get base url.
You have no way of knowing that without a request. You could use InetAddress and resolve host information, but I am guessing that is not what you are looking for.
Let's say you have two domains www.foo.com and www.bar.com pointing to the host where your application is running. On startup you have no information about any of that, you would have to do a reverse DNS search.
When you get a request, you have the information where it is coming from.
You should fill the links on request so you can get rid of caching request scope information.

Is there a SelfAttachingServerResource for Restlet?

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

New to REST - adding a web service class instance to a hashSet

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.

Categories