Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » Remote Application Platform (RAP) » Simple non-UI object example
Simple non-UI object example [message #846346] Mon, 16 April 2012 01:34 Go to next message
Michael Ihde is currently offline Michael IhdeFriend
Messages: 10
Registered: July 2009
Junior Member
I'm trying to understand how to use RAP to provide client<->server communication without a widget in the loop. I've tried to use the Geolocation code in the rap-mobile github source and AbstractObjectSyncronizer seemed like it might be the clue I needed...but there was no client-side code in the Git repo for me to complete the picture.

Here is a simple hypothetical that I hope will point me in the correct direction. I have a third-party Javascript library that I load into RAP using the org.eclipse.rap.ui.resources extension point. This Javascript library has a function ThirdPary.isSomethingReady().

In the Activator of my bundle I want to execute this client-side code and then read the result. My naive approach is to try something like this:

  JSExecutor.executeJS("var isReady = ThirdPary.isSomethingReady()");


But then I'm stuck figuring out how to read the isReady result. Thanks for any help/illumination you can provide!

~Michael
Re: Simple non-UI object example [message #846697 is a reply to message #846346] Mon, 16 April 2012 09:52 Go to previous messageGo to next message
Ralf Sternberg is currently offline Ralf SternbergFriend
Messages: 1313
Registered: July 2009
Senior Member

Hi Michael,

there is no recipe to follow yet for non-widget components. Many of the
parts involved are still under development. For RAP 2.0, we'll have a
tutorial on that topic available. Until then, here's how you can issue a
request from the client:

var isReady = ThirdPary.isSomethingReady();
var request = org.eclipse.swt.Request.getInstance();
request.addParameter( "ThirdPary.ready", isReady );

If you want to inform the server immediately, you can also call
request.send(). If you omit this call, the parameter will be transmitted
with the next request.

On the server side, you'll have to read and process this parameter.
Check out the GeolocationSynchronizer for an example.

Hope this helps,
Ralf


--
Ralf Sternberg

Twitter: @EclipseRAP
Blog: http://eclipsesource.com/blogs/

Professional services for RAP and RCP?
http://eclipsesource.com/services/rap/
Re: Simple non-UI object example [message #846808 is a reply to message #846697] Mon, 16 April 2012 19:25 Go to previous messageGo to next message
Mark Leone is currently offline Mark LeoneFriend
Messages: 69
Registered: April 2012
Member
I work with Michael. Here's how we implemented the server side reading of the request parameter.

final LifeCycle lc = RWT.getLifeCycle();
lc.addPhaseListener(new PhaseListener() {

    public void beforePhase(PhaseEvent event) {}

    public void afterPhase(PhaseEvent event) {
        String isReady = RWT.getRequest().getParameter("ThirdParty.ready");
        ...
        lc.removePhaseListener(this);
    }

    public PhaseId getPhaseId() {
        return PhaseId.READ_DATA;
    }

}

JSExecutor.executeJS(...



This is working fine. But it raises a further question. It seems that for future applications we might want to use Session or Application scope rather than request scope for passing objects from client to server. Of course we can access Session and Application attributes on the server side as with any web app using the JEE protocol. But is there a way on the client side to get access to the Session and/or Application containers and set attributes on them? That is, are there Session and/or Application analogs to
org.eclipse.swt.Request.getInstance()
Re: Simple non-UI object example [message #847589 is a reply to message #846808] Tue, 17 April 2012 12:56 Go to previous messageGo to next message
Ralf Sternberg is currently offline Ralf SternbergFriend
Messages: 1313
Registered: July 2009
Senior Member

Hi Leone,

please note that a phase listener has application scope, not session
scope. You have to compare the current display with the session display
to make your code behave correctly in a multi-user environment. See the
class AbstractObjectSynchronizer as an example.

As long as you're in the UI thread (and you are during request
processing), you can always store attributes in the session store
`RWT.getSessionStore()` or the application store
`RWT.getApplicationStore()`.

Best regards, Ralf

--
Ralf Sternberg

Twitter: @EclipseRAP
Blog: http://eclipsesource.com/blogs/

Professional services for RAP and RCP?
http://eclipsesource.com/services/rap/
Re: Simple non-UI object example [message #847912 is a reply to message #847589] Tue, 17 April 2012 19:29 Go to previous messageGo to next message
Mark Leone is currently offline Mark LeoneFriend
Messages: 69
Registered: April 2012
Member
Thanks Ralf. I understand how to get access to Session and Application objects on the server. What I'm missing is how to get access to them from the client, in Javascript. The examples I've seen so far set a parameter on the request, as in the code you provided earlier, namely

var request = org.eclipse.swt.Request.getInstance();
request.addParameter( "ThirdPary.ready", isReady );


But if I want to place an object from the client into Session or Application scope, is there an equivalent Javascript class to retrieve an object that represents the Session and or Application context? If I were coding a traditional JEE app, I could of course pass objects at Application and Session scope from the client to the server; so I'm wondering if I can do that in RAP also.

-Mark
Re: Simple non-UI object example [message #849880 is a reply to message #847912] Thu, 19 April 2012 14:31 Go to previous messageGo to next message
Michael Ihde is currently offline Michael IhdeFriend
Messages: 10
Registered: July 2009
Junior Member
Ralf/Mark,

Thanks for the help. I've included a full example below for others who run across this thread...however, I struggled to find a way to do exactly what I was trying to accomplish. My goal was to provide a synchronous API...something like this:

public class MyWidget implements IEntryPoint {
  public int createUI() {
    Display display = new Display();
    if (isThirdPartyReady()) {
      // Do one thing  
    } else {
      // Do another thing
    }
  }

  public boolean isThirdPartyReady(IProgressMonitor monitor) {
     // add life cycle listener

     // execute JS

     // while !monitor.isCanceled()
     //   check for response

     // return response
  }
}


This, of course, will produce a deadlock because isThirdPartyReady was called in the UIThread and the LifeCycleListeners are also called in the UIThread. I tried using a custom ServiceHandler and qx.io.request.Xhr() but I was unable to get that to work (should I continue to try down this path?). Fundamentally I'm attempting to execute client-side code and receive the response while blocking the UI thread...perhaps this is a naive goal.

In my particular case, I want to build my UI differently based off results of client-side execution. For example:

  public int createUI() {
    if (detectedSomethingAboutClientSide()) {
       // series of SWT widget creation
    } else {
        // alternate series of SWT widget creation
    }
  }


I can accomplish this through asynchronous callbacks (like below), it just makes the code a bit more obtuse. In my particular case, it would suffice if I could contribute client-side code into rwt-index.html initialization. I'm thinking something like IEarlyStartupJS. Javascript from this extension-point would be executed in rwt-index.html and be able to contribute parameters to the "rwt_initialize" message. The LifeCycleServiceHandler would store these in RWT.getSessionStore() or some other location. Is this a useful idea? If so, I will happily make the changes and provide a patch.

Anyways here is the complete final solution:

public interface IAsyncCallback<T> {
	public void onSuccess(T result);
	
	public void onFailure(Throwable t);
}
...
public static void isThirdPartyReady(final Display display, final IAsyncCallback<Boolean> callback) {
	RWT.getLifeCycle().addPhaseListener(new PhaseListener() {		
	@Override
	public PhaseId getPhaseId() {
		return PhaseId.READ_DATA;
	}
			
	@Override
	public void beforePhase(PhaseEvent event) {
	}
			
	@Override
	public void afterPhase(PhaseEvent event) {
		if (display != LifeCycleUtil.getSessionDisplay()) return;
			
		HttpServletRequest req = RWT.getRequest();
		String isThirdPartyReadyStr = req.getParameter("isThirdPartyReady");
		if ((req != null) && (isThirdPartyReadyStr!= null)) {
			final boolean isThirdPartyReady = Boolean.parseBoolean(isThirdPartyReadyStr);
			if (callback != null) {
				SafeRunner.run(new ISafeRunnable() {
					@Override
					public void run() throws Exception {
						callback.onSuccess(isThirdPartyReady);
					}
					@Override
					public void handleException(Throwable exception) {
					}
				});	
			}
			RWT.getSessionStore().setAttribute("isThirdPartyReady", isThirdPartyReady );
			RWT.getLifeCycle().removePhaseListener(this);
		}
	}
	});
		
		
	StringBuilder code = new StringBuilder();
	code.append("var req = org.eclipse.swt.Request.getInstance();\n");
	code.append("req.addParameter(\"isThirdPartyReady\", ThirdParty.util.isReady());\n");
	code.append("req.send();\n");
	JSExecutor.executeJS(code.toString());
}


Thanks again for all the help.

~Michael
Re: Simple non-UI object example [message #851866 is a reply to message #849880] Sat, 21 April 2012 11:55 Go to previous messageGo to next message
Ralf Sternberg is currently offline Ralf SternbergFriend
Messages: 1313
Registered: July 2009
Senior Member

Hi Michael,

Do you have to *wait* for your third-party library to become ready or do
you just *check* if it's available? In the latter case, it would be
ideal to pass this information to the server in the first request already.

For the mobile RAP clients, we've been thinking about a new Java API to
identify the client and access some client properties. Maybe such an API
could be extensible to provide for your case, too. If this sounds like a
solution, you could open an enhancement request and describe your use case.

As a workaround, you could also register your JavaScript code as a
resource to have it delivered to the client right on startup. The code
could attach a send listener to the request that adds your custom
parameter to every single Ajax request.

Regards, Ralf

--
Ralf Sternberg

Twitter: @EclipseRAP
Blog: http://eclipsesource.com/blogs/

Professional services for RAP and RCP?
http://eclipsesource.com/services/rap/
Re: Simple non-UI object example [message #853152 is a reply to message #851866] Sun, 22 April 2012 19:26 Go to previous message
Michael Ihde is currently offline Michael IhdeFriend
Messages: 10
Registered: July 2009
Junior Member
Ralf,

Coincidentally I had just figured out the workaround approach you suggested. Here are the details of what ended up working for me for other's who want to repeat it.

A) Contribute my JavaScript via org.eclipse.rap.ui.resources
B) Contribute a phase listener org.eclipse.rap.ui.phaselistener

In the Javascript code I do this

...
org.eclipse.swt.Request.getInstance().addEventListener( "send", this._onSWTRequestSend, this );
...
function _onSWTRequestSend( evt ) {
  var req = org.eclipse.swt.Request.getInstance();
  var is_rwt_initialize = req.getParameter( "rwt_initialize");
  if (is_rwt_initialize === "true") {
    req.addParameter("isThirdPartyReady", ThirdParty.util.isReady());
  }
}


My phase listener check for the parameter in the beforePhase() callback. This allows it to set the session store before createUI is called.

public void beforePhase(PhaseEvent event) {
  ...
  RWT.getSessionStore().setAttribute(...);
  ...
}


I'll have to think about the use-case for the mobile RAP client.

Thanks for the help and patience. RAP and the RAP developers are both awesome Smile

~Michael

[Updated on: Sun, 22 April 2012 20:04]

Report message to a moderator

Previous Topic:RAP application with XWT
Next Topic:A tutorial about Single Sourcing with RAP
Goto Forum:
  


Current Time: Sat Apr 20 00:55:36 GMT 2024

Powered by FUDForum. Page generated in 0.04079 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top