Dynamic BlazeDS endpoint configuration - java

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.

Related

Applications Credentials not avaliable in Google Cloud Vision API

I am trying to setup Google Cloud Vision API, I have defined a Application Credential Variable through CMD by using set GOOGLE_APPLICATION_CREDENTIALS PathToJSON however this still does not allow me to connect to Google Cloud Vision API for OCR.
I have also tried to set it manually through the windows UI, however still no luck, I created and defined a project in the Google Cloud page, and generated a credential key, when it asked me "Are you planning to use this API with App Engine or Compute Engine?", I selected No.
I am currently using Googles boilerplate code
public class DetectText {
public static void main(String args[])
{
try{
detectText();
}catch (IOException e)
{
e.printStackTrace();
}
}
public static void detectText() throws IOException {
// TODO(developer): Replace these variables before running the sample.
String filePath = "C:\\Users\\Programming\\Desktop\\TextDetection\\Capture.PNG";
detectText(filePath);
}
// Detects text in the specified image.
public static void detectText(String filePath) throws IOException {
List<AnnotateImageRequest> requests = new ArrayList<>();
ByteString imgBytes = ByteString.readFrom(new FileInputStream(filePath));
Image img = Image.newBuilder().setContent(imgBytes).build();
Feature feat = Feature.newBuilder().setType(Feature.Type.TEXT_DETECTION).build();
AnnotateImageRequest request =
AnnotateImageRequest.newBuilder().addFeatures(feat).setImage(img).build();
requests.add(request);
// Initialize client that will be used to send requests. This client only needs to be created
// once, and can be reused for multiple requests. After completing all of your requests, call
// the "close" method on the client to safely clean up any remaining background resources.
try (ImageAnnotatorClient client = ImageAnnotatorClient.create()) {
BatchAnnotateImagesResponse response = client.batchAnnotateImages(requests);
List<AnnotateImageResponse> responses = response.getResponsesList();
for (AnnotateImageResponse res : responses) {
if (res.hasError()) {
System.out.format("Error: %s%n", res.getError().getMessage());
return;
}
// For full list of available annotations, see http://g.co/cloud/vision/docs
for (EntityAnnotation annotation : res.getTextAnnotationsList()) {
System.out.format("Text: %s%n", annotation.getDescription());
System.out.format("Position : %s%n", annotation.getBoundingPoly());
}
}
}
}
static void authExplicit(String jsonPath) throws IOException {
}
}
I am not using a server or Google compute virtual machine.
Can someone please explain to me what the problem is, and how I would go about fixing it?
Stack Trace
java.io.IOException: The Application Default Credentials are not available. They are available if running in Google Compute Engine. Otherwise, the environment variable GOOGLE_APPLICATION_CREDENTIALS must be defined pointing to a file defining the credentials. See https://developers.google.com/accounts/docs/application-default-credentials for more information.
at com.google.auth.oauth2.DefaultCredentialsProvider.getDefaultCredentials(DefaultCredentialsProvider.java:134)
at com.google.auth.oauth2.GoogleCredentials.getApplicationDefault(GoogleCredentials.java:119)
at com.google.auth.oauth2.GoogleCredentials.getApplicationDefault(GoogleCredentials.java:91)
at com.google.api.gax.core.GoogleCredentialsProvider.getCredentials(GoogleCredentialsProvider.java:67)
at com.google.api.gax.rpc.ClientContext.create(ClientContext.java:142)
at com.google.cloud.vision.v1.stub.GrpcImageAnnotatorStub.create(GrpcImageAnnotatorStub.java:117)
at com.google.cloud.vision.v1.stub.ImageAnnotatorStubSettings.createStub(ImageAnnotatorStubSettings.java:156)
at com.google.cloud.vision.v1.ImageAnnotatorClient.<init>(ImageAnnotatorClient.java:136)
at com.google.cloud.vision.v1.ImageAnnotatorClient.create(ImageAnnotatorClient.java:117)
at com.google.cloud.vision.v1.ImageAnnotatorClient.create(ImageAnnotatorClient.java:108)
at DetectText.detectText(DetectText.java:54)
at DetectText.detectText(DetectText.java:36)
at DetectText.main(DetectText.java:25)
Based on your error message, it seems that the GOOGLE_APPLICATION_CREDENTIALS environment variable is not being found.
On one hand, before trying to run the text detection sample code, follow the steps outlined in the documentation in order to discard that any of them has been skipped.
On the other hand, if you are using an IDE such as IntelliJ or Eclipse, you have to set the environment variable GOOGLE_APPLICATION_CREDENTIALS global through Windows System Properties, so it can be used by the IDE. Nevertheless, when testing I had to close and reopen the IDE for the changes to take effect and the aforementioned error would not appear.
Additionally, there is also a way to specify the location of the JSON file within the code, as shown in this example. However, it is not advisable to put it that way, it is best to use the environment variables.

