Save Java Applet Variable to Mysql - java

Hi
I've done a lot of research on the best way to communicate between a java applet and MySql Database.
I have a tune player which I have students logging onto, it's a java applet with a speed slider. I want to save the speed that they play each tune at so it goes back to the same speed the next time they open that tune.
It seems I have a number of options, none of which seem very neat.
Use a javascript function to
periodically check the speed and
save it to a cookie, then each page
of the site would have to check
cookies relationg to each tune.
Make each link on the page call a
javascript function to check the
speed variable in the applet and add
it to a perameter in the url then
redirect so the next php page can
save the speed to a database. This
way when the user navigates away the
speed will be saved, but this won;t
work if the back button is used.
Is there a better way of doing this?

Use the JNLP API and the problems should be solved.
Since Java 1.6.0_10+, it is possible to use the Java Web Start API services (JNLP API) within an embedded applet. The JNLP API provides the PersistenceService. Here is a small demo. of the PersistenceService.
If the user hits the back button (or otherwise leaves the page), the destroy() method will be called. Override the destroy method and persist the data at that time.

No need to use JavaScript.
The java code below posts variables to a PHP script on the web server then
shows the server response on the console
private void post()
throws MalformedURLException, IOException
{ URL url;
URLConnection con;
OutputStream oStream;
String parametersAsString;
byte[] parameterAsBytes;
String aLine; // only if reading response
parametersAsString = "msg=hi&to=memo";
parameterAsBytes = parametersAsString.getBytes();
// send parameters to server
url = this.getCodeBase();
url = new URL(url + "scriptfile.php");
con = url.openConnection();
con.setDoOutput(true);
// setDoInput(true); // only if reading response
con.setDoInput(false);
con.setRequestProperty("Content=length", String.valueOf(parameterAsBytes.length));
oStream = con.getOutputStream();
oStream.write(parameterAsBytes);
oStream.flush();
// read response from server & show the server response on the Java console or whatever ...
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
aLine = in.readLine();
while (aLine != null)
{ System.out.println(line);
aLine = in.readLine();
}
in.close();
oStream.close();
}

I'd suggest you get the applet to update the database. Whenever the speed slider changes you can fire off an update to the database, or you might need to coalesce multiple changes into one request depending on usage.
When the applet changes tune it can also do its own lookup of the correct speed.
Note that the applet will probably not be able to hit the database directly - browsers should restrict what I/O operations are available to applets - but you should be able to get the applet to hit a URL on the server that will actually perform the update. Signing the applet may let you hit the database but you should read up on the applet security model and the various browser quirks first.

It's not really clear how all of this is set up since you don't have a lot of details. However, assuming that you have an actual Java applet, I'd say the following:
If the Java applet requires a login (that is, it knows who the user is) then it can store the preference on the server. To do this you could have the applet connect to the server using JDBC, which isn't generally a good idea for internet-facing applets, or you could have the applet send a message to a server process such as a web server. That process connects to the mysql server.
The applet can communicate directly with the browser using Javascript. So you can have the applet set the cookie when the slider changes, instead of having the Javascript set it.

Related

How to continuously read an online/web file in java?

I am making a simple text-only instant messenger in java. The way that it currently works is that all the messages are put into an online text file by sending a php file a request (I know this is bad for security, but this is just to learn how to do web-connected apps in java.)
Currently, I am continually fetching the entire contents of the messages.txt file and placing them into my JTextPane like this:
while(true) {
URL url = new URL("{path to text file}");
InputStream in = url.openStream();
Scanner s = new Scanner(in).useDelimiter("\\A");
String conversation = s.hasNext() ? s.next() : "";
textPane.setText(conversation);
}
But when the conversation becomes long enough, it lags as it is fetching 100kb+ files constantly from a web server.
What I want to happen is to only read the changes to the file so that it doesn't lag and max out my internet connection by requesting enourmous amounts of plain text files. I don't want to just make it run every 2 seconds because it's an instant messenger, no delays.
How would I go around only fetching the changes to the file and adding them to the text pane?
Can you push the file contents to another file once it crosses a certain threshold. This will ensure that you operate upon a smaller file.
Instead of contacting url directly you could place some server side script that would call the file
You could (as a client) provide the server script the last line / message identifier and the server could respond with new messages that have been added after the message id that the client has provided. In addition it could send the new last message id
With this approach the server side script doesnt even need to read itself the whole file and instead can immediately skip to the required line if message id contains the information about the line in the log file
Of course this approach is really far from real scenarios but its ok for learning IMO

