vert.x Serve static files - java

I have the following Verticle class:
public class SendFileExample extends AbstractVerticle {
public void start(Future<Void> fut) throws Exception {
Router router = Router.router(vertx);
router.route("/hello").handler(StaticHandler.create("client"));
router.route("/hello").handler(routingContext -> {
HttpServerResponse response = routingContext.response();
System.out.println("Hello");
response.sendFile("client/index.html");
});
vertx.createHttpServer().requestHandler(router::accept).listen(3000,
result -> {
if (result.succeeded()) {
fut.complete();
} else {
fut.fail(result.cause());
}
}
);
}
}
My html file is:
<html>
<head>
<title> hello </title>
</heade>
<body>
<h1> Hello World </h1>
<button> Hello </button>
<script src="app.js"></script>
</body>
</html>
I used "StaticHandler.create..." in order to serve all static files inside client folder.
As you can understand, I want that once the server gets a GET request to "localhost:3000/hello", the client will get an HTML page, which will call app.js file.
Unfortunately, I can't do it. index.html is loaded and the browser can't load app.js.
It's important to note that index.html and app.js both are located exactly in the same path which is ${PROJECT_ROOT}/client.
The code, however, is located in:
${PROJECT_ROOT}/src/main/java/com/company.

You simply missed the star sign when you defined your static handler:
router.route("/hello*").handler(StaticHandler.create("client"));

Why don't you try something straight-forward like:
if (req.path().equals("/")) {
res.sendFile("client/index.html");
}else{
res.sendFile( "client" + req.path() );
}

Related

Comunication between java/spring and c++/qt applications with websockets

I am trying implement websockets using spring with a java/web application to allow it to exchangte messages with a application written with c++ using qt (and the websockets library from it).
I have in my java/spring application this configuration:
WebScoketConfig.java
#Configuration
#EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(new SocketHandler(), "/name");
}
}
SocketHandler.java
#Component
public class SocketHandler extends TextWebSocketHandler {
List<WebSocketSession> sessions = new CopyOnWriteArrayList<>();
#Override
public void handleTextMessage(WebSocketSession session, TextMessage message) throws InterruptedException, IOException {
Map<String, String> value = new Gson().fromJson(message.getPayload(), Map.class);
session.sendMessage(new TextMessage("Hello " + value.get("name") + " !"));
}
#Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
sessions.add(session);
}
}
and I created a very simple qt-creator project, with a main function and one class MainWindow, with two objects: a lineEdit, where the user types a message to send to server, and a pushButton, to proceed with the data send.
In my MainWindow class, I implement this slot to handle the data exchange:
void MainWindow::on_pushButton_clicked()
{
QString message = this->ui->lineEdit->text();
QWebSocket m_webSocket;
m_webSocket.open(QUrl(QStringLiteral("ws://localhost:8080/name")));
m_webSocket.sendTextMessage("Hello " + message + " !");
m_webSocket.close();
}
But when I execute both applications, and try send a message for the java/web application, nothing happens. I pretty sure the mistake I made it's on the c++/qt side, since in the java/spring side I have a html/javascript code which allow me testing the message exchage, nd works fine.
Anyone can tell me what I am doing wrong here?
update: minimal reproducible example - java/spring
the project can be generated with start.spring.io, only with spring-websocket as dependency. besides the 2 files I already add above, the project will have:
resources/static/index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello WebSocket</title>
<link href="/main.css" rel="stylesheet">
</head>
<body>
<table>
<tr>
<td>
<button id="connect" type="button" onclick="connect();">Connect</button>
<button id="disconnect" type="button" disabled="disabled" onclick="disconnect();">Disconnect</button>
</td>
<td>
<label for="name">What is your name?</label>
<input type="text" id="name" placeholder="Your name here...">
<button id="send" type="button" onclick="send();">Send</button>
</td>
</tr>
</table>
<hr>
<table id="conversation" border="2">
<thead>
<tr>
<th>Greetings</th>
</tr>
</thead>
<tbody id="greetings">
</tbody>
</table>
<script src="/app.js"></script>
</body>
</html>
resources/app.js
var ws;
function connect() {
ws = new WebSocket('ws://localhost:8080/name');
ws.onmessage = function(text) {
var tr = document.createElement("tr");
var td = document.createElement("td");
td.innerText = text.data;
tr.appendChild(td);
document.querySelector("#greetings").appendChild(tr);
}
document.querySelector("#connect").setAttribute("disabled", "disabled");
document.querySelector("#disconnect").removeAttribute("disabled");
document.querySelector("#conversation").style.display = 'block';
document.querySelector("#greetings").innerHTML = "";
}
function disconnect() {
if (ws != null)
ws.close();
document.querySelector("#connect").removeAttribute("disabled");
document.querySelector("#disconnect").setAttribute("disabled", "disabled");
document.querySelector("#conversation").style.display = 'none';
document.querySelector("#greetings").innerHTML = "";
}
function send() {
var name = document.querySelector("#name");
var data = JSON.stringify({'name': name.value});
ws.send(data);
}
after build with mvn package, just run with java -jar target/app.jar.
update: minimal reproducible example - c++/qt
project is created with qt-creator, as type qt-widget. It will create a project with 5 files: websocket.pro, mainwindow.ui, mainwindow.h, mainwindow.cpp and main.cpp.
Open mainwindow.ui and add a lineEdit and pushButton from toolbar. right-click on the pushButton and choose Go to slot and select clicked(). Add the code above.
Update 2
void MainWindow::on_pushButton_clicked()
{
QString message = ui->lineEdit->text();
connect(&m_webSocket, &QWebSocket::connected, [this, message](){
QJsonObject object
{
{"name", message}
};
QJsonDocument d(object);
m_webSocket.sendTextMessage(d.toJson().toStdString().c_str());
m_webSocket.close();
});
m_webSocket.open(QUrl(QStringLiteral("ws://localhost:8080/name")));
}
The problem is that you are trying to send the text without verifying that the connection is successful. The solution is to use the connected signal, in addition to making m_webSocket a member of the class as advised in the comments:
*.h
private:
Ui::MainWindow *ui;
QWebSocket m_webSocket;
*.cpp
void MainWindow::on_pushButton_clicked()
{
QString message = ui->lineEdit->text();
connect(&m_webSocket, &QWebSocket::connected, [this, message](){
m_webSocket.sendTextMessage("Hello " + message + " !");
m_webSocket.close();
});
m_webSocket.open(QUrl(QStringLiteral("ws://localhost:8080/name")));
}
Update:
In your project I have noticed the following errors:
For some reason when I tested using Google Chrome I could not connect so I added registry.addHandler(new SocketHandler(), "/name").setAllowedOrigins("*"); to the configuration.
The variable "session" only handles sending data to a socket, if you want to send that information to all sockets (js and qt) then you must iterate.
When a session is disconnected do not remove it from "sessions" which can cause errors. You must remove session in the afterConnectionClosed method.
In your code you are calling to connect to the server in the slot associated with the connected signal which is silly since that slot is called after the connection and for this you should first call the open method. Anyway opening the connection, waiting for the connection to be established, sending the message and closing the connection is not a good idea, it is better to open the connection before sending the message and close it when necessary (for example when closing the GUI or the user wants to close it as it does in js since the sending of information is not instantaneous but is asynchronous).
The complete code is here.

