Restlet API example - rest

Is there any simple example of Restlet API with Java?
I want a simple example of Restlet API by calling Get / POST method. One client should call one method from the server through Restlet. The server should execute that method and send the reply accordingly. How can the server open those methods to respond to the client using Restlet?

here simple code which call amazon.java rest class when its match with url as
http://anydomain.com/amazone if you hit this in url than its called get method
public class RestApi extends Application {
/**
* Creates a root Restlet that will receive all incoming calls.
*/
#Override
public Restlet createInboundRoot() {
Router router = new Router(getContext());
// Defines only one route
router.attach("/amazon", Amazon.class);
return router;
}
}
amazon.java
public class Amazon extends ServerResource {
#Override
protected Representation post(Representation entity)
throws ResourceException {
System.out.println("post Method");
return super.post(entity);
}
#Override
protected Representation get() throws ResourceException {
System.out.println("get method");
return super.get();
}
}
and mapping in web.xml file as
<servlet>
<servlet-name>RestletServlet</servlet-name>
<servlet-class>org.restlet.ext.servlet.ServerServlet</servlet-class>
<init-param>
<param-name>org.restlet.application</param-name>
<param-value>com.wa.gwtamazon.server.RestApi </param-value>
</init-param>
<!-- Catch all requests -->
<servlet-mapping>
<servlet-name>RestletServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>

You may want to consider looking at http://www.restlet.org/documentation/ the documentation provided by the project provides good examples to get started with using the code.
Version 2.1 is currently the stable branch and the #Get, #Post, etc. annotations, available to be used on your ServerResource, provide a slightly more flexible approach than outlined by Divyesh, although that approach is I believe still also available.

Related

how to minimize servlet declarations for gwt-rpc in web.xml?

Sorry I am still a beginner in GWT. I have noticed that when my project was grow up , the declarations of servlets for rpc in web.xml file are many, many and many. For a single *ServiceImpl class , we need to define in web.xml as
<servlet>
<servlet-name>greetServlet</servlet-name>
<servlet-class>com.my.testing.server.GreetingServiceImpl</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>greetServlet</servlet-name>
<url-pattern>/testing/greet</url-pattern>
</servlet-mapping>
If if have 30 *ServiceImpl class, they may take about 200 lines in web.xml for rpc calls. So , I would like to know
Is web.xml file the only place to declare rpc servlets ?
Has someways to skip declarative styles (I mean via annotations '#' etc) ?
GWT works pretty well without these declarations in web.xml, using Annotations:
/*
* this is your server-side rpc-implementation
*/
#WebServlet(name = "YourService", urlPatterns = {"/path/to/yourservice"})
public class YourServiceImpl extends RemoteServiceServlet implements YourService {
public void doSomething() {
//some code
}
}
/*
* this is the corresponding rpc-interface
*/
#RemoteServiceRelativePath("path/to/yourservice")
public interface YourService implements RemoteService {
void doSomething();
}
The resulting path to your servlet depends on you project structure. If your project is deployed in your servers root, you will find your servlet there (with the path you specified with urlPatterns above). However, if you deployed your project under its own URI, you will have to prepend this to the urlPattern.
If you use Guice, this case can be easy solved using ServletModule.
In this module you may programmatically define (and test in JUnit) all your RPC servlets and filters as well.
Example:
public class WebModule extends ServletModule {
#Override
protected void configureServlets() {
// configure filters
filter("/*").through(CacheControlFilter.class);
filter("/*").through(LocaleFilter.class);
// bind XSRF servlet
bind(XsrfTokenServiceServlet.class).in(Singleton.class);
serve("/gwt/xsrf").with(XsrfTokenServiceServlet.class);
// configure servlet mapping
serve("path/to/servlet").with(LoginServiceImpl.class);
}
}

GWT: How to extract a content of a javascript function using (JSNI)

