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

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);
}
}

Related

Creating a Spring 4 MVC project with annotations and no xml files

I'm new to Spring MVC and Hibernate. I'm trying to start a project by following tutorials but I have been running into problems as my project structure is not consistent with the tutorials I am reading.
I have downloaded the latest STS and I do see the option of creating an Spring MVC project. However it is based on Spring 3 and still uses XML files. From what I have read it looks like there is a way to do it without XML files since Spring 3. I prefer annotations over XML files greatly.
How can I create a Spring MVC 4 application that is based on annotations and relies on xml files minimally?
EDIT:
I want to create a web project
Here is a squeletal example of full java configuration. You will need :
a class extending AbstractAnnotationConfigDispatcherServletInitializer to replace the old web.xml file
one or more #Configuration annotaded class(es) to initialize the root context (replaces the old applicationContext.xml)
one or more #Configuration annotaded class(es) to initialize the DispatcherServlet context (replaces the old dispatcher-servlet.xml)
This is the web.xml :
public class WebAppConf extends AbstractAnnotationConfigDispatcherServletInitializer {
#Override
protected Class<?>[] getRootConfigClasses() {
// declare root context configuration classes
return new Class<?>[]{ RootConf.class };
}
#Override
protected Class<?>[] getServletConfigClasses() {
// declare servlet context configuration classes
return new Class<?>[]{ ServletConf.class };
}
#Override
protected String[] getServletMappings() {
// mapping of DispatcherServlet
return new String[]{"/"};
}
#Override
protected void customizeRegistration(Dynamic registration) {
// additional configuration, here for MultipartConfig
super.customizeRegistration(registration);
MultipartConfigElement multipartConf = new MultipartConfigElement("", 200000L, -1L, 0);
registration.setMultipartConfig(multipartConf);
}
}
RootConf will declare business model, service and dao beans and is not shown here.
ServletConf declares the controllers and servlet configuration :
#Configuration
#EnableWebMvc
// declare where to find annotated controllers
#ComponentScan({"org.example.web"})
public class ServletConf extends WebMvcConfigurerAdapter {
#Bean
MultipartResolver multipartResolver() {
return new StandardServletMultipartResolver();
}
#Bean
ViewResolver internalViewResolver() {
// the view resolver bean ...
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/jsp/");
resolver.setSuffix(".jsp");
return resolver;
}
}
As said above, it is squeletal, but it comes from a working minimal example so you should be able to start with that and extend it at will. In my example, the above three classes live in a org.example.config package that will never be scanned for autodetecting other configuration classes or annotated beans.
Hope it helps ...
I know this doesn't answer your question fully, but hopefully the links will be useful.
WebApplicationInitializer - A 100% code based approach to configuration
as well as AnnotationConfigWebApplicationContext
Also, if you have the time, reading the relevant sections of Spring's MVC chapter of their documentation is helpful.
I Wish that this link will be helpful for you Spring security with annotation Mkyong
The latest versions of STS integrate the Spring guides from https://spring.io/guides directly, try the "Import Spring Getting Started Content" wizard. There are good guides included for creating a Spring Boot based web service, for example, among many others.

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.

Servlet: forward request to Servlet by its name when using annotations instead of web.xml?

I have an entry servlet (called DispatcherServlet) which redirects all incoming GET and POST requests at /* to other servlets depending on a configuration parameter. In order to dispatch the request to other servlets, I use their name instead of a path, because my DispatcherServlet would end up in an endless loop while listening to /*.
The "old" way was to give servlets a name in the web.xml descriptor:
<servlet>
<servlet-name>MyServlet</servlet-name>
<servlet-class>mypackage.MyServlet</servlet-class>
</servlet>
Afterwards, one is able to address the servlet by its name, for example, when using a RequestDispatcher. The code in my DispatcherServlet looks like this:
RequestDispatcher dispatcher = getServletContext().getNamedDispatcher("MyServlet");
dispatcher.forward(request, response);
This works perfectly. But, I would like to use the "new" Servlet 3 annotations without the web.xml, hence I do this:
#WebServlet(name="MyServlet")
public class MyServlet extends HttpServlet {
...
But now, getServletContext().getNamedDispatcher("MyServlet") within my DispatcherServlet returns null instead of the appropriate dispatcher for MyServlet, although I expect that #WebServlet(name="MyServlet") behaves the same like <servlet-name>MyServlet</servlet-name>
I have tested this on Tomcat 7.
Is this because MyServlet has not been loaded yet by the time when DispatcherServlet is called and hence the name of MyServlet is not known? If so, what sense does the #WebServlet(name="...") annotation make ;)
Please don't answer with something like "why don't you use filters?" etc. This is more about the background of annotations vs. web.xml
Thanks in advance!
(ps. please change the title if you find a more suitable one ;))
If you do not specify the urlMapping with the name, you will need do add the full class name. Like
RequestDispatcher dispatcher = getServletContext().
getNamedDispatcher("mypackage.MyServlet");
It works for me if the servlet is annotated as:
#WebServlet(urlPatterns="/Servlet", name="Servlet")
or better:
#WebServlet(urlPatterns="/Servlet", displayName="Servlet", name="Servlet")
Also, you can try to get your servlet name with:
getServletName()
By just comment with #WebServlet is not enough to load a Servlet into the Web container; you must include at least one URL pattern, and if you don't want to expose the Servlet to keep it for internal forward only, set the URL to start with '/WEB-INF/'.
And keep in mind that the 'name' property is buggy, so not use it.
#WebServlet(urlPatterns = "/WEB-INF/thisServlet")
public class FooServlet extends HttpServlet {
...
}
and to forward the request, call something like this:
servletContext.getNamedDispatcher(FooServlet.class.getName()).forward(request, response);

Restlet API example

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.

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>