Retrieve data into Java Application from an HTML file that was launched

So I have been searching for a way to get current location in java (not using any Android APIs) and something that is quite accurate. What I have so far is running an HTML file inside of Java and what I want to do is retrieve the GPS coordinates from a google API (html file).
What I have so far:
HtmlRun.java
import java.awt.Desktop;
import java.io.File;
import java.io.IOException;
public class HtmlRun {
public static void main(String[] args) throws IOException {
File htmlFile = new File("findLocation.html");
Desktop.getDesktop().browse(htmlFile.toURI());
}
}
findLocation.html
<!DOCTYPE html>
<html>
<head>
<title>Geolocation</title>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<meta charset="utf-8">
<style>
/* Always set the map height explicitly to define the size of the div
* element that contains the map. */
#map {
height: 100%;
}
/* Optional: Makes the sample page fill the window. */
html, body {
height: 100%;
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<div id="map"></div>
<script>
// Note: This example requires that you consent to location sharing when
// prompted by your browser. If you see the error "The Geolocation service
// failed.", it means you probably did not give permission for the browser to
// locate you.
function initMap() {
var map = new google.maps.Map(document.getElementById('map'), {
center: {lat: -34.397, lng: 150.644},
zoom: 6
});
var infoWindow = new google.maps.InfoWindow({map: map});
// Try HTML5 geolocation.
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function(position) {
var pos = {
lat: position.coords.latitude,
lng: position.coords.longitude
};
infoWindow.setPosition(pos);
infoWindow.setContent('Location found.');
map.setCenter(pos);
}, function() {
handleLocationError(true, infoWindow, map.getCenter());
});
} else {
// Browser doesn't support Geolocation
handleLocationError(false, infoWindow, map.getCenter());
}
}
function handleLocationError(browserHasGeolocation, infoWindow, pos) {
infoWindow.setPosition(pos);
infoWindow.setContent(browserHasGeolocation ?
'Error: The Geolocation service failed.' :
'Error: Your browser doesn\'t support geolocation.');
}
</script>
<script async defer
src="https://maps.googleapis.com/maps/api/js?key=AIzaSyBTQzs7iZUtr7v-VbvAWhAql5LiQ9zZrFE&callback=initMap">
</script>
</body>
</html>
When I run this, it opens up my default app for html files and everything is sorted... but how could I retrieve the information I need? (GPS coordinates)
It occurs over here:
var pos = {
lat: position.coords.latitude,
lng: position.coords.longitude
};
But I don't know how to retrieve that data back into my Java application.
This here:
public static void main(String[] args) throws IOException {
File htmlFile = new File("findLocation.html");
Desktop.getDesktop().browse(htmlFile.toURI());
}
is just opening the html doc in a web browser, after that you have no control AT ALL about what is happening with the web content, the user can even click all the buttons/ pois in the map and you will never get access to that information.
What you need is a webserver that SERVES the content of that app, you can implement REST/full services or even WebSockets to exchange the data between Browser and server

