Very new to Wicket but have very basic Java. I am not understanding how "result" is not been used as I have used it in an AjaxButton function
The quickfix says to provide a getter and setter, which I did (have removed now) but still nothing happened when I click the OK button
CalcPage.java:
public class CalcPage extends WebPage{
private int num;
private int result; // error:The value of the field CalcPage.result is not used
private Label r;
public CalcPage() {
Form<Void> f = new Form<Void>("f");
add(f);
f.add(new TextField<Integer>("num", new PropertyModel<Integer>(this, "num")));
AjaxButton ok = new AjaxButton("ok") {
#Override
protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
result = 2 * num;
target.add(r);
}
#Override
protected void onError(AjaxRequestTarget target, Form<?> form) {
}
};
f.add(ok);
r = new Label("r", new PropertyModel<Integer>(this, "result"));
add(r);
}
}
CalcPage.html
<html xmlns:wicket="http://wicket.apache.org">
<head>
<meta charset="utf-8" />
<title>Apache Wicket Quickstart</title>
<link href='https://fonts.googleapis.com/css?family=Yanone+Kaffeesatz:regular,bold' rel='stylesheet' type='text/css' />
<link rel="stylesheet" href="style.css" type="text/css" media="screen" title="Stylesheet" />
</head>
<body>
<form wicket:id="f">
<input type="text" wicket:id="num"/>
<input type="submit" value="OK" wicket:id="ok"/>
</form>
Result: <span wicket:id="r"></span>
</body>
</html>
Hoping (according to book Enjoying web development with Wicket) to double the input but when I click on OK and nothing happens.
Also in code I am getting a compile error with #Override, once this is removed I can compile and load webpage. Are they related??
Wicket Ajax Debug window info:
INFO: focus removed from
INFO: focus set on
INFO: focus removed from
INFO: focus set on wicketDebugLink
INFO: focus removed from wicketDebugLink
INFO: focus set on ok2
INFO: Received ajax response (69 characters)
INFO:
INFO: Response processed successfully.
INFO: refocus last focused component not needed/allowed
ETA I changed from private to public and that error is gone but clicking ok still doesn't work and new error has come:
The method onSubmit(AjaxRequestTarget, Form) from the type new AjaxButton(){} is never used locally
You need to call r.setOutputMarkupId(true) if you want to update a Component via Ajax.
1) if javac (or your IDE) says that #Override does not override anything then most probably you have a typo somewhere and you need to fix it, i.e. to properly override the method from super
2) never leave #onError() empty. As a minimum add some basic logging in it to notify you that there is a validation error. Maybe #onSubmit() is not called at all. The best would be to have a FeedbackPanel in the page and you should update it in #onError() - target.add(feedbackPanel)
3) Check the browser's Dev tools Console for JavaScript errors. I'd expect Wicket complaining that it cannot find an HTML element with id rXY (where XY is a number) because of the missing r.setOutputMarkupId(true)
Version 8 of wicket doesn't have the "form" parameter so it can be deleted:
new code
AjaxButton ok = new AjaxButton("ok") {
#Override
protected void onSubmit(AjaxRequestTarget target) {
result= 2*num;
target.add(r);
}
Related
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.
Good day,
The following is my jsp code:
<s:form beanclass="c.c.i.c.app.profile.ui.ChangePasswordAction" method="post" name="form1">
<!-- some others code here -->
<sx:row cssClass="button_row">
<sx:input name="updatePassword" image="submit"/>
</sx:row>
</s:form>
And this is my jquery:
<script type="text/javascript">
$(':input[name=updatePassword]').click(function() {
var answerProceed = confirm("Do you wish to proceed with the changes?");
if( answerProceed ){
var form = $("form[name=form1]");
form.attr("action", '<s:url beanclass="c.c.i.c.app.profile.ui.ChangePasswordAction" event="update"/>');
form.submit();
} else {
return false;}
});
</script>
We can see that, in the jQuery, it will trigger a update event to ChangePasswordAction.
However, currently I have a issue, which is sometimes it will trigger 2 times, its not always happen, but the happen rate is about 50%.
The following is the trigger log I get from my application log:
2019-06-26 18:19:13.658 [WebContainer : 31] TRACE o.s.w.c.s.XmlWebApplicationContext - [bmaker] - Publishing event in Root WebApplicationContext: org.springframework.security.event.authorization.AuthorizedEvent[source=FilterInvocation: URL: /common/change_password.html?update=&__stoken=1a47d3a9-29e8-4904-b204-3cb9fc0129f0]
2019-06-26 18:19:13.660 [WebContainer : 26] TRACE o.s.w.c.s.XmlWebApplicationContext - [bmaker] - Publishing event in Root WebApplicationContext: org.springframework.security.event.authorization.AuthorizedEvent[source=FilterInvocation: URL: /common/change_password.html?update=&__stoken=1a47d3a9-29e8-4904-b204-3cb9fc0129f0]
Anyone know what wrong with the code?
If an <input/> is of type="submit" in a form you have to use preventDefault() if you want to check for confirmation before you submit the form.
You can pass e as parameter in your listener as an Event implementation parameter like MouseEvent (because of the click event) in this case.
For example :
$(':input[name=updatePassword]').click(function(e) { // <-- e implements Event
e.preventDefault(); // <-- prevent the submit of the form
var answerProceed = confirm("Do you wish to proceed with the changes?");
if (answerProceed) {
var form = $("form[name=form1]");
// var form = e.currentTarget.form; you can do this
// var form = this.form; or you can do this, "this" is implicit clicked element
form.attr("action", '<s:url beanclass="c.c.i.c.app.profile.ui.ChangePasswordAction" event="update"/>');
form.submit();
}
else {
return false;
}
});
You can access the form of an element by doing .form on an element, see
HTMLSelectElement.form
See
Event.preventDefault()
Event
MouseEvent
Does Eclipse Orion WebIDE support JSP? I am trying to create a simple application and jsp files are not working.
index.html
<html>
<head>
<script type="text/javascript" src="jquery-1.12.4.js"></script>
<script>
function getInput()
{
$.ajax({
type:"GET",
url: "./test.jsp",
success: function(success) {
console.log(success);
}
});
}
</script>
</head>
<body onload="getInput()">
test.jsp
<%#import="./javaMethod*"%>
<%javaMethod a = new javaMethod();
var value = a.initiate();
%>
<input type="hidden" id="test" value="<%=value%>">
javaMethod.java
public class javaMethod
{
public int initiate()
{
return 1;
}
}
This should add a hidden input field which will hold the value from the java method. However, it is not working and the jsp is just displaying as plain text.
This should add a hidden input field - no, this should log anything comes from test.jsp to the browser console. To add the output of the JSP to the body element, use $(document.body).append(success);.
I render a TextField. It's value is populated by script, not the user. I need to get that value from Java but I get null by doing textField.getInput();
Any ideas how to get that value and use it in Java code?
I had the same problem a few month ago. One problem is, that setting the input value via javascript doesn't fire the "onChange" event which you could easily use to get the value.
The solution I implemented might not be the easiest one, but it's working:
put a form with a hidden ajax submit link around your input
when you fill your input with javascript, use javascript also to do a form submit
html:
<html xmlns:wicket="http://wicket.apache.org">
<body>
<div>
<a href="#" onclick="document.getElementById('input').value = 'test'; document.getElementById('myForm').submit();">fill
input</a>
<form wicket:id="form" id="myForm">
<input type="text" wicket:id="input" id="input">
<a style="visibility: hidden;" wicket:id="submit">submit</a>
</form>
<p> Output:
<wicket:container wicket:id="output"></wicket:container>
</p>
</div>
</body>
</html>
and the corresponding java:
public class HomePage extends WebPage {
private String inputValue;
public HomePage(final PageParameters parameters) {
super(parameters);
final Label output = new Label("output", new PropertyModel<String>(
this, "inputValue"));
output.setOutputMarkupId(true);
add(output);
Form form = new Form("form");
form.add(new AjaxSubmitLink("submit") {
#Override
protected void onAfterSubmit(AjaxRequestTarget target, Form<?> form) {
super.onAfterSubmit(target, form);
target.add(output);
}
});
add(form);
form.add(new TextField<String>("input", new PropertyModel<String>(this,
"inputValue")));
}
}
Explanation:
The TextField gets an AjaxFormSubmitBehaviour with a custom event.
This event can be triggered by javascript. I use jQuery, as it is provided by Wicket anyway.
See the code:
public class Example extends WebPage
{
public Example(PageParameters pp)
{
super(pp);
final Model<String> m = new Model<String>("");
Form<Void> f = new Form<Void> ("form");
TextField<String> textField = new TextField<String>("textField", m, String.class);
textField.setOutputMarkupId( true );
textField.setMarkupId( "myuniqueid" );
textField.add( new AjaxFormSubmitBehavior("customevent")
{
protected void onSubmit(AjaxRequestTarget target)
{
System.out.println("Model value:"+m.getObject());
target.add( this.getComponent() );
}
} );
f.add(textField);
add(f);
}
}
HTML
<!DOCTYPE html>
<html xmlns:wicket="http://wicket.apache.org">
<head>
<meta charset="utf-8" />
</head>
<body>
<a href="#" onclick="$('#myuniqueid').val('test'); $('#myuniqueid').trigger('customevent');">fill
input</a>
<form wicket:id="form">
<input wicket:id="textField"></input>
</form>
</body>
</html>
I have a web page with an applet as the only element that looks something like this:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title>...</title>
</head>
<body>
<applet style="padding:1px; border:1px solid gray" mayscript="mayscript" codebase="..." name="AppletName" code="..." archive="..." width="600" height="500" alt="Alt Text">
<param name="initial_focus" value="true"/>
Alt Text
</applet>
</body>
</html>
When the page initially loads, focus is set in the applet and I can tab through and interact with the applet just fine. However, if I leave the browser window and then come back to it, I can no longer regain focus on the applet just using the tab key.
Pressing F5 to reload the page fixes the page so that the Applet regains focus, but this solution is unacceptable.
How do I solve this problem? Thanks.
Tentative solution:
//Dean Edwards/Matthias Miller/John Resig
function init() {
// quit if this function has already been called
if (arguments.callee.done) return;
// flag this function so we don't do the same thing twice
arguments.callee.done = true;
// kill the timer
if (_timer) clearInterval(_timer);
window.onfocus = function() {
if(!document.AppletName.isActive())
document.AppletName.requestFocus();
};
}
/* for Mozilla/Opera9 */
if (document.addEventListener) {
document.addEventListener("DOMContentLoaded", init, false);
}
/* for Internet Explorer */
/*#cc_on #*/
/*#if (#_win32)
document.write("<script id=__ie_onload defer src=javascript:void(0)><\/script>");
var script = document.getElementById("__ie_onload");
script.onreadystatechange = function() {
if (this.readyState == "complete") {
init(); // call the onload handler
}
};
/*#end #*/
/* for Safari */
if (/WebKit/i.test(navigator.userAgent)) { // sniff
var _timer = setInterval(function() {
if (/loaded|complete/.test(document.readyState)) {
init(); // call the onload handler
}
}, 10);
}
/* for other browsers */
window.onload = init;
Note that the key part for detecting whether the applet needs focus and requesting it if so is (this only works if mayscript is enabled):
if(!document.AppletName.isActive())
document.AppletName.requestFocus();
The rest of the code is just attaching the window on focus handling after the page is loaded (using the script JQuery.ready is based off of).
Better solutions welcome.