I am calling a javascript function from gwt client side using JSNI like follow:
anchor.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
execute(notification.getActionCode(), notification.getParams());
}
});
private static native String execute(String functionName, String params)/*-{
try{
$wnd[functionName](params);
}catch(e){
alert(e.message);
}
}-*/;
My problem is that my javascript function contains window.open("ServletName?....").
When clicking on the anchor, the window opened with error below:
The requested resource (/es/gwt/core/ServletName) is not available.
if i replace window.open("ServletName?....") by window.open("../../ServletName?...."), the window open successfully, but these javascript functions are used also outside gwt so i cant modify it .
I dont know why the part /gwt/core is being added to the url which is causing the problem.
Is there a way in gwt before executing the javascript function, to extract its content and adding the "../.." before the url? i mean heaving the javascript function name, can we get its content before calling the execute function? in my case my javascript function is a follow:
function everlinked_AddSpace(spaceId){
window.open('ELUtilities?Service=Space&action=homePage&SpaceId='+spaceId+'&Template=apps/everlinked/templates/spaces/space_main.htm','_blank');;
}
i need to modify it in gwt client side and call it with the new modifications.
I appreciate if someone could help me.
I think you are trying to resolve your problem using a bad approach.
The easier way is to use an url re-writer, or to modify your web.xml url-pattern to route the relative path sent by your gwt app to the same servlet.
Probably you have in your web.xml something like this:
<servlet>
<servlet-name>myservlet</servlet-name>
<servlet-class>maynamespace.ServletName</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>myservlet</servlet-name>
<url-pattern>/ServletName</url-pattern>
</servlet-mapping>
So you can add this block to your web.xml.
<servlet-mapping>
<servlet-name>myservlet</servlet-name>
<url-pattern>/es/gwt/core/ServletName</url-pattern>
</servlet-mapping>
Note that url-pattern has a very limited set of regular expressions (/path/* and *.ext), so in your case you have to write the full path.

GWT rpc failing - base url not what I expected

I am trying to become familiar with using the GWT api to create web based applications. I have been following some tutorials on GWT and have not yet been able to make an RPC call. Looking at the problem with a broad scope, my goals are to make a server call to run a series of database tests that I know work (ive tested this code).
---EDIT---
I think that the problem here is that the resource is being looked for here:
/MatesWeb/org.matesweb.Main/peopleService
when I think it should be looked for here:
/MatesWeb/peopleService
---END_EDIT---
Here is the info and code I feel is relevant:
-using netbeans
-error that I am getting is "/MatesWeb/org.matesweb.Main/PeopleService - description - The requested resource is not available."
-GWT.getModuleBaseURL() returns: :8080/MatesWeb/org.matesweb.Main/
-URL in browser is: :8080/MatesWeb/
from web.xml file
<servlet>
<servlet-name>peopleService</servlet-name>
<servlet-class>org.matesweb.server.PeopleServiceImpl</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>peopleService</servlet-name>
<url-pattern>/peopleService</url-pattern>
</servlet-mapping>
From PeopleService Service
package org.matesweb.client;
import com.google.gwt.user.client.rpc.RemoteService;
import com.google.gwt.user.client.rpc.RemoteServiceRelativePath;
#RemoteServiceRelativePath("PeopleService")
public interface PeopleService extends RemoteService {
String[] saveGetPerson(String[] persInfo);
int runTests();
}
From PeopleServiceImpl
package org.matesweb.server;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;
import org.matesweb.client.PeopleService;
import org.matesweb.server.tests.DbTest;
class PeopleServiceImpl extends RemoteServiceServlet implements PeopleService {
#Override
public String[] saveGetPerson(String[] persInfo) {
throw new UnsupportedOperationException("Not supported yet.");
}
#Override
public int runTests()
{
int retInt;
DbTest dbTest = new DbTest();
retInt = dbTest.runTests();
return retInt;
}
}
From PeopleServiceAsync
package org.matesweb.client;
import com.google.gwt.user.client.rpc.AsyncCallback;
public interface PeopleServiceAsync
{
void saveGetPerson(String[] persInfo, AsyncCallback<String[]> persInformation);
void runTests(AsyncCallback<Integer> retInt);
}
Any idea of whats going on here?
Cheers,
Nick
#RemoteServiceRelativePath("PeopleService")
The #RemoteServiceRelativePath annotation is used to decide what url to hit. This path to the server is relative to the compiled module itself - the gwt app loaded from the path /MatesWeb/org.matesweb.Main/, so the service is being sought out at /MatesWeb/org.matesweb.Main/PeopleService. I assume this means you have an html file in the MatesWeb/ directory (probably the .war file is called MatesWeb?), and inside of there exists the compiled app in org.matesweb.Main/, including the initial JS file, org.matesweb.Main.nocache.js.
If you want to tell the service to be found at /MatesWeb/peopleService, you have two options. The first is to modify the annotation to back up a directory, something like this:
#RemoteServiceRelativePath("../peopleService")
Using .., I indicate the parent directory, and I also changed the case of the path part 'peopleService' - this may or may not matter. A second option is to set the url programmatically:
PeopleServiceAsync service = GWT.create(PeopleService.class);
((ServiceDefTarget)service).setServiceEntryPoint("/MatesWeb/peopleService");
As referenced in the #RemoteServiceRelativePath javadocs http://google-web-toolkit.googlecode.com/svn/javadoc/latest/com/google/gwt/user/client/rpc/RemoteServiceRelativePath.html.
If, instead, you want to leave the client as is and tell the server that this service should be at the path the client expects, you can modify the web.xml to make the servlet available at the path that the client is currently expecting to find it:
<servlet-mapping>
<servlet-name>peopleService</servlet-name>
<url-pattern>/MatesWeb/org.matesweb.Main/PeopleService</url-pattern>
</servlet-mapping>
Note again that I've changed the case - it may not matter, but I generally like to be consistent.
First hunch is PeopleService must be peopleService in the #RemoteServiceRelativePath . Please use firebug to monitor your rpc requests. You can observe and verify request url issues like these easily.
Update your URL pattern in web.xml as in here
<url-pattern>/org.matesweb.Main/greet</url-pattern>

GWT Maven build with maven profiles

I'm attempting to use capabilities provided by maven profiles to build customized builds for different server environments. What I'm attempting to do is combine maven resource filtering
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
with it's profile mechanism
<profiles>
<profile>
<id>mock</id>
<properties>
<application-url>http://mock-server-url</application-url>
</properties>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
</profiles>
to convert this value in a file named server.cfg
${application-url}
to something I can use here:
public interface ServerResource extends ClientBundle {
public static final ServerResource INSTANCE = GWT.create(ServerResource.class);
#Source("server.cfg")
public TextResource server();
}
I can see that the value's been replaced in WEB-INF/classes but it doesn't appear that GWT used the file with the replacement to create the application javascript. How can I do this?
Using GWT compiler permutations to apply this kind of configuration is in my opinion a very bad idea. One of the most common complaints about GWT is the time it takes to compile, and by doing this you're just adding to the problem.
Configuration should usually be read from configuration files (surprise!), like shown here.
Anyway, what you're trying to do seems to me impossible. You cannot tell the client-side code to which server it should connect. This would violate the same-origin policy! The app can only communicate with the server it came from.
To have different apps running in different URLs, you would need to deploy several GWT apps with different names (even if they are basically the same). Then, you would just have to type the correct URL for each app (version) in the browser, and it will "look" at the right app. So you could have URLs like this:
http://myserver.com/app1
http://myserver.com/app2
In order to make a request to a different app running in the same server as the GWT application, you can do something like this:
String serviceUrl = "/app2/someService"; // or some other String sourced from a config file, using a GWT ClientResource for example
RequestBuilder rb = new RequestBuilder(RequestBuilder.GET,
serviceUrl);
try {
// send request from app1 to app2
rb.sendRequest(null, new RequestCallback() {
#Override
public void onResponseReceived(Request request,
Response response) {
log.info("Response: " + response.getStatusText());
// if response is 200 it's ok, you can read the outputStream to see what's in there
}
#Override
public void onError(Request request, Throwable exception) {
log.warning("Request Error", exception);
// do something more
}
});
} catch (RequestException e) {
log.warning("Request Exception", e);
// getting here means trouble with the connection or service!
}
I solved what I was trying to accomplish without the use of maven profiles or the GWT ClientBundle (which I never did get to work in the way I had intended when I wrote the question).
Here were the main issues I hoped to solve using maven profiles and the workaround I employed to solve the issue at hand:
Use Mock MVP Models in Hosted Mode
// inside the initialization for my model locator
boolean hostedMode = GWT.getPermutationStrongName().equals("HostedMode");
if (hostedMode) {
// instantiate mock models
} else {
// instantiate real models to call REST web services
}
Provide real models with correct RESTful server URL
I was able to accomplish this because my GWT app and the RESTful web service url follow a set naming convention. I basically strip the trailing '/' from the URL and append '_services"
String createServicesBaseUrl() {
StringBuffer baseUrl = new StringBuffer(GWT.getHostPageBaseURL());
int length = baseUrl.length();
baseUrl.replace(length-1, length, "_services");
return baseUrl.toString();
}
Enable testing of as much of the MVP Presenter (Activities & Places) as I could
I was already injecting the model locator into my Activity classes, so replacing that with a mock model locator for use by JUnit was straightforward. I did the same for my views and abstracted away some of the other code which didn't seem to work outside of the browser (like the GWT PlaceController).
All in all my build is much the same, but I learned how to gain a lot of flexibility in testing, configuring the server instance my GWT application connects with, and which model my application uses (dependent on hosted vs server mode).

Communicating between an HttpServlet and the client side of a GWT application

I have a simple GWT application that consists of a FormPanel that contains a single FileUpload field. The action on this form is to send it to GWT.getModuleBaseURL() + "process", which web.xml in turn tells GWT is the FileProcessServlet.
FileProcessServlet is a class that I made that extends HttpServlet and overrides doPost(HttpServletRequest req, HttpServletResponse resp) to parse the uploaded file and turn it into a Base64 string using Base64Utils. Now, I would like to pass the client side a single string that is the Base64 encoding of the file just sent it.
For the life of me, I just cannot figure out how to do this. The GWT documentation on Communicating with the Server doesn't say anything about receiving information back from a FormPanel.submit(). There is no callback function associated with such a request, as is the case with GWT RPC. At the same time, I need to use a servlet, since I want to parse a file, and that can't be done by the client. Any suggestions?
~~~~
PS: One option is that I can write directly to the html page from the servlet using java.io's PrintWriter (as this suggests). This may present a kind of solution where I store the Base64 string in a div with a special ID and then use DOM to get this content on the client end. However, I have not yet gotten PrintWriter to cooperate with me. Anytime I use it, with varying content types and character encodings, I still see nothing printed on the page. What I currently have attempting to print this out is:
String base64 = Base64Utils.toBase64(file);
resp.setContentType("text/html; charset=UTF-8");
resp.setCharacterEncoding("UTF-8");
PrintWriter out = resp.getWriter();
out.print(base64);
out.flush(); out.close();
But nothing comes out. The debugger has confirmed that the string base64 is not null nor empty on the penultimate line. Any help on this related front would also be appreciated. Nonetheless, I sincerely hope there is a better way.
form.addSubmitCompleteHandler(new FormPanel.SubmitCompleteHandler() {
public void onSubmitComplete(SubmitCompleteEvent event) {
// When the form submission is successfully completed, this event is
// fired. Assuming the service returned a response of type text/html,
// we can get the result text here (see the FormPanel documentation for
// further explanation).
Window.alert(event.getResults());
}
});
Whatever you write out from the servlet, will be in the event.getResults(), in your case the base64 String
Well I'm not 100% sure if your problem is on client or server side.
For the client:
formPanel.setAction("/[urlMappingOfYourServlet]");
formPanel.setEncoding(FormPanel.[CORRECT_ENCODING]);
formPanel.setMethod(FormPanel.METHOD_POST);
And to start the submission:
formPanel.submit();
Don't forget the mapping of your servlet in your web.xml. E.g.:
<servlet>
<servlet-name>nameOfYourServlet</servlet-name>
<servlet-class>your.package.server.YourServletClass</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>nameOfYourServlet</servlet-name>
<url-pattern>/urlMappingOfYourServlet</url-pattern>
</servlet-mapping>
On the server side you get the parsed data:
String data = request.getParameter("[NameOfYourFormPanelItem]");
You could use a javax.servlet.ServletOutputStream instead of PrintWriter.
ServletOutputStream out = resp.getOutputStream();
out.write(base64);
out.flush();
Another possibility is to use a RequestBuilder on the client side:
RequestBuilder requestBuilder = new RequestBuilder(RequestBuilder.POST, "/urlMappingOfYourServlet");
requestBuilder.sendRequest(someData, new RequestCallback() {
#Override
public void onResponseReceived(Request request,
Response response) {
// ToDo: Get your String here
response.getText();
}
#Override
public void onError(Request request, Throwable exception) {
// ToDo
}
});