eclipse is showing error on render() in play2

i am new on Play Framework and i am trying to develop sample java application
i have created new html page test.html
in controllers it is working if we simply return result in the form of string i.e. return ok("hello world") but it simply format all the styling/text and just shows "hello world" on the UI.
public static Result test() {
return ok("hello world");
}
// working fine
but it gives errors when i try this
public static Result test(){
return ok(test.render());
}
// giving error
it gives following errors
[error] /opt/ahsen/play-2.2.3/testapp/app/controllers/Application.java:15: render(java.lang.String,play.api.templates.Html) in views.html.test cannot be applied to ()
[error] return ok(test.render());
[error] (compile:compile) javac returned nonzero exit code
here is my test.html file
#(title: String)(content: Html)
<!DOCTYPE html>
<html>
<head>
<title>#title</title>
<link rel="stylesheet" media="screen" href="#routes.Assets.at("stylesheets/main.css")">
<link rel="shortcut icon" type="image/png" href="#routes.Assets.at("images/favicon.png")">
<script src="#routes.Assets.at("javascripts/jquery-1.9.0.min.js")" type="text/javascript">
</script>
</head>
<body>
#content
</body>
</html>
help please
Your test.html template requires two parameters
#(title: String)(content: Html)
So you need to pass them to the template in your controller
public static Result test(){
String title = "test title";
Html content = // create content
return ok(test.render(title, content));
}
Better solution
Test.html looks rather as a more general layout template. I would create a separate file for generating content instead passing it directly from a controller.
content.html
#(title: String)
#test(title){
<span>this is the content</span>
}
And in the controller it would look like this.
public static Result test(){
String title = "test title";
return ok(content.render(title));
}

how to display tree structure dynamically using angularjs

i want to display tree structure dynamically.i am using angularjs and directives but getting json object only.
popupview.js:
app.directive('treeview', function(TreeService,$http) {
return {
scope: {
griddata:'=',
},
restrict: 'AE',
replace: true,
templateUrl: 'app/partials/treeviewgrid.html',
compile: function(cElem, cAttrs) {
return {
pre:function(scope, iElement, iAttrs) {
},
post:function(scope, iElement, iAttrs) {
scope.roleList = scope.griddata;
controller.js:
(function(){
app.controller('myController', function($scope,$http,TreeService){
$scope.roleList =
[{"roleName":"okm:root","roledId":"okm:root","children":[{"roleName":"my","roledId":"my","children":[{"roleName":"self","roledId":"self","children":[{"roleName":"htmlmenu.html","roledId":"htmlmenu.html","children":[]}]},{"roleName":"100.pdf","roledId":"100.pdf","children":[]},{"roleName":"act.txt","roledId":"act.txt","children":[]}]},{"roleName":"test","roledId":"test","children":[{"roleName":"Administration guide.pdf","roledId":"Administration guide.pdf","children":[]},{"roleName":"Quick Install.pdf","roledId":"Quick Install.pdf","children":[]},{"roleName":"test.docx","roledId":"test.docx","children":[]}]}]}];
});
})();
}
};
}
};
});
tree.html:
<!DOCTYPE html>
<html ng-app="myapp">
<body ng-controller="myController">
<treeview griddata="roleList"></treeview>
</body>
</html>
from the above code the out put is:
[{"roleName":"okm:root","roledId":"okm:root","children":[{"roleName":"my","roledId":"my","children":[{"roleName":"self","roledId":"self","children":[{"roleName":"htmlmenu.html","roledId":"htmlmenu.html","children":[]}]},{"roleName":"100.pdf","roledId":"100.pdf","children":[]},{"roleName":"act.txt","roledId":"act.txt","children":[]}]},{"roleName":"test","roledId":"test","children":[{"roleName":"Administration guide.pdf","roledId":"Administration guide.pdf","children":[]},{"roleName":"Quick Install.pdf","roledId":"Quick Install.pdf","children":[]},{"roleName":"test.docx","roledId":"test.docx","children":[]}]}]}];
but expected out put is:
okm:
root
my
self
htmlmenu.html
100.pdf
act.txt.
so please provide suggestion for how to do this.
Thanks.
I propose to use some of existing components like this
https://github.com/eu81273/angular.treeview
example:
var myApp = angular.module('myApp', ['angularTreeview']);
http://jsfiddle.net/eu81273/8LWUc/