How to implement a catch all route with java spark for an SPA

The app I'm trying to get working uses Vue.js and Java Spark. I am trying to get the SPA to work with HTML5 history mode. Right now it serves the index page and the app takes over routing from there. Because of html5 routing, if I try to go straight to a url such as "/about", i'll get an error. I tried to add a catch all route using:
get("/*", (rq, rs) -> new ModelAndView(map, "index.hbs"), new HandlebarsTemplateEngine());
But this overrides the previously defined static file routing in:
staticFileLocation("/public");
How can I implement a catch all route for all other pages without overriding the static file routes? I'd rather not have to redefine every route on the server to the same page. I've accomplished this in node.js with express, It has to be possible with Spark.
Spark.get("*", (request, response) ->
{
response.type("application/json");
return "not supported";
});
Should do the trick.

Restlet, CLAP, Ajax, and chunk timeouts

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

VB.NET Consuming web service written for glassfish: SoapHeaderException

Wrote a 'webservice' with Netbeans wizard, runs on glassfish. I added a reference using the wsdl to my .NET client, VB if it makes any difference.
I clearly have no idea what is going on, as I am encountering some brick walls.
The issue is a SoapHeaderException.
System.Web.Services.Protocols.SoapHeaderException: com/mysql/jdbc/Connection
at System.Web.Services.Protocols.SoapHttpClientProtocol.ReadResponse(
SoapClientMessage message, WebResponse response, Stream responseStream,
Boolean asyncCall)
at System.Web.Services.Protocols.SoapHttpClientProtocol.Invoke(
String methodName, Object[] parameters)
at WSClient.WSClient.localhost.DatabaseGateService.createCustomerTable(String xml)
in C:\Project\WSClient\Web References\localhost\Reference.vb:line 40
at WSClient.USAHWSClientConsumer.TestCustomer() in
C:\Project\WSClient\Client\WSConsumer.vb:line 22
The web service itself is simple:
#WebService()
public class DatabaseGate {
private MySQLManagerImp manager;
public DatabaseGate(){
manager = new MySQLManagerImp();
}
#WebMethod(operationName = "createCustomerTable")
public void createCustomerTable(#WebParam(name = "xml") String xml) {
manager.createCustomersTable(xml);
}
}
It takes an xml string, as I did not want to pass in an abomination of arguments.
I attempt to consume the service by simply instantiating the web reference:
Dim ws As localhost.DatabaseWS = New localhost.DatabaseWS
// Create the xml string
Dim qbCustomerQueryRS As String = qbQuery.GetCustomerQueryXML()
Dim processedCustomerXML As String =
customerResponseParser.GetAllCustomerDatabaseFriendlyXML(qbCustomerQueryRS)
ws.createCustomerTable(processedCustomerXML)
I've tried writing the string in a soap envelope, but still receive the same message. So passing a string is kaputt, as it should be; why would the WS know to parse a string, and simply instantiating and calling the method from the object as if it were local isn't working the way I think it does.
What is happening?
Sounds like the WSDL references com/mysql/jdbc/Connection, which is not a class known on the .NET side. If you have control over the Web Service, add annotations to avoid serialization of external class references (like com/mysql/jdbc/Connection). If you don't, simply download the WSDL to a text file, edit it manually to remove such classes/attributes, and re-create the reference pointing to the edited file. You can change the endpoints in Web.config later.
As it turns out, the reason I was receiving
System.Web.Services.Protocols.SoapHeaderException: com/mysql/jdbc/Connection
was similar to Diego's answer (thank you for pointing me in the right direction): A reference problem.
I assumed my WS deployment worked correctly because I had tested the method that executed, but only assuming the data I needed successfully transmitted over the wire.
Testing another angle using glassfish revealed:
Service invocation threw an exception with message : null; Refer to the server log for more details
Checking the server log, the answer was obvious:
java.lang.NoClassDefFoundError: com/mysql/jdbc/Connection
I had forgotten to add the jar to com/mysql/jdbc/Connection.

How do I load test data into my GWT Widget?

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

Categories