After reading a bunch of confusing articles describing how to install the java plugin into Firebox on Ubuntu Linux 9.04, I found that there is already a package for it:
sudo apt-get install sun-java6-plugin
Notes on software tech with a special focus on image processing, pattern recognition/machine learning, java open source tools, and high performance computing.
After reading a bunch of confusing articles describing how to install the java plugin into Firebox on Ubuntu Linux 9.04, I found that there is already a package for it:
sudo apt-get install sun-java6-plugin
Using Spring Security with GWT is fairly easy . . . just protect your GWT page and its associated servlets.
But one tricky thing is handling expired logins. When your user's login expires, they may be in the middle of using your web application. They will probably click some widget that will generate a call to the server. Because the login has expired, Spring Security will return your login page instead the expected server response. So you need to set up your GWT client code to handle this.
I got some good tips on how to do this on this page, but to make the ideas contained there a little more concrete, let me give some example code.
In my case, I wrapped the DisplayCallback class from the GWT Presenter library, but you should be able to apply these ideas to any gwt AsyncCallback.
/**
* This is a special version of DisplayCallback that will handle Spring/Acegi
* security errors. If a 403 Access Denied errors occurs, the user will be
* shown an error message. If the server returns a Login page, that means the
* user's login has presumably expired, so we direct the browser to redirect
* to our login page.
*
* Credit for these ideas comes from here:
* http://www.dotnetguru2.org/bmarchesson/index.php/2007/04/23/technical_tip_using_acegi_with_gwt
*
*/
public abstract class MyDisplayCallback<T> extends DisplayCallback<T> {
private static final String SERVER_ERROR = "An error occurred while "
+ "attempting to contact the server. Please check your network "
+ "connection and try again.";
public StatProjDisplayCallback(Display display) {
super(display);
}
@Override
protected final void handleFailure(Throwable cause) {
doCleanup();
String errorMessage = cause.toString();
if (errorMessage.indexOf("403") != -1)
{
// Access denied for this role
Log.debug("login invalid for this resource");
if (GWT.isClient()) {
Window.alert("Access denied");
}
}
else if (errorMessage.indexOf("Login") != -1)
{
Log.debug("login expired, showing login dialog");
if (GWT.isClient()) {
Window.Location.assign("login.jsp?relogin=true");
}
}
else
{
Log.error("Handle Failure:", cause);
Window.alert(SERVER_ERROR);
}
}
/**
* This method can be overriden to include code that should run in case the server call fails.
* This method will be called by handleFailure()
*/
protected void doCleanup() {};
@Override
protected abstract void handleSuccess(T value);
}
Hopefully I will spiff this post up with some screenshots, but for now, let me just quickly note the steps that were required to get this to build.
The Hive Development blog has a nice tutorial on setting up a Google Web Toolkit app with the Presenter and Dispatcher patterns. This is all based on a nice Google presentation explaining some useful patterns for developing robust app with GWT.
I recommend watching the video first and then reading the hivedevelopment blog article. Read through it and then download the full source code using the link near the top of the page. In the end, it's helpful example starter application for exploring concepts.
Anyways, the framework that you end up with uses Google Guice for server-side dependency injection and the servlet config. I am going to describe how I converted that to use Spring instead, using the GWT-Dispatch-Spring library. Comments are welcome since I am probably not doing things optimally in some places.
Why would you want to do this? I think it is personal preference whether you use Guice or Spring (nice discussion/war going on here). I am fairly new to both so I don't have a personal opinion. In the end of this, you will end up with a project using Guice's ally Gin on the client and Spring on the server, so you can be like Switzerland and remain neutral. ;)
The major steps described here include:
@Component
public class SendGreetingHandler extends SpringActionHandler<SendGreeting, SendGreetingResult> {
@Autowired
public SendGreetingHandler(ActionHandlerRegistry actionHandlerRegistry) {
super(actionHandlerRegistry);
}
@Override
public SendGreetingResult execute(final SendGreeting action,
final ExecutionContext context) throws ActionException {
final String name = action.getName();
try {
String serverInfo = RemoteServiceUtil.getThreadLocalContext().getServerInfo();
String userAgent = RemoteServiceUtil.getThreadLocalRequest().getHeader("User-Agent");
final String message = "Hello, " + name + "!<br><br>I am running " + serverInfo + ".<br><br>It looks like you are using:<br>" + userAgent;
//final String message = "Hello " + action.getName();
return new SendGreetingResult(name, message);
}
catch (Exception cause) {
throw new ActionException(cause);
}
}
@Override
public void rollback(final SendGreeting action,
final SendGreetingResult result,
final ExecutionContext context) throws ActionException {
// Nothing to do here
}
@Override
public Class<SendGreeting> getActionType() {
return SendGreeting.class;
}
}
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd"> <context:annotation-config /> <context:component-scan base-package="com.adeoservices.gwt.dispatch.spring.server" /> <context:component-scan base-package="co.uk.hivedevelopment.greet.server" /> </beans>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.gwtrpcspring.RemoteServiceDispatcher</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>*.rpc</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>remoteLoggerServiceImpl</servlet-name>
<servlet-class>com.allen_sauer.gwt.log.server.RemoteLoggerServiceImpl</servlet-class>
</servlet>
<!-- Default page to serve -->
<welcome-file-list>
<welcome-file>GreetMvp.html</welcome-file>
</welcome-file-list>
</web-app>
At this point, we have converted the Server side code to use Spring instead of Guice. Try running the app. You will probably notice a bunch of logging statements in the Console regarding the Spring dependency injection scanning:
1253 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating instance of bean 'sendGreetingHandler' 1254 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'springActionHandlerRegistry' 1255 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Autowiring by type from bean name 'sendGreetingHandler' via constructor to bean named 'springActionHandlerRegistry'
Try clicking the button to send the GreetAction to the server. You get an error because we haven't yet adjusted the client to work with Spring and to look for the new Spring RemoteServiceDispatcher that we defined in our new web.xml.
First, we need to add the Dispatch-Spring library to our client code. Add the highlighted line to GreetMvp.gwt.xml:
<inherits name='net.customware.gwt.dispatch.Dispatch' /> <inherits name="com.adeoservices.gwt.dispatch.spring.Dispatch-Spring"/>
Now, we just need to use the Spring-based DispatchAsync. Here is how I did it. I don't like it this way, so maybe somebody can help me (I'll explain). Go to the GreetingPresenter. Modify the constructor so that it takes a SpringDispatchServiceAsync instead of DispatchAsync:
public GreetingPresenter(final Display display, final EventBus eventBus, final SpringDispatchServiceAsyncImpl dispatcher, final GreetingResponsePresenter greetingResponsePresenter) {
What I don't like is how the GreetingPresenter now requires a specific implementation for DispatchAsync. What would be more appropriate is to configure Gin to inject the correct implementation in GreetingClientModule. At this point, I can't figure out how to get this to work: gin complains that DispatchAsync has been "double-bound". But I am basically brand new to Gin/Guice so I'm probably missing something.
In any case, the app should be working and the Client should receive a valid response from the server. You now have a working example using Spring on the server!
The ESXX blog has some handy code for integrating Apache HttpClient 4 with Google App Engine. Since it includes working source code, everything you need to figure it out is there. However, it can be a little confusing at first if you try dropping the code directly into an App Engine project. Your project will fail to compile as it uses several functions that are not supported by the App Engine SDK.
Instead of putting the problematic source code directly in your project, put them in a separate jar file. Then you can include that jar file in your project and everything should work fine.
I did this by creating a simple java project in eclipse, with just the two adapter code files. To get this to build, I also included the apache httpclient jars and the app engine sdk jar. I've included an image of my simple project structure here. Eclipse should automatically build the files once those jars are in place.
Then, at the command line, I simply went to that project's build directory and manually built the jar file using "jar cf GAEHttpClient.jar *". You can of course use your own jar file name. Make sure you build the jar at the root of your build directory structure.
Once your jar file is built, you should be able to add it to your main App Engine project (right click on the project in your Package Explorer and go to Build Path-> Configure Build Path-> Add external JARs . . . then add it to your war/WEB-INF/lib directory using File->Import->General->File System . . .) Once you have that (and the Apache httpclient jars) in place, you should be able to compile your code without error:
HttpParams httpParams = new BasicHttpParams(); ClientConnectionManager connectionManager = new GAEConnectionManager(); HttpClient httpClient = new DefaultHttpClient(connectionManager, httpParams);
Copyright 2010 README.txt. Blog Templates created by Web Hosting Men