Can i create a Path using its value??
Path p=new Path();
p.getElements().add(new MoveTo(mouse.getX(), mouse.getY()));
System.out.Print(p);
This will print
Path#29f12030
can i convert this into path again?
You have already created a path and it's still a path, you don't need to convert it.
When you call System.out.print(p) you invoke the default toString function on your p object, which prints an internal Java reference to your Path (e.g. Path#29f12030).
If you override the default toString method with your own implementation, as is shown in the sample below, your print statement will display the value of the path.
public class PrintPath extends Application {
public static void main(String[] args) throws Exception { launch(args); }
#Override public void start(final Stage stage) throws Exception {
Path p = new PrintedPath();
p.getElements().add(new MoveTo(100, 150));
System.out.println(p);
stage.setScene(new Scene(new StackPane()));
stage.show();
}
class PrintedPath extends Path {
#Override public String toString() {
StringBuilder b = new StringBuilder();
for (PathElement e: getElements()) {
if (e instanceof MoveTo) {
MoveTo m = (MoveTo) e;
b.append("M").append(m.getX()).append(" ").append(m.getY()).append(" ");
}
// logic to display other path element types could be added here . . .
}
return "Path{ " + b.toString() + "}";
}
}
}
I think you should elaborate your purpose of sending data over network in a context of your app architecture. Give some fundamental details about it. In my understanding, you want to send a Path instance over the network and able to process it on the other end. If so,
- have a look to a serialization API. Read the post about it "How to transfer objects over network using java". Extend the Path or wrap it into another class then implement Serializable.
- Or, refer to Java Architecture for XML Binding (JAXB). Basically by using it you can convert/marshal the objects to XML strings and transfer over the network and then unmarshal it. Here is hello world example.
- Or, implement your own encoding/decoding mechanism to transfer the Path object.
Related
can anyone guide me on how to perform a reload of an apache commons configuration2 properties. I'm unable to find any implementation of this anywhere. The apache docs are a bit too abstract. This is what I have so far but it's not working.
CombinedConfiguration cc = new CombinedConfiguration();
Parameters params = new Parameters();
File configFile = new File("config.properties");
File emsFile = new File("anotherconfig.properties");
ReloadingFileBasedConfigurationBuilder<FileBasedConfiguration> configBuilder =
new ReloadingFileBasedConfigurationBuilder<FileBasedConfiguration>(PropertiesConfiguration.class)
.configure(params.fileBased()
.setFile(configFile));
PeriodicReloadingTrigger reloadTrg = new PeriodicReloadingTrigger(configBuilder.getReloadingController(), null, 5, TimeUnit.SECONDS);
reloadTrg.start();
cc.addConfiguration(configBuilder.getConfiguration());
FileBasedConfigurationBuilder<FileBasedConfiguration> emsBuilder =
new FileBasedConfigurationBuilder<FileBasedConfiguration>(PropertiesConfiguration.class)
.configure(params.properties()
.setFile(emsFile));
cc.addConfiguration(emsBuilder.getConfiguration());
DataSource ds = EmsDataSource.getInstance().getDatasource(this);
BasicConfigurationBuilder<DatabaseConfiguration> dbBuilder =
new BasicConfigurationBuilder<DatabaseConfiguration>(DatabaseConfiguration.class);
dbBuilder.configure(
params.database()
.setDataSource(ds)
.setTable("EMS_CONFIG")
.setKeyColumn("KEY")
.setValueColumn("VALUE")
);
cc.addConfiguration(dbBuilder.getConfiguration());
The configuration obtained from a builder is not updated automatically. You need to get the configuration from the builder every time you read it.
From Automatic Reloading of Configuration Sources:
One important point to keep in mind when using this approach to reloading is that reloads are only functional if the builder is used as central component for accessing configuration data. The configuration instance obtained from the builder will not change automagically! So if an application fetches a configuration object from the builder at startup and then uses it throughout its life time, changes on the external configuration file become never visible. The correct approach is to keep a reference to the builder centrally and obtain the configuration from there every time configuration data is needed.
use following code:
#Component
public class ApplicationProperties {
private PropertiesConfiguration configuration;
#PostConstruct
private void init() {
try {
String filePath = PropertiesConstants.PROPERTIES_FILE_PATH;
System.out.println("Loading the properties file: " + filePath);
configuration = new PropertiesConfiguration(filePath);
//Create new FileChangedReloadingStrategy to reload the properties file based on the given time interval
FileChangedReloadingStrategy fileChangedReloadingStrategy = new FileChangedReloadingStrategy();
fileChangedReloadingStrategy.setRefreshDelay(PropertiesConstants.REFRESH_DELAY);
configuration.setReloadingStrategy(fileChangedReloadingStrategy);
} catch (ConfigurationException e) {
e.printStackTrace();
}
}
public String getProperty(String key) {
return (String) configuration.getProperty(key);
}
public void setProperty(String key, Object value) {
configuration.setProperty(key, value);
}
public void save() {
try {
configuration.save();
} catch (ConfigurationException e) {
e.printStackTrace();
}
}
}
Is it possible to wrap a whole Stylesheet in a string and apply it to a certain node?
Usage case would be to add specific (non changeble) behavior for PseudoClass.
I know I can use pane.getStylesheets().add(getClass().getResource("mycss.css").toExternalForm());, but I would like to know if there's some way to embrd it direcly in source; something along the lines:
pane.getStylesheets().add(
".button:ok { -fx-background-color: green; }\n"+
".button:ko { -fx-background-color: red; }");
I found a way of doing this by defining a new URL connection:
private String css;
public void initialize() {
...
// to be done only once.
URL.setURLStreamHandlerFactory(new StringURLStreamHandlerFactory());
...
}
private void updateCss(Node node) {
// can be done multiple times.
css = createCSS();
node.getStylesheets().setAll("internal:"+System.nanoTime()+"stylesheet.css");
}
private class StringURLConnection extends URLConnection {
public StringURLConnection(URL url){
super(url);
}
#Override public void connect() throws IOException {}
#Override public InputStream getInputStream() throws IOException {
return new StringBufferInputStream(css);
}
}
private class StringURLStreamHandlerFactory implements URLStreamHandlerFactory {
URLStreamHandler streamHandler = new URLStreamHandler(){
#Override protected URLConnection openConnection(URL url) throws IOException {
if (url.toString().toLowerCase().endsWith(".css")) {
return new StringURLConnection(url);
}
throw new FileNotFoundException();
}
};
#Override public URLStreamHandler createURLStreamHandler(String protocol) {
if ("internal".equals(protocol)) {
return streamHandler;
}
return null;
}
}
Obviously protocol "internal" can be any (non clashing) well-formed string and (in this simple example) filepath is compeltely ignored.
I use this to set the global .css, so I do not need to remember multiple strings.
It seems the Stream is opened just once, but I do not know if this holds true in all cases.
Feel free to complicate the code as needed ;)
Credit for this method goes to Jasper Potts (see this example)
Here is my CSS updater class based on ZioBytre's answer (+1 works very well).
This is a self contained class that can easily be copied to a project and used as it is.
It has a dependency on the commons IO IOUtils class to return a Stream based on a String. But this could easily be inlined or replaced by another library if needed.
I use this class in a project where the CSS is dynamically editable inside the application, on the server side, and pushed to the JavaFX clients. It could be used in any scenario where the CSS string does not come from a file or URL but from another source (server app, database, user input...)
It has a method to bind a string property so that the CSS changes will be automatically applied as soon as they happen.
/**
* Class that handles the update of the CSS on the scene or any parent.
*
* Since in JavaFX, stylesheets can only be loaded from files or URLs, it implements a handler to create a magic "internal:stylesheet.css" url for our css string
* see : https://github.com/fxexperience/code/blob/master/FXExperienceTools/src/com/fxexperience/tools/caspianstyler/CaspianStylerMainFrame.java
* and : http://stackoverflow.com/questions/24704515/in-javafx-8-can-i-provide-a-stylesheet-from-a-string
*/
public class FXCSSUpdater {
// URL Handler to create magic "internal:stylesheet.css" url for our css string
{
URL.setURLStreamHandlerFactory(new StringURLStreamHandlerFactory());
}
private String css;
private Scene scene;
public FXCSSUpdater(Scene scene) {
this.scene = scene;
}
public void bindCss(StringProperty cssProperty){
cssProperty.addListener(e -> {
this.css = cssProperty.get();
Platform.runLater(()->{
scene.getStylesheets().clear();
scene.getStylesheets().add("internal:stylesheet.css");
});
});
}
public void applyCssToParent(Parent parent){
parent.getStylesheets().clear();
scene.getStylesheets().add("internal:stylesheet.css");
}
/**
* URLConnection implementation that returns the css string property, as a stream, in the getInputStream method.
*/
private class StringURLConnection extends URLConnection {
public StringURLConnection(URL url){
super(url);
}
#Override
public void connect() throws IOException {}
#Override public InputStream getInputStream() throws IOException {
return IOUtils.toInputStream(css);
}
}
/**
* URL Handler to create magic "internal:stylesheet.css" url for our css string
*/
private class StringURLStreamHandlerFactory implements URLStreamHandlerFactory {
URLStreamHandler streamHandler = new URLStreamHandler(){
#Override
protected URLConnection openConnection(URL url) throws IOException {
if (url.toString().toLowerCase().endsWith(".css")) {
return new StringURLConnection(url);
}
throw new FileNotFoundException();
}
};
#Override
public URLStreamHandler createURLStreamHandler(String protocol) {
if ("internal".equals(protocol)) {
return streamHandler;
}
return null;
}
}
}
Usage :
StringProperty cssProp = new SimpleStringProperty(".root {-fx-background-color : red}");
FXCSSUpdater updater = new FXCSSUpdater(scene);
updater.bindCss(cssProp);
//new style will be applied to the scene automatically
cssProp.set(".root {-fx-background-color : green}");
//manually apply css to another node
cssUpdater.applyCssToParent(((Parent)popover.getSkin().getNode()));
For anyone who is writing framework level code that does not want to use up the one and only override of the global, static url stream factory, you can instead tie into the internal "service loader" framework in the URL class itself.
To do this, you must create a class named Handler extends URLStreamHandler and update the system property java.protocol.handler.pkgs to point to the package of that class, minus the final package suffix. So, com.fu.css would set the property to com.fu, then all css:my/path requests would route to this handler.
I will paste the class I am using below; forgive the weird collections and supplier interfaces; you can guess what these do and replace them with standard utilities without much trouble.
package xapi.jre.ui.css;
import xapi.collect.X_Collect;
import xapi.collect.api.CollectionOptions;
import xapi.collect.api.StringTo;
import xapi.fu.Out1;
import xapi.io.X_IO;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLStreamHandler;
import java.nio.charset.Charset;
/**
* I abhor the name of this class,
* but it must be called "Handler" in order for java.net.URL to be able to find us.
*
* It sucks, but it's not our api, and it's the only way to get dynamic stylesheets in JavaFx,
* short of overriding the url stream handler directly (and this can only be done once in a single
* JVM, and as framework-level code, it is unacceptable to prevent clients from choosing to
* override the stream handler themselves).
*
* Created by James X. Nelson (james #wetheinter.net) on 8/21/16.
*/
public class Handler extends URLStreamHandler {
private static final StringTo<Out1<String>> dynamicFiles;
static {
// Ensure that we are registered as a url protocol handler for css:/path css files.
String was = System.getProperty("java.protocol.handler.pkgs", "");
System.setProperty("java.protocol.handler.pkgs", Handler.class.getPackage().getName().replace(".css", "") +
(was.isEmpty() ? "" : "|" + was ));
dynamicFiles = X_Collect.newStringMap(Out1.class,
CollectionOptions.asConcurrent(true)
.mutable(true)
.insertionOrdered(false)
.build());
}
public static void registerStyleSheet(String path, Out1<String> contents) {
dynamicFiles.put(path, contents);
}
#Override
protected URLConnection openConnection(URL u) throws IOException {
final String path = u.getPath();
final Out1<String> file = dynamicFiles.get(path);
return new StringURLConnection(u, file);
}
private static class StringURLConnection extends URLConnection {
private final Out1<String> contents;
public StringURLConnection(URL url, Out1<String> contents){
super(url);
this.contents = contents;
}
#Override
public void connect() throws IOException {}
#Override public InputStream getInputStream() throws IOException {
return X_IO.toStream(contents.out1(), Charset.defaultCharset().name());
}
}
}
Now, any code can call Handler.registerStylesheet("my/path", ()->"* { -fx-css: blah }");, and you can use this stylesheet anywhere via "css:my/path".
Note that I am only looking at the path portion of the url; I intend to leverage query parameters to further increase the dynamism (by using a css factory that accepts a map of parameters), but that is beyond the scope of this question.
I looked at the documentation and I don’t see a built-in way to do that. getStylesheets is the only stylesheet-related method in Parent, and it only accepts “string URLs linking to the stylesheets”, not stylesheets themselves. It returns a generic ObservableList, so its return value has no special methods for different types; only a generic add. This is consistent with getResource returning a URL, and toExternalForm() merely returning a String version of that URL object.
However, there is one thing you could try: a data URI. Instead of passing in a generated URI to a stylesheet file, pass in a data URI whose contents are that stylesheet. I don’t know if the API would accept that kind of URI, though, given that the CSS Reference Guide linked in getStylesheets’s documentation says
A style sheet URL may be an absolute URL or a relative URL.
Try a really simple data URI first to see if it works. You can generate one using this online tool. If Java does accept a data URI, then you just need to wrap your CSS-containing String with some method call that converts a String to a data URI, something like this:
pane.getStylesheets().add(new DataURI(
".button:ok { -fx-background-color: green; }\n"+
".button:ko { -fx-background-color: red; }").toString());
The class DataURI is hypothetical. If JavaFX accepts a manually-generated data URI, then you will have to find a library that provides that DataURI class yourself; I’m sure one exists somewhere.
There is also a way to specify inline CSS for a certain Node as a String, which is almost what you are looking for. It is mentioned in the CSS Reference Guide:
CSS styles can come from style sheets or inline styles. Style sheets are loaded from the URLs specified in the stylesheets variable of the Scene object. If the scene graph contains a Control, a default user agent style sheet is loaded. Inline styles are specified via the Node setStyle API. Inline styles are analogous to the style="…" attribute of an HTML element.
However, it sounds like it does not support selectors in the CSS, only rules – so rather than saying .red { color: red; }, you would only be able to write color: red;, and it would apply to all children of that Node. This doesn’t sound like what you want. So a data URI is your only hope.
EDIT: While this is a smart idea (I didn't know about data URIs before) it doesn't work. I have the same requirement so I tried. It doesn't raise an exception but there is a warning in the the logs and the styles are not applied :
I used this style :
.root{
-fx-font-family: "Muli";
-fx-font-weight: lighter;
-fx-font-size: 35pt;
-fx-padding: 0;
-fx-spacing: 0;
}
And using the provided tool generated the following data URI :
data:text/css;charset=utf-8,.root%7B%0D%0A%20%20%20%20-fx-font-family%3A%20%22Muli%22%3B%0D%0A%20%20%20%20-fx-font-weight%3A%20lighter%3B%0D%0A%20%20%20%20-fx-font-size%3A%2035pt%3B%0D%0A%20%20%20%20-fx-padding%3A%200%3B%0D%0A%20%20%20%20-fx-spacing%3A%200%3B%0D%0A%7D
Applying it to my scene :
scene.getStylesheets().add("data:text/css;charset=utf-8,.root%7B%0D%0A%20%20%20%20-fx-font-family%3A%20%22Muli%22%3B%0D%0A%20%20%20%20-fx-font-weight%3A%20lighter%3B%0D%0A%20%20%20%20-fx-font-size%3A%2035pt%3B%0D%0A%20%20%20%20-fx-padding%3A%200%3B%0D%0A%20%20%20%20-fx-spacing%3A%200%3B%0D%0A%7D");
Results in (pardon my French, AVERTISSEMENT=WARNING):
janv. 07, 2015 12:02:03 PM com.sun.javafx.css.StyleManager loadStylesheetUnPrivileged
AVERTISSEMENT: Resource "data:text/css;charset=utf-8,%23header%7B%0D%0A%20%20%20%20-fx-background-color%3A%23002D27%3B%0D%0A%20%20%20%20-fx-font-size%3A%2035pt%3B%0D%0A%20%20%20%20-fx-text-fill%3A%20%23fff%3B%0D%0A%7D" not found.
So sadly JavaFX seems not to be aware of data URIs.
Since JavaFX 17 it is now possible to use data URIs.
For example,
scene.getStylesheets().add("data:text/css;base64," + Base64.getEncoder().encodeToString("* { -fx-color: red; }".getBytes(StandardCharsets.UTF_8)));
will simply work in JavaFX 17.
Newbie question about JavaFX that I haven't been able to answer, despite knowing it must be pretty simple to do and not finding any resources on it anywhere I've looked (tutorials, many of the Oracle online docs, articles, the well-known JavaFX bloggers, etc.)
I'm developing a command line (script) running application and I have successfully gotten output (via ProcessBuilder) from the script that I can display in an ongoing manner, as things happen on the command line. That is, I can do System.out.println(line); all day long, showing the output in the console, which simply returns output from an input stream returned by the 'myProcess' that's running, created like this:
BufferedReader bri = new BufferedReader(new InputStreamReader(myProcess.getInputStream()))
So I am able to see all the output coming back from the script.
I'd like to set-up a JavaFX TextArea or ScrollPane or, not sure what, to display this output text (there's a lot of it, like several thousand lines) as an ongoing 'progress' of what's taking place in the script, as it happens. I have a Scene, I have buttons and get input from this scene to start the script running, but now I'd like to show the result of clicking the button "RUN THIS SCRIPT", so to speak.
I assume I need to create a TextArea as described here or perhaps a TextBuilder would be useful to begin making it. Not sure.
I need a bit of help in how to setup the binding or auto-scroll/auto-update part of this.
Can someone provide me a place to start, to do this with JavaFX? I'd rather not use Swing.
(I'm using JavaFX 2.2, JDK 1.7u7, all the latest stuff, and yes, this is an FXML app--so doing it that way would be preferred.)
UPDATE: Sergey Grinev's answer was very helpful in the binding part. But here is some more detail on what I mean when I ask for "a bit of help in how to setup" -- basically, I need to return control to the main Scene to allow the user to Cancel the script, or to otherwise monitor what's going on. So I'd like to "spawn" the process that runs that script (that is, have some kind of 'free running process'), but still get the output from it. (I wasn't very clear on that in my initial question.)
The technique I'm using here (see below) is to do a waitFor on the process, but of course this means the dialog/Scene is 'hung' while the script executes. I'd like to gain control back, but how do I pass the 'p' (Process) to some other controller piece (or alternatively, simply kick off that other process passing in the parameters to start the script and have it start the script) that will then do the auto-update, via the binding Sergey Grinev mentions--without 'hanging' the Scene/window? Also: Can I then 'stop' this other process if the user requests it?
Here is my current code ('waits' while script--which takes 20-40 min to run!--completes; this is not what I want, I'd like control returned to the user):
public class MyController implements Initializable {
#FXML
private void handleRunScript(ActionEvent event) throws IOException {
ProcessBuilder pb = new ProcessBuilder("myscript.sh", "arg1", "arg2", ...);
Process p = pb.start();
try {
BufferedReader bri = new BufferedReader
(new InputStreamReader(p.getInputStream()));
String line;
while ((line = bri.readLine()) != null) {
System.out.println(line);
textAreaRight.setText(line);
}
bri.close();
p.waitFor();
}
catch (Exception err) {
err.printStackTrace();
}
}
#FXML
private void handleCancel(ActionEvent event) {
doSomethingDifferent();
}
}
To log strings you can use TextArea
To make it asynchronious you need to make a separate thread for output reader.
public class DoTextAreaLog extends Application {
TextArea log = new TextArea();
Process p;
#Override
public void start(Stage stage) {
try {
ProcessBuilder pb = new ProcessBuilder("ping", "stackoverflow.com", "-n", "100");
p = pb.start();
// this thread will read from process without blocking an application
new Thread(new Runnable() {
#Override
public void run() {
try {
//try-with-resources from jdk7, change it back if you use older jdk
try (BufferedReader bri = new BufferedReader(new InputStreamReader(p.getInputStream()))) {
String line;
while ((line = bri.readLine()) != null) {
log(line);
}
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
}).start();
stage.setScene(new Scene(new Group(log), 400, 300));
stage.show();
} catch (IOException ex) {
ex.printStackTrace();
}
}
#Override
public void stop() throws Exception {
super.stop();
// this called on fx app close, you may call it in user action handler
if (p!=null ) {
p.destroy();
}
}
private void log(final String st) {
// we can access fx objects only from fx thread
// so we need to wrap log access into Platform#runLater
Platform.runLater(new Runnable() {
#Override
public void run() {
log.setText(st + "\n" + log.getText());
}
});
}
public static void main(String[] args) {
launch();
}
}
I searched a lot and still couldn't find a solid solution for this. Suppose you have methods in your application. This methods use "System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration" to access some setting in the web.config. If you try to test these methods, your tests will fail because your test project doesn't have web.config.
What is the best way to solve this problem. For projects with simple config file, I usually use a method like this as facade method.
public class Config
{
public static String getKeyValue(String keyName)
{
if (keyName == String.Empty) return String.Empty;
String result = "";
System.Configuration.Configuration rootWebConfig1 =
System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration(null);
if (rootWebConfig1.AppSettings.Settings.Count > 0)
{
System.Configuration.KeyValueConfigurationElement reportEngineKey =
rootWebConfig1.AppSettings.Settings[keyName];
if (reportEngineKey != null)
{
result = reportEngineKey.Value;
}
}
return result;
}
}
Every time I tried to set the path for OpenWebConfiguration( ), I got the error "The relative virtual path is not allowed"
To make that scenario more testable, I usually take the approach of making a "settings manager" of my own, and giving it an interface. So for example:
public interface IConfig
{
string GetSettingValue(string settingName);
}
Then I can have my "real" implementation:
public sealed class Config : IConfig
{
public string GetSettingValue(string settingName)
{
// your code from your getKeyValue() method would go here
}
}
Then my code that uses it would take in an instance of this (this is an example of the Dependency Inversion Principal):
public void DoStuff(IConfig configuration)
{
string someSetting = configuration.GetSettingValue("ThatThingINeed");
// use setting...
}
So now for my production code, I can call DoStuff and pass in an instance of Config.
When I need to test, I can use a mocking tool (Moq, JustMock, RhinoMocks, etc) to create a fake IConfig that returns a known value without hitting the actual .config file, or you can do it without a mocking framework by making your own mocks (and store them in your test project).
public class ConfigMock : IConfig
{
private Dictionary<string, string> settings;
public void SetSettingValue(string settingName, string value)
{
settings[settingName] = value;
}
public string GetSettingValue(string settingName)
{
return settings[settingName];
}
}
and
[Test]
public void SomeExampleTest()
{
var config = new ConfigMock();
config.SetSettingValue("MySetting", "SomeValue");
var underTest = new MyClass();
underTest.DoStuff(config);
}
The easiest way to do this is to use a mocking library such as moq. It takes a bit of time to figure it out, but once you do you can abstract away most of your plumbing to return the values you need for repeatable, consistent testing.
my requirement is as follows:
INFO: icefaces upload component, uploads the files to relative folder and creates for each user a sub-directory in that folder with the sessionId.
Requirement: at the sessionDestroyed for each user, i want to get the real path, to delete current user folder.
i know how to get the real path with JSF as follows:
ServletContext ctx = (ServletContext) FacesContext.getCurrentInstance()
.getExternalContext().getContext();
String deploymentDirectoryPath = ctx.getRealPath("/");
Problem: if you try to get the real path in sessionDestroyed you will get null pointer exception, so i was wondering if there's a way to initialize the variable deploymentDirectoryPath in the listener so i can use it in sessionDestroyed method, or maybe initialize the real path variable on application startup and use it here ?
please advise how to solve this issue.
Even though you haven't posted the actual code that relates to the problem, the following gives me the real path:
public class MySessListener implements HttpSessionListener {
#Override
public void sessionCreated(final HttpSessionEvent se) {
System.out.println(Thread.currentThread().getStackTrace()[1]);
new Timer().schedule(new TimerTask() {
#Override
public void run() {
HttpSession sess = se.getSession();
sess.invalidate();
}
}, 10000);
}
#Override
public void sessionDestroyed(HttpSessionEvent se) {
System.out.println(Thread.currentThread().getStackTrace()[1]);
String realPath = se.getSession().getServletContext().getRealPath("/");
System.out.println("realPath: " + realPath);
}
}
Output
INFO: com.bhesh.demo.web.listener.MySessListener.sessionCreated(MySessListener.java:13)
INFO: com.bhesh.demo.web.listener.MySessListener.sessionDestroyed(MySessListener.java:26)
INFO: realPath: C:\Documents and Settings\Bhesh\My Documents\NetBeansProjects\JsfMessageList\build\web\
Based on BalusC sound advice here and elsewhere one could write a general purpose function like this:
String getPath(){
ExternalContext tmpEC;
tmpEC = FacesContext.getCurrentInstance().getExternalContext();
String realPath=tmpEC.getRealPath("/");
return realPath;
}
You can get the real path as follows:-
FacesContext.getCurrentInstance().getExternalContext().getRealPath("/");
EDIT:-
As mentioned by BalusC in one of his answers, you should think twice before using getRealPath("/") because if one has not chose to expand the war file then, getRealPath("/") might return null.
Use getExternalContext.getResourceAsStream instead. as per, docs, It is valid to call this method during application startup or shutdown.