Is it possible to write text into a web page after it has loaded?

Let me get straight to an example to explain further.
final var socket = new java.net.ServerSocket(1234);
for (;;)
{
try (final var client = socket.accept())
{
client.getOutputStream().write("HTTP/1.1 200 OK\r\n\r\n".concat(java.time.Instant.now().toString()).getBytes());
}
}
When I now open my browser of choice (Firefox cough) I'll receive the current time and date. The question now is how I can write to that socket at a later point in time.
hypothetical solution
Here's something I already tried, but doesn't work at all.
final var socket = new java.net.ServerSocket(1234);
for (;;)
{
try (final var client = socket.accept())
{
client.getOutputStream().write("HTTP/1.1 200 OK\r\n\r\n".concat(java.time.Instant.now().toString()).getBytes());
client.getOutputStream().flush();
Thread.sleep(1000L);
client.getOutputStream().write("And another paragraph.".getBytes());
}
}
The result is a web page loading for approximately a single second, printing out the following result (may vary due to different date and time on your end).
2019-01-19T18:19:15.607192500Z
And another paragraph.
Instead I would like the see something like that:
print out the current time and date.
wait a second without the content of the web page changing.
print out the next paragraph.
How would I go about implementing that?
Is it possible for the server to write text into a web page after it is loaded? Yes it definitely is, but these days I suspect it it is rarely done. I started web development in the 1990s and back then that was a pretty common technique. We used it to write live chat messages to browsers with no Javascript. These days Javascript is ubiquitous and powerful, so using client-side Javascript to update a page will be the best option in most cases.
That said, the technologies we used for writing server-side updates back then should still work now. I suspect the reason you don't see updates in your browser is because it doesn't know it should start displaying the page before everything is loaded. Using chunked transfer encoding, a 1990s technology still supported by modern browsers, should resolve that. It it allows the server to indicate when a 'chunk' of data is complete and browsers will generally process each chunk immediately rather than wait for all the chunks to arrive.
The easiest way to use chunked transfer encoding is to use an HTTP library like Apache HttpComponents, then wrap your output stream in the appropriate class:
final var socket = new java.net.ServerSocket(1234);
for (;;)
{
try (final var client = socket.accept())
{
var outputStream = new ChunkedOutputStream(client.getOutputStream());
outputStream.write("HTTP/1.1 200 OK\r\n\r\n".concat(java.time.Instant.now().toString()).getBytes());
outputStream.flush();
Thread.sleep(1000L);
outputStream.write("And another paragraph.".getBytes());
}
}

How to Ensure Input from URL isn't from a Redirected Page

