Fairly new to Wicket so excuse my ignorance.
I have a Wicket app...starts with WicketApplication.class I have a WicketApplication.properties file to load some values. The properties file sits next to the class file (same package). Works fine, no issues.
Now, I would like to move the properties file outside the application WAR/JAR. Exported the app as a WAR to run on Tomcat. I have create a a folder called properties under tomcat root & moved WicketApplication.properties to this directory. Added the following to init() method in WicketApplication.class...
String realPath = getServletContext().getRealPath("/");
realPath = realPath.replaceAll("\\\\", "/");
if (realPath.toUpperCase().indexOf("WEBAPPS") != -1) {
String newRes = realPath.substring(0, realPath.toUpperCase().indexOf("WEBAPPS") -1);
System.out.println (newRes + "/properties");
getResourceSettings().getResourceFinders().add(new Path( newRes + "/properties"));
}
I get an exception thrown.
How do I "externalise" the properties file?
Also, if I could take one step further, how do I map a properties file name to class name..it, myapplication.properties -> WicketApplication.class
Thanks in advance.
You need to add new IStringResourceLoader with application.getResourceSettings().getStringResourceLoaders().add(...).
See https://github.com/apache/wicket/blob/515e2be2a5301f5caf7b1baee4a593d21c20e275/wicket-core/src/main/java/org/apache/wicket/settings/ResourceSettings.java#L220-L224 for the default ones.
IResourceFinder should be used when you want to add custom location for your HTML files.
There is no way to map myapplication.properties to WicketApplication.class. By adding an additional IStringResourceLoader you just tell Wicket to search in yet another place.
Related
I have a javafx project, which contains multiple paths for images and text files :
private Image imgMan = new Image(getClass().getResource("../man.gif").toExternalForm());
FileHelper.resetScores("./bin/application/MAP/BestScores.txt");
...
When i launch from eclipse, it work normally, and access to images and files without any problem.
But when i try to export my project to a jar file, it export correctly, but it don't launch !
I try to launch it from cmd, the trace of stack said that he don't know the paths...
Caused by: java.lang.NullPointerException
at application.Client.(Client.java:31)
(line 31 in my code refer to the first line of code given in the question)
I try to create a resource folder and put all files into it, but no result.
So what is the best way to make it ?
where must i create the resource folder ?
and how to access the files into it from the code ?
Thank you
There are several thing you should check:
verify the path in your jar against the class you are looking. Your image must be there.
verify you have successfully loaded a resource because using it, eg: check if getResource returns null.
For the first point, it depends on how you build your jar:
Eclipse will by default copy class file and resources to bin unless you use m2e. If you use the Extract runnable JAR (from File > Export menu), it may ignore some resources.
If you use Maven then your images must be in src/main/resources by default.
For the second point, you should use a method that should check the resource exists before delegating to Image. While it won't change your core problem, you would have a less subtile error:
static javafx.scene.image.Image loadImage(Class<?> source, String path) {
final InputStream is = source.getResourceAsStream(path);
if (null == is) {
throw new IllegalStateException("Could not load image from " + source + " path: " + path);
}
try (is) { // Java 9 -> you may want to use InputStream is2 = is
return new javafx.scene.image.Image(is); // use is2 for Java < 9
}
}
You should also try with an absolute path (from the root of the jar, or your src/main/resources if you use maven):
Image image = loadImage(this.getClass(), "/images/man.gif");
I'm building a Vaadin(basically Java that compiles to html/javascript) project and am trying to import a template(basically a HTML file). For all intents and purposes thought, I'm just importing a file as an input stream. Here is the offending code:
File file = new File("C:/JavaProjects/VaadinSpikeWorkspace/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/CISTVaadinClient/VAADIN/themes/layoutsinteractionDetailsTabLayout.html");
InputStream is = null;
CustomLayout custom = null;
try {
is = new FileInputStream(file);
} catch (FileNotFoundException e1) {
System.out.println("mark 1");
e.printStackTrace();
}
try {
custom = new CustomLayout(is);
} catch (IOException e) {
System.out.println("mark 2");
e.printStackTrace();
}
What I'm doing:
Deploying the Vaadin project (basically a dynamic web project with a few extra .jars) to tomcat and accessing thVe aadin Project using my browser
What I'm seeing:
A blank screen in my browser
File not found exception (i.e "mark 1")
And as a result: IOException (i.e. "Mark 2")
What I've checked:
The file definitely does deploy to tomcat with the rest of the project
Outside of the webapps folder, the file i'm trying to import is available via the browser once deployed (i.e. Localhost/myProject/MyFile.html)
The Tomcat install is fine (It was a fresh install and works with this/other projects outside of this problem)
What I've tried
Using a relative URL, or just the name of the file (i.e. New File( "../webapps/vaadin/layouts/MyFile.html") )
Using the absolute Path to the Project directory
Using the absolute path to the deploy directory (as above)
Putting the file somewhere else (read: Every single possible location in the project)
Again, I'm trying to simply read the file, MyFile.html as an input stream. What am I doing wrong/ overlooking?
Thanks for your time.
I had no problems reading files when using VaadinService which points to WebContent directory (with META-INF, VAADIN and WEB-INF inside). If it's run in the test environment then VaadinService is not available, so I use such piece of code:
private static final String BASEDIR;
static {
if (VaadinService.getCurrent() != null) {
BASEDIR = VaadinService.getCurrent().getBaseDirectory().getAbsolutePath();
} else {
BASEDIR = "WebContent";
}
}
then to navigate to VAADIN folder just use
BASEDIR+="/VAADIN/restOfYourPath"
Just in order to make it more portable: have you thought about bringing your templates into your classpath? Something like
yourApp/WEB-INF/classes/templates/layoutsinteractionDetailsTabLayout.html
This way, you only need this line of code, assuming you are into a Servlet or Spring Controller or Struts 1/2 action or whatever called YourClass:
InputStream is = YourClass.class.getClassLoader().getResourceAsStream("templates/layoutsinteractionDetailsTabLayout.html");
If you are really trying to use this file as an HTML template, you'll be much better off to leverage Vaadin's support for this. They have a CustomLayout which loads an HTML template from your theme.
Your template would go into a folder like the following:
VAADIN/themes/mytheme/layout/layoutsinteractionDetailsTabLayout.html
Note that mytheme is the name of your theme and layout is a specially recognized Vaadin directory within themes.
Your custom component would then look like:
public class InteractionDetailsTabLayout extends CustomLayout {
private static final String TEMPLATE = "layoutsinteractionDetailsTabLayout";
public InteractionDetailsTabLayout() {
super(TEMPLATE);
}
}
Note that the super constructor argument excludes the directory and file suffix.
If you actually want to load a file in your webapp, don't bother with it in your VAADIN directory but instead put it in your classpath resources and access it with the ClassLoader.
I've got one problem. I'm working on a web Application using Struts (Struts 2 Framework).
I created a Freemarker template file for every single user and save it in
webapps/mail/mailEn/customer.ftl
Now, when the page is called, I must look if a customer.ftl So I try looking after it in my java class like this:
( when i use local direcory path C://... it works)
MimeBodyPart textBodyPart = null;
try {
textBodyPart = new MimeBodyPart();
Configuration cfg = new Configuration();
//FileTemplateLoader ftl1 = new FileTemplateLoader(new File ("D:/Workspace//Projectname///web///styles/");
FileTemplateLoader ftl1 = new FileTemplateLoader (new File("\\mail\\mailEn")); TemplateLoader[] loaders = new TemplateLoader[] { ftl1 };
MultiTemplateLoader mtl = new MultiTemplateLoader(loaders);
cfg.setTemplateLoader(mtl);
cfg.setObjectWrapper(new DefaultObjectWrapper());
Template template = cfg.getTemplate("customerInfo.ftl");
Map<String, String> rootMap = new HashMap<String, String>();
rootMap.put("image1", "images/LOGO.jpg");
rootMap.put("recipient", "aaaa");
rootMap.put("address", "xxxx");
rootMap.put("contact", "yyyy");
rootMap.put("country", "uuuu");
rootMap.put("sender", "rrrrr");
Writer out = new StringWriter();
template.process(rootMap, out);
textBodyPart.setContent(out.toString(),Constants.TEXT_HTML);
}
With the absolute path (D:/....) it works without problems. But this can't be the
solution, because when Ive finished this web-app, I will have an war-file which will be put on a server and the absolute path will be wrong then. So I need a relative path which will always work!
I'm working with Eclipse at this moment. When I try to use the path above (/../.. ....),
the file I'm looking for can never be found. (I tried to go up to the home path of the
project and then to the folder mail, where the file is)
I tried out many different paths like ./web/mail/ , ../../../../../web/styles, and so on,
but I never found the file I was looking for.
If anyone could give me a hint what to do, I would be very grateful!
Thank you!
You should use WebappTemplateLoader (or maybe ClassTemplateLoader). FileTemplateLoader is not a good fit for this, as in theory you can't even know if the war file will be extracted on the server, and if it's not extracted, you surely won't have a directory to point to.
actully your file are getting stored in the temp folder (application server/os) so i suggest to you `
request.getRequestedURI() + "/" + FILE_PATH`
Say: you saved "file.txt" at "URL:PORT/file/file.txt" which refers to the tmp folder in fact and it gets deleted once the server is restarted or application undeployed. make sure the folder you are using to save is outside web-inf
Solution(adjustment)
I used request.getSession().getServletContext().getRealPath()
In a class for example MessageUtility i used
final private static String MAIL = ResourceBundle.getBundle("cfg_webapp").getString("mails.folder");
String mailpath = request.getSession().getServletContext().getRealPath(MAIL);
FileTemplateLoader ftl1 = new FileTemplateLoader(new File(mailpath));
In cfg_webapp.properties i defined
## Mails
mails.folder=mails
It gets the path from ----- src/main/webapps/mails/customer.ftl
thanks all.
I have read all the other questions related to this in StackOverflow and I did not find any clear response.
To cut it short, I have an application that will store some files in a directory that I will use than to process them. I have intentions of moving my app in different places (other computers) so I need to have a relative path to work with so that I will not change that in each time.
Does anyone know how to get the relative path of the application (not the full path) so that I could use in this case? If what I am asking is not wright please tell me another way to achieve what I need. Thank you
Just use "./".
No matter what directory your application has been launched from, "./" will always return that directory.
For example:
new File("./") will return a file object pointed at the directory your java application has been launched from
new File("./myDirectory") will return a file object pointed at the myDirectory folder located in the directory your java application has been launched from
Here is one approach:
I believe you need to define the path of directory containing the files in a configuration/property file. You can change the path in the configuration file when you move your application or the directory containing the file. This is how your properties file(let's say config.properties) contents should be:
filesDirPath=\usr\home\test
And this what you should do in the code:
private void readConfig()
{
Properties prop = new Properties();
try {
//load a properties file
prop.load(new FileInputStream("config.properties"));
//get the directory path property value
String flesDirPath = prop.getProperty("filesDirPath");
System.out.println("Files to be read are located in dir : " + flesDirPath );
} catch (IOException ex) {
ex.printStackTrace();
}
}
I have a webapp which contains a manifest file, in which I write the current version of my application during an ant build task. The manifest file is created correctly, but when I try to read it in during runtime, I get some strange side-effects. My code for reading in the manifest is something like this:
InputStream manifestStream = Thread.currentThread()
.getContextClassLoader()
.getResourceAsStream("META-INFFFF/MANIFEST.MF");
try {
Manifest manifest = new Manifest(manifestStream);
Attributes attributes = manifest.getMainAttributes();
String impVersion = attributes.getValue("Implementation-Version");
mVersionString = impVersion;
}
catch(IOException ex) {
logger.warn("Error while reading version: " + ex.getMessage());
}
When I attach eclipse to tomcat, I see that the above code works, but it seems to get a different manifest file than the one I expected, which I can tell because the ant version and build timestamp are both different. Then, I put "META-INFFFF" in there, and the above code still works! This means that I'm reading some other manifest, not mine. I also tried
this.getClass().getClassLoader().getResourceAsStream(...)
But the result was the same. What's the proper way to read the manifest file from inside of a webapp running in tomcat?
Edit: Thanks for the suggestions so far. Also, I should note that I am running tomcat standalone; I launch it from the command line, and then attach to the running instance in Eclipse's debugger. That shouldn't make a difference, should it?
Maybe your side-effects come from the fact that almost all jars include a MANIFEST.MF and you're not getting the right one. To read the MANIFEST.MF from the webapp, I would say:
ServletContext application = getServletConfig().getServletContext();
InputStream inputStream = application.getResourceAsStream("/META-INF/MANIFEST.MF");
Manifest manifest = new Manifest(inputStream);
Please note that running Tomcat from Eclipse is not the same as running Tomcat alone as Eclipse plays with the classloader.
a bit late, but this works for me (web appl in Glassfish)
Properties prop = new Properties();
prop.load(getServletContext().getResourceAsStream("/META-INF/MANIFEST.MF"));
System.out.println("All attributes:" + prop.stringPropertyNames());
System.out.println(prop.getProperty("{whatever attribute you want}"));
Try to use jcabi-manifests, that does all this loading work for you. For example:
String version = Manifests.read("My-Version");
loads My-Version attribute from one of available MANIFEST.MF files.
Important to mention that (more details are here) in most web containers current thread class loader is not the same as servlet context class loader. That's why you should append your servlet context to the register in runtime (more info):
Manifests.append(servletContext);
Also, check this out: http://www.yegor256.com/2014/07/03/how-to-read-manifest-mf.html
The default way class loaders work is to defer to the parent before attempting to lookup their own resources. So if a parent class loader has any manifest available, that's what you'll get. In fact, app servers don't necessarily do this, to allow applications to override versions of libraries. Further, class loaders can have multiple jars and hence multiple manifests.
It may be able to get a resource URL of one of your uniquely named resource. Open a connection. Cast to JarURLConnection. Get the JarFile. Load the manifest from that. That may not work, particularly if Tomcat explodes the war.
[Update] Of course, the war file itself isn't on the classpath. The classpath will have something like WEB-INF/lib/(.jar|.zip) and WEB-INF/classes/. Getting a resource from the ServletContext should work.
Best solution: Do something different. :)
The right manifest exists in application root at server.
Find out the appication root, for instance by finding out classpath of your class:
String rootPath = getClass().getProtectionDomain().getCodeSource().getLocation().getPath()
Then replace the path above with the founded path: Glassfish example:
/applications/<webProject>/META-INF/MANIFEST.MF
It work for me.
Don't know about a "official" way to read it, but if the MANIFEST.MF can't be properly loaded as a resource, how about trying to derive its path from a "ServletContext.getRealPath()" on some web path defined in your app?
Writing the app version also to some else place (a property file in WEB-INF/classes) by ant during build is another solution that comes to my mind.
This is what I do to print various versions to a logfile. I have hardcoded an expanded path but apps may use servletContext.getRealPath("/") to read a full path to webapp folder. May print just given libraries or everything from lib folder.
// print library versions (jersey-common.jar, jackson-core-2.6.1.jar)
try {
List<String> jars = Arrays.asList( "jersey-common", "jackson-core", "openjpa", "mylib" );
StringBuilder verbuf = new StringBuilder();
for(File file : new File("/opt/tomcat/webapps/myapp/WEB-INF/lib/").listFiles() ) {
String name = file.getName();
if (file.isDirectory() || !file.isFile() || !name.endsWith(".jar") ) continue;
name = name.substring(0, name.length()-4);
boolean found = jars.contains(name);
if (!found) {
int idx = name.lastIndexOf('-');
if (idx>0)
found = jars.contains( name.substring(0, idx) );
}
if (!found) continue;
JarFile jarFile = new JarFile(file, false);
try {
String ver;
Manifest mf = jarFile.getManifest();
if (mf!=null) {
ver = mf.getMainAttributes().getValue("Bundle-Version");
if (ver==null || ver.isEmpty())
ver = mf.getMainAttributes().getValue("Implementation-Version");
} else ver=null;
if (verbuf.length()>0) verbuf.append(", ");
verbuf.append(name + "=" + (ver!=null?ver:"") );
} finally {
jarFile.close();
}
}
System.out.println( verbuf.toString() );
} catch(Exception ex) {
ex.printStackTrace();
}