Java based Adapter- Could not find the Return value

I am using a java based adapter in worklight. I have a method which returns a string value. I am able to call the function and the result is going to success handler in the adapter, but i am not able to find out anything about the return value. I cant see the returned String anywhere in the response JSON. Can anyone help me with this?
Here is my response JSON:
{"status":200,"invocationContext":null,"invocationResult":{"responseID":"16","isSuccessful":true}}
I have seen the following example
http://public.dhe.ibm.com/ibmdl/export/pub/software/mobile-solutions/worklight/docs/Module_05_5_-_Using_Java_in_Adapters.pdf, when i do an "invoke Adapter Procedure" on the code sample, I am getting this result.
{ "isSuccessful": true, "result": -9 }
where result is the return value of the java method in the adapter.
But when i do the same thing for my app, i get the following
{ "isSuccessful": true }
Java-adapter.impl code
function getXML() { return {result:
com.worklight.javaCode.FileIOPlugin.getXML() }; }
Java class method
public class FileIOPlugin{
public static String getXML() {
return "SUCCESS";
}
}
function getXML()
{
var invocationData ={
adapter: 'JavaAdapter',
procedure: 'getXML'
};
WL.Client.invokeProcedure(invocationData,{
onSuccess: successHandler,
onFailure: failureHandler
)};
function successHandler(data) {alert(JSON.stringify(data));}
function failureHandler(data) {alert("Error to get data");}
The return needs to be an object.
I've tried to reproduce your problem in the recently released Worklight 6.0, and I see everything working fine, after a copy&paste of your code.
The only change I did was to add the empty parameters on the invocationData object used to invoke the adapter method.
This is my exact code:
FileIOPlugin.java (under server/conf, in a package com.worklight.javacode)
package com.worklight.javacode;
public class FileIOPlugin {
public static String getXML() {
return "SUCCESS";
}
}
JavaAdapter.xml (HTTP adapter definition, under adapters folder)
<?xml version="1.0" encoding="UTF-8"?>
<wl:adapter name="JavaAdapter"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:wl="http://www.worklight.com/integration"
xmlns:http="http://www.worklight.com/integration/http">
<displayName>JavaAdapter</displayName>
<description>JavaAdapter</description>
<connectivity>
<connectionPolicy xsi:type="http:HTTPConnectionPolicyType">
<protocol>http</protocol>
<domain>rss.cnn.com</domain>
<port>80</port>
<!-- Following properties used by adapter's key manager for choosing specific certificate from key store
<sslCertificateAlias></sslCertificateAlias>
<sslCertificatePassword></sslCertificatePassword>
-->
</connectionPolicy>
<loadConstraints maxConcurrentConnectionsPerNode="2" />
</connectivity>
<procedure name="getXML"/>
</wl:adapter>
JavaAdapter-impl.js (next to JavaAdapter.xml)
function getXML() {
return {
result : com.worklight.javacode.FileIOPlugin.getXML()
};
}
I called my app javaAdapterApp, hence these file names:
javaAdapterApp.js (under apps/javaAdapterApp/common/js)
function wlCommonInit(){
}
function getXML() {
var invocationData = {
adapter : 'JavaAdapter',
procedure : 'getXML',
parameters : []
};
WL.Client.invokeProcedure(invocationData, {
onSuccess : successHandler,
onFailure : failureHandler
});
}
function successHandler(data) {
alert(JSON.stringify(data));
}
function failureHandler(data) {
alert("Error to get data");
}
And finally
javaAdapterApp.html (under apps/javaAdapterApp/common)
<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
<title>javaAdapterApp</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=0">
<link rel="shortcut icon" href="images/favicon.png">
<link rel="apple-touch-icon" href="images/apple-touch-icon.png">
<link rel="stylesheet" href="css/javaAdapterApp.css">
<script>window.$ = window.jQuery = WLJQ;</script>
</head>
<body id="content" style="display: none;">
<button onClick="getXML()">GET XML</button>
<script src="js/initOptions.js"></script>
<script src="js/javaAdapterApp.js"></script>
<script src="js/messages.js"></script>
</body>
</html>
I ran it in the test server, and the result of JSON.stringify(data) in the success handler looks like:
{"status":200,"invocationContext":null,"invocationResult":{"responseID":"9","result":"SUCCESS","isSuccessful":true}}
There is the "SUCCESS" String you are looking for in the invocationResult.result.
Hope this helps
Orlando

Categories