I've been having trouble finding information on how I might go about hosting a .jar file with a simple Java server. Basically, I'm writing a 2D game in Java and I would like to create a launcher that, given internet access is present, will check for the latest version on launch and download the newest version if necessary. Now, I'm aware I could use a file sharing site, simply up the latest build and have the launcher download from there; I just happen to find the redundancy of hosting the file on a Java server that I will myself be running all the more satisfying.
So basically, my question is: how would I create a Java server that simply hosts the latest build's .jar file and when an incoming connection requests it, the server sends that entire file to the client PC?
Also, please omit any concerns regarding the possible inefficiency of downloading the entire game .jar, as the game will be extremely small. The only threat of an over-sized download I can foresee is with music; however, I could create a separate request for music files and only grab what is needed. That goes the same for graphical assets if they become an issue as well, but 16x16 textures don't strike me as having potential for getting in the way.
If you are willing to obtain a code signing certificate, you could use WebStart
Check Java WebStart - this covers all your needs regarding checking and downloading.
Build a simple webapp that contains / hosts two things: Your .jnlp (Web Start descriptor file) and your game .jar
Sign your jar using a valid code signing certificate (this is required for webstart)
Deploy your webapp or jnlp/jar combination to whatever webserver you can get a hold of. As you're only uploading two files, there are a lot of "free" webhosting sites where you can upload some files.
If you really, really like to run the server for the downloads yourself, you should possibly check out Tomcat or Jetty or run Java SE HttpServer like this:
public static void main(String[] args) throws Exception {
HttpServer server = HttpServer.create(new InetSocketAddress(8000), 0);
server.createContext("/game.jnlp", new FileHandler("game.jnlp"));
server.createContext("/game.jar", new FileHandler("game.jar"));
server.setExecutor(null);
server.start();
}
static class FileHandler implements HttpHandler {
String file = "";
public FileHandler(String string) {
file = string;
}
#Override
public void handle(HttpExchange t) throws IOException {
byte[] data = IOUtils.toByteArray(getClass().getResourceAsStream(file));
t.sendResponseHeaders(200, data.length);
OutputStream os = t.getResponseBody();
os.write(data);
os.close();
}
}
If you believe Webstart is overkill, which I'd understand in your situation, you would need two jar files in the client: One to check and do the download of the other and then start the newly loaded file up. Sequence of steps would be:
Check if .jar is reachable by network.
If it is, load it and store it in defined path
Start a new java Process (-> ProcessBuilder) to run that java-program
Wait for game to finish (downloader will finish right after)
In that case your server would only need to host the game.jar
Related
Please, help.
I have a java program that currently reads a list of files from physical directory (shared) and while reading, creating output files - also on the shared location.
So, for several files read, there can be a a single output file.
New requirements came to take the files from that output location and ftp them to a given ftp server
The caveat is: The ftp procedure is done by microservice that most likely runs on the machines which do not have access to the output folder. So, I am making a call to a service, not using FTP API (Appache, or etc..) internally.
Is it possible to send a OutputStream (byteOutputStream, or ObjectOutputStream) over an http call? If so, how?
I know how to ftp the files from within my application, but the goal is .. to make a microservice call (webservice call, for what it matters, since my application is a plain old core java app).
I had a (rather different) project recently, however it also had the requirement to write to a http response.
I used this approach which works in my case:
try (OutputStream os = response.getOutputStream()) {
final PrintWriter w = new PrintWriter(new OutputStreamWriter(os, "UTF-8"));
Then after that, I write to the PrintWriter w.
Every time a ftp connection is established I want a java program to get triggered.
I am not sure how to check the FTP connections. Is there a way to monitor the port so that I can acknowledge when FTP gets the new connection?
I've researched a bit and found the FTPClient class which basically suggests I need to do my own ftpclient, but I want to know if there is another way.
Even an external program could be an option.
it would be running on the server side, basically the program will be reading the files that the client put on it.
Consider using a file watcher. It doesn't seem that you really care that the file gets there using FTP (in fact, in the future it might get there by some other means), but just that the file is present and needs to be processed.
See Watching a Directory for Changes for details on how to write one.
I have a program that does a similar task server-side with java. It checks if files exist in a folder and launches the rest of the code if so. Like this:
public static boolean needToConvert(){
//get list of companies
List<String> companies = getCompanyNames();
//check whether a file exists in folder of company
for(String company: companies){
if (new File(INPUT_LOCATION + company).list().length > 0){
return true;
}
}
return false;
}
This is a rather in-expensive task, so you could just set the server to "check"; say, every minute or so.
There are a variety of approaches:
Have the FTP service itself launch the java app (sounds expensive) or notify a running Java app / service. This will be the simplest approach ...
Use some kind of external monitoring; e.g.
A generic packet packet sniffing tool (like wireshark or tcpdump) might be able to trigger an external application. If not, you may be able to get it to log info to a file that you scan for connection events.
You could possible implement something using jpcap to do your own packet sniffing in Java
There is a Linux utility called tcpspy that logs TCP/IP connection details to syslog. You could configure it log to a specific file and monitor that file, alternatively, you could modify tcpspy to launch or notify a Java app directly.
(Please Read Update #3 to understand where exactly my problem is now)
I have written a custom SQL program that gets user commands from a GUI client and sends them to server(which contains the Database) to process all using Sockets.
Now I'm trying to write a web client for this database using apache tomcat(and JSP).I have put all the java files from the socket version to the src also I've learned how to use JSP files so now the user can login from a web page and the program will check the login information pretty much the way it did with the previous server/client but without socket while running tomcat.
At this point now I have made a page with a textarea and a submit button which will run the servlet code below upon clicking submit button:
#WebServlet("/change")
public class SQLCommandSender extends HttpServlet {
DataStorage ds = new DataStorage();
QueryParser parser = new QueryParser();
Query q;
QueryResult res;
String textAreaValue;
#Override
public void doPost(HttpServletRequest request, HttpServletResponse response) {
try {
textAreaValue = request.getParameter("inConsole");
q = parser.parse(textAreaValue);
res = ds.execute(q);
System.out.println(res.getMessage());
} catch (Exception e) {
e.printStackTrace();
}
}
}
And now this is what goes wrong; when I submit a create table command from the textarea the command processing reaches a point which a new txt file will be created for the new table:
File tablez = new File("/Users/Sam/Documents/IntelliJ Projects/Login Database/C/DB/Tables/" + table.getName() + ".txt");
From what I found from debugging, when I run the exact same create command from my server socket code. this line runs without any problems and table is created without any error, but when I run the command from tomcat; the line above throws the following exceptions from up to down:
java.io.IOException: No such file or directory
java.io.FileNotFoundException: null/cat1$was.txt (No such file or directory)
java.lang.NullPointerException
Why something like this would happen ?
I should emphasis that both programs are accessing the same line of code in the same file.and the chunk of code that receives the raw command String and returns the log is the lines in try section of doPost method above.and same lines of code is used in socket version to execute commands.
UPDATE: Here's the complete stack trace
UPDATE2: I have found this questions which looks somehow like my problem, but I still can't understand it properly It might help others to have some insight
UPDATE 3: from the latest info I have the problem probably stems from tomcat server's inability to access files the way a socket server/client can manipulate files. So now I'm trying to run socket server/client from previous phase of the program by Servlet .so if you can guide me on how to run a server/client with codes in a servlet(which was done manually before by right-click and clicking run button before). I will edit the question to match the new details after I've solved and seen your answers.
p.s. I'm using Intellij and tomcat is run with Intellij's plugin in form of a java EE web application.
Also I have checked and the directory is correct.As I said the exact line works with previous server/client.
Tomcat Server threw an exception Running the same line that Socket Server runs correctly because it doesn't have the same direct access to the files in the src folder as a Socket Server/Client does.
I solved this problem by making a socket client in servlet and a socket Server in the DB and sending the command by that client instead of writing servlet codes like the ones in the question that directly made the server run the database codes without any mediator like socket Server which made problems as tomcat has restricted access.
In Java console application, I am trying to copy a single file from shared network, to which I have access only when connected to our institute's internal network (an internal domain).
So this obviously doesn't work when I am connected to any other network e.g. when I am working at home. Some how it tries to connect to the network drive a bit longer, then other party of my applicaiton fails.
The problem is, how do I check if this application has a valid connection to that network drive first and then try to copy this file or else let the other processes work fine.
Since, I already have a local copy of this file attach to the application. The file has to be copied only to update the one attached with application to have the latest information.
However, the application works fine with this local file as well.
Ohh yes, I am looking for something that's platform independent, should work on windows, Linux and Mac.
Any directions or suggestions would be really great.
Have a look at the File class and its functions such as isDirectory() & exists(). For example,
import java.io.File;
public class Test {
public static void main(String[] args) {
File file = new File("\\\\server01\\\\folder");
System.out.println(file.isDirectory());
System.out.println(file.exists());
}
}
For a valid UNC path, this would print:
true
true
For in invalid, i.e. unaccessible, this would print:
false
false
NB: You need the 4 slashes to represent "\" as '\' is used for escape sequences.
I want to make an Applet write to a text file. I think have overcome the security problem with my own certificate, but the text file isn't receiving the output.
My Applet can be seen at tomrenn.com/fallball, and should ask if you trust the certificate.
I'm not sure an Applet can write to a text file within the web hosted contents, so I'm asking if this is possible; and if not, at least be able to do it on the local machine. I had been using a FileOutputStream, but my teacher recommended this very basic output method.
public void writeToFile()
{
try {
java.io.File file = new java.io.File("highscores.txt");
java.io.PrintWriter output = new java.io.PrintWriter(file);
output.print(name + " " +score);
output.close();
} catch (IOException e) {
System.err.println ("Unable to write to file");
System.exit(-1);
}
}
This is not what I would be implementing, just trying to see if I get any output. Thanks for looking over my question!
From an Applet, you cannot directly write to the server's file system. You can issue a request to the server that causes the server to write to its own file system, but an Applet does not have a way to write to a file system on a remote machine. (Of course, unless it's mounted NFS or otherwise.) To issue such a request, you could use Apache HttpClient to issue HTTP requests, for example. This may be more heavyweight than you are looking for. You can also have the client issue a POST to the server to say, "This is my high score," and let the server manage high scores.
A signed Applet has every right to write to the local file system of the person running the Applet. If you are writing to the "current directory" (rather than an absolute full path), then make sure you know what directory the Applet is running in. Otherwise you may indeed create a file, but not be able to find it!
If you want an applet to store data on the local machine, from 6u10 the javax.jnlp.PersistenceService is available. Creating a secure "signed applet" is difficult, and I wouldn't recommend it to anyone.
Applets run on the client so cannot access the servers disk.
The code you posted will write to the clients local disk. I'd suggest changing it though to specify the directory you want to place the file. The users home directory would seem a good place for it
java.io.File file = new java.io.File(System.getProperty("user.home"), "highscores.txt");
just sign your applet.
it is easy using netbeans.
open the project in netbeans.
right click on your project and select properties now you will have new window.
go to > application > webstart on that window.
check enable webstart.
press customize button at signing and choose "self signed by a generated key".
check "applet descriptor" and target your applet.
press ok.
rebuild the project (now netbeans will create certificates with all privileges )
use "launch.html" at your projects dist dir to run the applet via jnlp.
That's all.
** used netbeans version = 7.0
** used JDK = 1.6
** certificates will expire in 6 months.
Thanks