My current project is writing a HTTP-Webserver in Java. The server checks a "deployment-directory" every two seconds and searches for a file named content.jar. If the file was changed the server deployes it. The file contains servlets which will be loaded by an URLClassLoader. On every deployment a new classloader is created.
In a different project my servlets are being developed. I wrote an Ant-buildfile that creates the content.jar file and moves it into the server's deployment directory. Unfortunately I get an Ant error:
BUILD FAILED [path]\WebServerServlet\Ant\Build.xml:15: Unable to
remove existing file [path]\WebServer\web\content.jar
I suppose that the file is locked on the filesystem by the JVM - is there a way to tell Ant it should not try to delete and move the file but to overwrite it instead?
Otherwise, does anyone have an idea how to avoid the file getting locked by the JVM by changing my deployment system?
EDIT
I have now found a solution!
As discussed in this question the only thing i had to add was
URLClassLoader loader = new URLClassLoader(..);
//class loading stuff here
loader.close() //the line all the trouble was about
With this appendix my Ant-buildfile is able to delete the "old" jar in the deployment-directory and move the new one into it.
I suspect that the classloader has a lock on the jar. Either way until the lock is released you're not going to be able to move, delete or modify it.
The solution is to write your own classloader. It's this custom classloader that should be monitoring your jar for changes, not the server, then reloading the classes accordingly.
There's a lot involved in writing a classloader to do dynamic reloading - fortunately, it's explained here.
Related
I have a few questions regarding the org.eclipse.wst.server.core folder in .metadata\.plugins folder in a eclipse work space. I know that while running an application in local host, this is the folder where we have to replace files for front end, like JSP, JS files, CSS files, HTML files, Images etc.
There will be some tmp folders into which I have to replace the files into respective locations. This folder will be having another folder with structure of a WAR file which I'll take from my work space and sometimes there will be multiple tmp folders like tmp0, tmp1, tmp2 etc (most of them having all required files). When there are multiple folders it is really confusing to decide that into which folder I need to replace the file(s).
Then I'll have to stop the server, kill all the java running in background (manually) and have to clear all the tmp folders (because if the java is not killed properly the jar files inside tmp's cannot be deleted saying its currently being used). I guess one among these tmp folders are used by the server to run the application.
After cleaning all the tmp folders if I start the server again, the first file created in that folder (org.eclipse.wst.server.core) will be one servers.xml, then one tmp0 will be created may be tmp1. When entire project is published only one tmp folder will be there, if I publish multiple times, another tmp folder will be created, may be 2nd time, 3rd time or nth time.
So my questions are
Is there a general name for org.eclipse.wst.server.core folder?
Why multiple tmp folders are created when publised multiple times? Can we restrict it into a single tmp folder?
After the project is published, is there a possibility that server will use multiple tmp folders for different request. Like for first request I uses tmp0 and when I refresh the page it uses tmp1 folder?
Edited regarding the 3rd question
I opened all the xml files in the folder given in the above image, and in tmp-data.xml, I found this content
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<temp-directories>
<temp-directory age="0" key="GlassFish v2.1 Java EE 5 at localhost" path="tmp0"/>
</temp-directories>
Where path attribute is given value as tmp0. So I'm guessing that will be the answer to my third question. I'm guessing this file will be created when there are multiple tmp folders, because after deleting all tmp folders and files in the folder and after publishing the work space the tmp-data.xml file was not present.
Edited regarding the WTP
I don't have much details about WTP, but when I clicked Help and selected About Eclipse in my eclipse I got this window
Not that I know of. It is created by WTP (Web Tools Platform) using WST (Web Standard Tools). If you find, let me know too.
That depends upon different checks that WTP and WST do before publishing the artifacts. It does not happen all the time, but it does a lot more than expected, because of file locks that stop eclipse from publishing a fresh copy of the application. And hence, the code must be trying to create new tmp folder just as a workaround. The metadata (publish.xml) is then updated, and everything works as normal, which I feel is much better since the developer does not have to know a lot of stuff about these failures. We can change this setting in the server properties in your eclipse. Note that different plugins have different ways of doing this, my STS has default deploy path set to wtpwebapps.
This must be available in your publish xml file. And it also depends upon the version of WTP / WST you are using. It is hard to see where the folder generation is happening (at least for me at this time), but you can look at PublishUtils.java and PublishDelegate.java in WTP. Github here.
No certainly not, after a project is published the whole server points to the location at which the artifacts reside. Though the context refresh might fail because of overlapping threads or wait time, it is not possible for two different instances to be deployed into the same server with the same application/context name.
Read this and this
Edit: Clarity - the main .pl file loads, it's all the subfiles that it has been told to load which don't load. (all the consult('subfile.pl').)
I have a Java project that uses tuProlog. It calls a theory as:
Theory theory = new Theory(":-consult('main.pl').");
engine.setTheory(theory);
This is as per the manual.
file.pl exists in the same folder as other prolog files.
Inside of main.pl, I have further
consult('otherfile.pl').
statements to load additional files (several).
The folder structure is:
src/main.pl
src/Prolog_Files/otherfile.pl (multiple)
src/main/java/JavaStuff
I can't get the engine to load the theories that I've told it to consult inside of the main file.pl
I have tried: giving it absolute path instead of just filename.
moving files around.
I'm wondering if there is something about usage of tuProlog I'm not understanding?
The theory works when loaded with:
Theory theory = new Theory(new FileInputStream(url_of_file)).
However, this is causing me issues when building the jar, as it can't find the file location.
Am I attempting to load the file correctly? Are my consults inside of the main .pl file correct?
Could someone please post an example of how this should be done if not? The manual doesn't elaborate very much on this topic.
Thanks
The manual is slightly outdated in parts - it says to use consult/1, whereas elsewhere it states that consult/1 is deprecated, whereas include/1 is the replacement.
Secondly, when using 2p.jar, it reads Prolog files from the Project root as its root. When creating a jar, 2p.jar cannot be inside of the project jar. They should be in relative folders, and 2p.jar reads Prolog files with the location of 2p.jar as root. It doesn't seem that it can read inside of project jar.
Hopefully that's clear enough!
I have a relatively basic java program which uses a system tray icon. The path I was using while writing the code is as follows "../images/logo.png". However, when I compile it into a jar file, the image does not show up in the system tray. Instead, if I change the path to "./images/logo.png", then the image shows up in the system tray when it's in the jar file form, but not while I'm testing.
It's not a major issue. However, I am curious to know why this inconsistency occurs.
When you package your program into a .jar file, your build is most likely copying the image into the same directory as the .jar file. However, when debugging in your ide, your image file lies one directory below.
Another possibility is that you are simply setting your Working Directly differently in the two scenarios.
Incidentally, you might be interested in embedding the image in your jar file, see:
https://stackoverflow.com/a/1096491/24954
This answer depends on two things. If the image file is embedded or not.
Embedded Resource
Once you have Jar'ed your application and the images are emebbed inside the application, normal file access methods will no longer work.
Trying to do something like...
new ImageIcon("../images/logo.png");
or
new File("../images/logo.png");
Won't work. This is because the resource is no longer a file within the context of the file system (it's actually a Zip entry in the Jar).
Instead, you need to use Class#getResource which will return a URL to the embedded resource.
new ImageIcon(getClass().getResource("../images/logo.png"));
Will work better. In general though, it is recommended to use an absolute path to the resources new ImageIcon(getClass().getResource("/images/logo.png")); as it's generally more difficult to break (IMHO)
External Resource
The path to the image is relative to the execution point of the application.
In development, you may have had to move up a directory (out of the src folder presumably) to find the image resource. This will mean that you will need to store you Jar file in a folder that would require it step up one level before it could find the image resource.
If you can, it's generally better to embedded the resource within the Jar where possible. It makes it easier to deploy as you reduce the number of files you need to package and makes it (a little) harder for the user to mess with it ;)
I have created a dynamic web project, and use Apache Tomcat as a server.
In my servlet I'm creating a text file and want to reuse that in a JSP. However they are by default created in the installation folder of Eclipse when I do something as simple as the following:
File f = new file("test.txt").
I don't know why this happens. Is there a way to create the file in the WebContent directory as I want to make that file available for download in my JSP.
Java has a concept of the "current directory". When you start an application via Eclipse, this may indeed point to your installation directory. If you don't specify any path, a file will be created in this current directory. Hence the reason why your test.txt ends up there.
The WebContent directory is a something that is specific to Eclipse. Your code should not depend on putting anything there. You only start your application via Eclipse when you're developing it, not when you're deploying it to a live server.
The content of this directory will become the root of your .war, which is a well known location independent of how you start & deploy you app, BUT you still cannot depend on writing anything to this location at run-time. You might deploy your application as a packaged .war (likely for live deployments) or you may deploy your application unpackaged but then your application server may simply not pick up any changes done at run-time.
What you can do if you are sure your application only runs on a single server is writing the files to a well known location on your file system, such as /tmp, or /var/yourapp/files, etc. The code serving up those files can then pick them up from that location.
If you want to play it 100% safe according to the Java EE rules, you'd store your files on something like an FTP server that has a configurable address. Technically your war could be shipped between nodes on a cluster and requests could end up going to different machines, so depending on a local filesystem wouldn't work then.
Executing this statement this.getServletContext().getRealPath (""), you'll obtain the path where Tomcat WebServer is pointing at at runtime. You could add a folder "MyFolder" and call this statement:
new File(this.getServletContext().getRealPath ("") + "/MyFolder/test.txt");
Anyway, the default path looks something like:
...\workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\<NameOfYourProject>
Note that when you create a new file, it won't appear in your immediate workspace (check the .metadata path), unless you change the runtime location tomcat should point at.
I'm trying to read signals from a PLC trough Java, and for that I think I should use a "bridge" called JEasyOPC. The problem is that I don't how to install it, and make it work.
I followed a tutorial but I get always stuck at the same problem. I get an error:
Property file javafish.clients.opc.JCustomOpc doesn't exist. System terminated.
If you are using JEasyOpc inside a web application (e.g. inside a .war file), then you may need to do the following
Replace this line in PropertyLoader.java with
ClassLoader cl = ClassLoader.getSystemClassLoader();
with
ClassLoader cl = PropertyLoader.class.getClassLoader();
Also, make sure you specify -Djava.library.path=[path to folder containing dll]
The property file is in a directory called resources. If you have the jeasyopc.jar in a directory, /jeasy, then the resources directory should be in a directory such as /jeasy/resources. You need to put this on your classpath. This can be done in your environment or at run time with something like java -Djava.ext.dirs=.:/jeasy/resources .