I'm using Restlet 2.3.2.
I'm building an Android Activity running a Servlet Server. I would like to package some files (the keystore and the static web files directory) with the resulting APK and make them accessible to Restlet.
Right now, I put those files in /storage/sdcard0. Here is the code that actually works with the files located at that place :
Server server = component.getServers().add(org.restlet.data.Protocol.HTTPS, port);
component.getClients().add(org.restlet.data.Protocol.FILE);
Series<Parameter> parameters = server.getContext().getParameters();
parameters.add("sslContextFactory", "org.restlet.engine.ssl.DefaultSslContextFactory");
parameters.add("keyStorePath", "/storage/sdcard0/ssl/keystore");
parameters.add("keyStorePassword", "password");
parameters.add("keyPassword", "password");
parameters.add("keyStoreType", "BKS");
parameters.add("keyManagerAlgorithm", KeyManagerFactory.getDefaultAlgorithm());
// Create an application
Application application = new Application() {
#Override
public Restlet createInboundRoot() {
return new Directory(getContext(), "/storage/sdcard0/www/");
}
};
component.getDefaultHost().attach("/static", application);
I'd like to package these files by putting them in res/rawor assets in my Android project, but I don't know how to make them accessible to my web server once moved.
you can change the Directory root url and use the clap protocol (that leverages the classloader):
component.getClients().add(org.restlet.data.Protocol.CLAP);
// Create an application
Application application = new Application() {
#Override
public Restlet createInboundRoot() {
return new Directory(getContext(), "clap://class/assets/");
}
};
I've not tested exactly your code, I hope it will work for you.
Related
I search for some help creating a web Flex application using BlazeDS and Java server with dynamic BlazeDS endpoint configuration.
First, I will try to explain my current situation.
I have a Flex 3.2 application that provides GUI of the application. From the ActionScript I call Java methods using BlazeDS. To access the BlazeDS I use a Config class that provides the endpoint as shown below (it is a constructor):
public function Config(): void {
if (_serviceUrl == null) {
try {
var browser: IBrowserManager = BrowserManager.getInstance();
browser.init();
var url: String = browser.url;
var host: String = mx.utils.URLUtil.getServerName(url);
var port: uint = mx.utils.URLUtil.getPort(url);
var parts: Array = url.split('/');
if (parts[2] == '') {
url = DEFAULT_URL;
Alert.show("Unable to determine server location, using default URL: " + DEFAULT_URL, "Connection error");
}
else {
url = parts[0] + '//' + parts[2] + '/' + parts[3] + '/messagebroker/amf';
}
_serviceUrl = url;
} catch (e: Error) {
Alert.show("Exception while trying to determine server location, using default URL: " + DEFAULT_URL, "Connection exception");
_serviceUrl = DEFAULT_URL;
}
}
}
The idea of the class is to determine the endpoint from the request URL. I use a Delegate class to call the remote methods using BlazeDS like the following:
{
import com.adobe.cairngorm.business.ServiceLocator;
import mx.rpc.IResponder;
import mx.rpc.remoting.RemoteObject;
public class AbstractRemoteDelegate
{
public function AbstractRemoteDelegate(responder:IResponder,serviceName:String)
{
_responder=responder;
_locator=ServiceLocator.getInstance();
_service=_locator.getRemoteObject(serviceName);
_service.showBusyCursor=true;
_service.endpoint = Config.instance.serviceUrl;
}
private var _responder:IResponder;
private var _locator:ServiceLocator;
private var _service:RemoteObject;
protected function send(operationName:String,... args:Array) : void {
_service.getOperation(operationName).send.apply(_service.getOperation(operationName),args).addResponder(_responder);
}
}
}
This approach actually works fine. However, I got across a situation where I can't use dynamically determined URL. In such a situation, I need a hard-coded URL in the Config.as file. And this is the problem. When trying to deploy the application to another server, I always need to rebuild the application with a new URL configuration in the ActionScript class Config.
Therefore I search for a way to define a static configuration for the Flex application to connect to a BlazeDS server. And the way to change such configuration without rebuilding the application so I can give the customer his own way to reconfigure and move the Flex application.
I thought about using a configuration file, but Flex runs on the client side and there is no configuration file!
I thought about using database configuration, but I don't have any database on the client side!
To sum up, I am looking for a way, how to get BlazeDS URL from a configuration to be able to change it without rebuilding the whole app.
Thanks for any useful suggestions.
EDIT: Revised the question to be more actual. I improved the way to determine the URL dynamically from the request URL, so it works now even for proxy server. However, my curiosity persists for the configuration of flex without rebuilding.
Here is an old example Blaze DS Service of mine which does basically the same as you did. It's just the string which needs to be created correctly. If the endpoint address is wrong, catch the error accordingly.
My project may currently not build because of Flexmojos ... I'm not able to test that yet.
Since it did not read you question properly, I misunderstood you: You can put a configuration file next to the SWF and load it via URLLoader or pass it via FlashVars. That should give you the freedom to pass the endpoint dynamically.
We're using RESTlet to do a small little REST server for a project we have. We set up a bunch of routes in a class inheriting from Application:
public static void createRestServer(ApplicationContext appCtx, String propertiesPath) throws Exception {
// Create a component
Component component = new Component();
component.getServers().add(Protocol.HTTP, 8081);
component.getClients().add(Protocol.FILE);
component.getClients().add(Protocol.CLAP);
Context context = component.getContext().createChildContext();
RestServer application = new RestServer(context);
application.getContext().getParameters().add("useForwardedForHeader", "true");
application.getContext().getAttributes().put("appCtx", appCtx);
application.getContext().getAttributes().put("file", propertiesPath);
// Attach the application to the component and start it
component.getDefaultHost().attach(application);
component.start();
}
private RestServer(Context context) {
super(context);
}
public synchronized Restlet createInboundRoot() {
Router router = new Router(getContext());
// we then have a bunch of these
router.attach("/accounts/{accountId}", AccountFetcher.class); //LIST Account level
// blah blah blah
// finally some stuff for static files:
//
Directory directory = new Directory(getContext(),
LocalReference.createClapReference(LocalReference.CLAP_CLASS, "/"));
directory.setIndexName("index.html");
router.attach("/", directory);
return router;
}
The problem: If I request a .js file in the JAR via Ajax from a web page (also loaded via CLAP from this JAR), it'll only return the first 7737 bytes of that file and then hang. I can't get it to return the rest of the file. It always hangs after exactly the same number of bytes. 1 in 50 times it works.
Any ideas why it's hanging? Can I just turn off chunked encoding for CLAP and static files (all ours are quite small).
This is driving us nuts.
I don't know which server connector you use for your application but it seems that it's the default one.
Restlet is pluggable and extensible at different levels. I recommend you to use the Jetty one. To do that simply add the JAR file for the Jetty extension (org.restlet.ext.jetty.jar) within your classpath. The connector will be automatically registered and use instead of the default one.
I also recommend you to upgrade to the latest version (2.3).
To see which connectors are registered in the Restlet engine, you can use the following code:
List<ConnectorHelper<Server>> serverConnectors
= Engine.getInstance().getRegisteredServers();
for (ConnectorHelper<Server> connectorHelper : serverConnectors) {
System.out.println("Server connector: "+connectorHelper);
}
You shouldn't have such problems after doing this.
Hope it helps you,
Thierry
This might be a very trivial question, but I'm having trouble finding an answer:
Using the Google Plugin for Eclipse, I would like to develop a plain old Java application (not a web-app), that uses AppEngine for cloud storage.
For this, I could, of course, simply create two projects, one containing the AppEngine server and one containing the Java application.
But I'm wondering whether it is possible to set up a single project in Eclipse that contains both the server and the client code (like for a GWT project). To execute it for local debugging, I would then want Eclipse to launch Tomcat to make my servlets available and then launch my Main.java from the client directory of the project as if the project was just a simple Java application. Is this what the "Launch and deploy from this directory" checkbox is for in the "Google" -> "Web Application" settings? If so, how do I use it?
I found one way to do it, but it's a bit cheesy.
First, add the following helper-class to the project:
// other imports
import com.google.appengine.tools.development.DevAppServerMain;
public class DevServer {
public static void launch(final String[] args) {
Logger logger = Logger.getLogger("");
logger.info("Launching AppEngine server...");
Thread server = new Thread() {
#Override
public void run() {
try {
DevAppServerMain.main(args); // run DevAppServer
} catch (Exception e) { e.printStackTrace(); }
}
};
server.setDaemon(true); // shut down server when rest of app completes
server.start(); // run server in separate thread
URLConnection cxn;
try {
cxn = new URL("http://localhost:8888").openConnection();
} catch (IOException e) { return; } // should never happen
boolean running = false;
while (!running) { // maybe add timeout in case server fails to load
try {
cxn.connect(); // try to connect to server
running = true;
// Maybe limit rate with a Thread.sleep(...) here
} catch (Exception e) {}
}
logger.info("Server running.");
}
}
Then, add the following line to the entry class:
public static void main(String[] args) {
DevServer.launch(args); // launch AppEngine Dev Server (blocks until ready)
// Do everything else
}
Finally, create the appropriate Run Configuration:
Simply click "Run As" -> "Web Application". To create a default Run Configuration.
In the created Run Configuration, under the "Main"-tab select your own entry class as the "Main class" instead of the default "com.google.appengine.tools.development.DevAppServerMain".
Now, if you launch this Run Configuration, it will first bring up the AppEngine server and then continue with the rest of the main(...) method in the entry class. Since the server thread is marked as a daemon thread, once the other code in main(...) completes, the application quits normally, shutting down the server as well.
Not sure if this is the most elegant solution, but it works. If someone else has a way to achieve this without the DevServer helper-class, please do post it!
Also, there might be a more elegant way to check whether the AppEngine server is running, other than pinging it with a URL connection as I did above.
Note: The AppEngine Dev Server registers its own URLStreamHandlerFactory to automatically map Http(s)URLConnections onto AppEngine's URL-fetch infrastructure. This means that you get errors complaining about missing url-fetch capabilities if you then use HttpURLConnections in your client code. Luckily, this can be fixed in two way as described here: Getting a reference to Java's default http(s) URLStreamHandler.
If you definitely want to use appengine, then you will end up creating two projects, one on appengine and another a standalone (no servlets). In this case you can take a look at appengine Remote API
I am using eclipse with the Google Toolkit and I have created a widget with a listbox, vertical split panel and a couple of buttons. What I am trying to do is have a list of files in a local directory listed in the listbox and I want to be able to click on a file and have it displayed in the top part of the split panel. I found out the hard way about browsers and file IO and not being able to use java.io.File.
What are my options? Can I put the data files inside a jar or something and have the widget read it in that way? I need to do this as a test run, to implement an new feature with working with the data. It's not going to be any kind of final server hosted application, I am not concerned about how the actual files will be loaded in the future.
Any suggestions would be greatly appreciated.
Respectfully,
DemiSheep
If you just need a hard-coded list of values to visually test your widget, you can simply put these values in a String array and load it from there. Or you can http GET the strings from a server using RequestBuilder. You can keep a simple file (CSV, XML, JSON etc.) in your war directory and load this file using Request builder.
Example code from GWT developer guide:
import com.google.gwt.http.client.*;
...
String url = "http://www.myserver.com/getData?type=3";
RequestBuilder builder = new RequestBuilder(RequestBuilder.GET, URL.encode(url));
try {
Request request = builder.sendRequest(null, new RequestCallback() {
public void onError(Request request, Throwable exception) {
// Couldn't connect to server (could be timeout, SOP violation, etc.)
}
public void onResponseReceived(Request request, Response response) {
if (200 == response.getStatusCode()) {
// Process the response in response.getText()
} else {
// Handle the error. Can get the status text from response.getStatusText()
}
}
});
} catch (RequestException e) {
// Couldn't connect to server
}
Make sure you inherit HTTP module:
<inherits name="com.google.gwt.http.HTTP" />
Create testcases with JUnit!
This is the official Google site describing Testing with JUnit and varios test methods: Google Web Toolkit: Testing. You definitly find a solution here^^
As it comes to GWT, there is no such thing sent to a browser as a .jar-file.
The easiest thing to fetch the file would be to
put the files on a server
fetch them via a http-call
Remember the same-origin-policy that applies to GWT as it is underlying all javascript-Restrictions
We have an MTOM-enabled web service that is published with Grails and the Metro 1.0.2 plugin:
#MTOM
#WebService(targetNamespace="http://com.domain")
class TestService {
#WebMethod
int uploadFile(#XmlMimeType("application/octet-stream")DataHandler data) {
data.dataSource.inputStream.eachLine {
println "reading: -> ${it}"
}
return 0
}
}
Following this tutorial, we set up a Java test-client that looks like this
public class Client {
public static void main(String[] argv) {
MTOMFeature feat = new MTOMFeature();
TestService service = new TestServiceService().getTestServicePort(feat);
Map<String, Object> ctxt = ((BindingProvider)service).getRequestContext();
ctxt.put(JAXWSProperties.HTTP_CLIENT_STREAMING_CHUNK_SIZE, 8192);
service.uploadFile(new DataHandler(new FileDataSource("c:/file.xml")));
}
}
When I run the client, I get the following error message:
Couldn't create SOAP message due to
exception:
org.jvnet.mimepull.MIMEParsingException:
Missing start boundary
However, when I don't add the MTOMFeature, and just do
TestService service = new TestServiceService().getTestServicePort(); the files gets uploaded ok. But as I understand it if MTOM is not enabled on both server and client side, the entire file will be kept in memory (and not streamed). So, my questions are
Why do we get that error?
If I don't add the MTOMFeature, will the file still be MTOM-transmitted?
I would be very grateful for any help/tips!
After some research and testing, the answers are:
The error is because grails adds its own filtering, including services. So, by excluding the services from being filtered like this static excludes = ["/services/*"] in UrlMappings.groovy, it works.
No. Without the MTOMFeature the file will just be treated as any other data in the request. That means being stored in the memory, thus causing problems for big files.