Jun 25
If you’re developing GWT apps with traditional servlets (other than GWT-RPC) with your web server running as separate process, you can’t really send GWT Ajax messages from hosted mode since the outside process and port are considered to be another domain and GWT won’t send cross domain requests. One clean solution is to use a transparent proxy as hosted mode servlet and let that proxy talk to the real server. Here are the steps I took:
Find following jars are copy them to your GWT project:
{GWT-Project}/war/WEB-INF/lib
jetty-http-7.1.3.v20100526.jar
jetty-io-7.1.3.v20100526.jar
jetty-servlets-7.1.3.v20100526.jar
jetty-continuation-7.1.3.v20100526.jar
jetty-util-7.1.3.v20100526.jar
jetty-client-7.1.3.v20100526.jar
jetty-jmx-7.1.3.v20100526.jar
Add these jars to Referenced Libraries -> Build Path -> Configure Build Path -> Libraries -> Add Jars.
Don’t forget to make sure these jars are selected in ‘Order and Export’ Tab.
Modify {GWT-Project}/war/WEB-INF/web.xml:
<web-app>
<filter>
<filter-name>JettyContinuationFilter</filter-name>
<filter-class>org.eclipse.jetty.continuation.ContinuationFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>JettyContinuationFilter</filter-name>
<url-pattern>/app/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>jetty-proxy-servlet</servlet-name>
<servlet-class>org.eclipse.jetty.servlets.ProxyServlet$Transparent</servlet-class>
<init-param>
<param-name>ProxyTo</param-name>
<param-value>http://localhost:8080/</param-value>
</init-param>
<init-param>
<param-name>Prefix</param-name>
<param-value>/</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>jetty-proxy-servlet</servlet-name>
<url-pattern>/app/*</url-pattern>
</servlet-mapping>
</web-app>
Now all your URLS in your GWT app starting with ‘/app’ are normally forwarded to your traditional web server at localhost:8080.
BTW, I got these jetty jars from my local maven .m2 repository.
Tagged with: gwt • java • jetty • web development
Jun 04
If you’re getting ClassNotFoundException for your GWT server servlets, even though the class exists and is ok, you might want to check out the Build Path in Eclipse and make sure All libraries are selected in
Java Build Path -> Order and Export.
The error message could be confusing and misleading. Hope this tip saves you some time.
Tagged with: gwt • java • web development
May 26
Dependency Injection is supposed to make your life easier when it comes to writing Unit and Integration Tests; assuming you do your homework right and indeed make use of Injection. With Spring 3 annotations like @Autowired and configurations like , there really is no excuse for sloppiness.
Here’s is how to reap the rewards of DI when writing unit tests. You can dependency inject each Test Class using same @Autowired annotation that you use for your normal classes.
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"classpath:spring-config.xml"})
public class MyClassTest {
@Autowired
private TransferMoneyStrategy strategy = null;
....
@Test
public void test_transfer() {
// write Asserts here
}
}
Key is the annotation @ContextConfiguration – one line is all you need to boot up entire Spring infrastructure!
Tagged with: java • programming • software • spring • test • unit-test
Oct 14
RESTful programming is all the rage these days – at least in Rails world. It's a simple way to perform request dispatching which is easy to understand and maps database CRUD operations into web requests elegantly. While Rails comes with REST routing built in, there is no such support in Spring MVC. However, Spring's decoupled design makes it rather easy to implement. Here's code I wrote to implement RESTful dispatches using Spring MVC.(Also available as a download here)
package com.yellowfish.servlets;
import javax.servlet.http.*;
import org.apache.log4j.*;
import java.util.*;
import org.springframework.web.servlet.mvc.multiaction.*;
public class RESTMethodResolver implements MethodNameResolver {
public String getHandlerMethodName(HttpServletRequest req) throws NoSuchRequestHandlingMethodException {
Logger log = Logger.getLogger("com.yellowfish.servlets");
log.debug("Resolving method name for the Request");
String method = req.getParameter("_method");
String id = req.getParameter("id");
String http_method = req.getMethod().toUpperCase();
String controller_method = null;
log.debug("method: "+method+" http_method: " + http_method + " id: "+id);
if(http_method.equals("GET")) {
String uri = req.getRequestURI();
controller_method = (uri.endsWith("/new") ? "_new" : "show");
if(controller_method == "show") {
controller_method = (id == null) ? "index" : "show";
}
} else if(http_method.equals("POST")) {
if(method != null) {
method = method.toUpperCase();
if(id == null)
throw new com.yellowfish.servlets.ServletException("id cannot be NULL for PUT and DELETE");
if (method.equals("PUT"))
controller_method = "update";
else if(method.equals("DELETE"))
controller_method = "delete";
} else {
controller_method = "create";
}
}
if(controller_method == null) {
log.debug("No Controller Method Found");
throw new NoSuchRequestHandlingMethodException(null, this.getClass());
}
log.debug("Controller method resolved to :" + controller_method);
req.setAttribute("controller_method_name", controller_method);
if(id != null) {
try {
req.setAttribute("model-id", Long.valueOf(id));
} catch(NumberFormatException exp) {
log.warn("id" + id + " is not a Number");
}
}
return controller_method;
}
}
Then simply declare this bean in the spring config:
<bean class="com.yellowfish.servlets.RESTMethodResolver" id="rest-method-resolver"></bean>
It resolves incoming URL and Method as per following table:
REST Resolver Rules
| URI |
GET/POST |
ID Parameter Present? |
_method Parameter Present? |
Method Name |
| /server |
GET |
No |
N/A |
index |
| /server/_new |
GET |
No |
N/A |
new |
| /server?id=100 |
GET |
Yes |
N/A |
show |
| /server |
POST |
No |
No |
create |
| /server |
POST |
Yes |
PUT |
update |
| /server |
POST |
Yes |
DELETE |
delete |
To make life simple, the code above assumes all IDs to be numeric and if ID is present in incoming request, it creates a Request attribute called 'model-id' .
Tagged with: design pattern • mvc • spring • web development