I have the following lines of code that gathers the source code from a given URL:
URL url = new URL(websiteAddress);
URLConnection connection = url.openConnection(); // throws an IOException
connection.setConnectTimeout(timeoutInMilliseconds);
bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String line;
while ((line = bufferedReader.readLine()) != null) {
outputString += line;
}
However, the problem that I'm having is that wi-fi hotspots often redirect you to a page where you have to click "I Agree." If you run this code before you have clicked that checkbox, then it gathers the source code from the hotspot login page, rather than the intended page.
What I want to do is have some way of checking whether or not the intended page was reached. I was hoping that calling connection.getURL() after creating the InputStreamReader would show me the actual web page that was arrived, but no such luck. How can I determine whether or not the intended URL has been redirected?
One way would be to look for any specific element in your web page, and if its not there then you know that you may be in some other page (possibly redirected to some login page).
The only thing I can suggest is to have a server where you know what the response is, and query that first to ensure connectivity to at least that server. That will (typically) be enough to assume full connectivity.
You can then go on to query the url you're interested in.
The challenege is that if a computer asks for the page at some url, the way a lot of wifi hotspots work is to intercept that request and return the page. There's often no clue, form the computer's POV that the page returned is not the page requested.
One option would be to call setFollowRedirects(false). By default, a connection will quietly follow redirects and try to reach a page which returns a 200 HTTP response. Disabling redirect following will make confirming the expected page is returned easier, simply confirm the response is a 200.
That said, #rec's comment is worth taking into account - it isn't enough to simply check the response code, because there are many different ways a router could interrupt your request, many of which are not detectable. A malicious router could, for instance, intercept all your requests and change the responding content in a subtle but dangerous way - this is called a man-in-the-middle attack.
By definition you cannot avoid MitM attacks unless you can open a secure and trusted connection (generally, HTTPS) between yourself and the remote site, however assuming you aren't really concerned about attacks, the better tactic is simply to assume the data you get back could be broken in any number of ways, and instead make your scraping logic more robust to that possibility.
I can't speak directly to how you would make your logic more robust without understanding your use case and the issues you've run into, however the gist would be to add checks where issues might arise, and throw an exception that you then handle gracefully higher up the stack.
For instance, if your code was:
System.out.println(outputString.subString(outputString.indexOf('A'));
This would fail if outputString didn't actually have an'A'` character. So check that explicitly:
int aPos = outputString.indexOf('A');
if (aPos < 0) {
throw new InvalidParseException("Didn't find an 'A', cannot proceed");
}
System.out.println(outputString.subString(aPos);
And handle the InvalidParseException wherever makes the most sense for your use case.

Why is this URL not opened from Play! Framework 1.2.4?

I have a URL in my Play! app that routes to either HTML or XLSX depending on the extension that is passed in the URL, with a routes line like :-
# Calls
GET /calls.{format} Call.index
so calls.html renders the page, calls.xlsx downloads an Excel file (using Play Excel module). All works fine from the browser, a cURL request, etc.
I now want to be able to create an email and have the Excel attached to it, but I cannot pull the attachment. Here's the basic version of what I tried first :-
public static void sendReport(List<Object[]> invoicelines, String emailaddress) throws MalformedURLException, URISyntaxException
{
setFrom("Telco Analysis <test#test.com>");
addRecipient(emailaddress);
setSubject("Telco Analysis report");
EmailAttachment emailAttachment = new EmailAttachment();
URL url = new URL("http://localhost:9001/calls.xlsx");
emailAttachment.setURL(url);
emailAttachment.setName(url.getFile());
emailAttachment.setDescription("Test file");
addAttachment(emailAttachment);
send(invoicelines);
}
but it just doesn't pull the URL content, it just sits there without any error messages, with Chrome's page spinner going and ties up the web server (to the point that requests from another browser/machine don't appear to get serviced). If I send the email without the attachment, all is fine, so it's just the pulling of the file that appears to be the problem.
So far I've tried the above method, I've tried Play's WS webservice library, I've tried manually-crafted HttpRequests, etc. If I specify another URL (such as http://www.google.com) it works just fine.
Anyone able to assist?
I am making an assumption that you are running in Dev mode.
In Dev mode, you will likely have a single request execution pool, but in your controller that send an email, you are sending off a second request, which will block until your previous request has completed (which it won't because it is waiting for the second request to respond)...so....deadlock!
The resaon why external requests work fine, is because you are not causing the deadlock on your Play request pool.
Simple answer to your problem is to increase the value of the play.pool in the application.conf. Make sure that it is uncommented, and choose a value greater than 1!
# Execution pool
# ~~~~~
# Default to 1 thread in DEV mode or (nb processors + 1) threads in PROD mode.
# Try to keep a low as possible. 1 thread will serialize all requests (very useful for debugging purpose)
play.pool=3

"Forwarding" an image upload with Java

I have a Web Service that receives an image upload by a Multipart POST request. I would like to forward the file to another web service without storing it, as the environment does not have access to a file system, so basically just passing along the information that's being received.
How do I achieve this?
If the other webservice resides on the same server use:
String url = "<relative path>";
request.getRequestDispatcher(url).forward(request, response);
return;
otherwise use:
response.sendRedirect(url);
You could always try chaining the input and output streams from one to the other, but I suspect you won't get very far with this when there's a hiccup on either side of the connection.
Another option you have, depending on how much memory you have access to, is to save it as a variable after you fetch it, and then pass it along to the other webservice. This of course won't work with very large images but it's a starting point.

Categories