This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.

Bug 148590 - Dynamic project properties
Summary: Dynamic project properties
Status: RESOLVED WONTFIX
Alias: None
Product: projects
Classification: Unclassified
Component: Ant Project (show other bugs)
Version: 6.x
Hardware: All All
: P3 blocker (vote)
Assignee: Tomas Stupka
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2008-09-29 05:16 UTC by _ gtzabari
Modified: 2016-07-07 08:38 UTC (History)
4 users (show)

See Also:
Issue Type: ENHANCEMENT
Exception Reporter:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description _ gtzabari 2008-09-29 05:16:01 UTC
dev build 200809250201

I am using Proguard to obfuscate my application. I would like to use the output JAR file when running my application
under Netbeans.

I manually replaced the value of "run.classpath" in project.properties to point to this JAR file but whenever I try
running Netbeans pops up a dialog saying "MyPackage.Main class wasn't found in MyProjectName. Select the main class: [...]"

If I extract the JAR file into a directory and point to that instead Netbeans runs it just fine. This indicates to me
that Netbeans isn't parsing "run.classpath" properly (if it contains only a JAR file).

Working around this bug is rather difficult because extracting the obfuscated JAR under Windows isn't always possible
(case insensitive file-system while the JAR contains case-sensitive collisions). Hopefully this is a trivial bug in the
classpath parsing code.
Comment 1 Milos Kleint 2008-09-30 07:25:54 UTC
well, when you changed the runtime classpath, did you also uncheck the "Compile on save" checkbox in the project
properties dialog?
if not, I suppose the problem can in the fact that compile on save doens't work with jar files but the output directory
class files.

Comment 2 _ gtzabari 2008-09-30 21:33:47 UTC
"compile on save" is disabled, so this should definitely work.
Comment 3 Milos Kleint 2008-10-01 12:56:17 UTC
might be silly comment, but I assume your Mypackage.Main is the package and name *after* obfuscation and not before.

I've checked the action runner and we do consult the execution classpath when trying to find the main class.
Comment 4 Milos Kleint 2008-10-01 14:05:10 UTC
I've done the following experiment:

1. created a sample j2se application, disabled cos, built it.
2. copied the project's jar in the dist subfolder to JavaApplication125_1.jar
3. updated the nbproject/project.properties file with these entries.
main.class=javaapplication125.Main
run.classpath=\
    ${basedir}/dist/JavaApplication125_1.jar

4. run file + run project.--> both executed and printed out the correct output.

closing as worksforme. please reopen with a sample application that demostrates the problem.
Comment 5 _ gtzabari 2008-11-05 20:21:38 UTC
I've managed to isolate the problem. My classpath is defined as:

run.classpath=\
  ../build/${config}/foo.jar

but for some reason Netbeans doesn't recognize the ${config} variable. I am expecting this to work because only
build-impl.xml target "-init-project" seems to read project.properties" and it clearly imports ${config} beforehand. It
looks like the run operation doesn't share the same code-base.

Would it be possible to update the IDE run operation to import ${config} and the other built-in properties? I expect a
JAR file in a different directory based on the configuration because the code relies on JNI and varies between 32-bit
and 64-bit architectures.
Comment 6 _ gtzabari 2008-11-05 20:24:36 UTC
Upon further reflection, it is worth noting that "Project Properties -> Libraries" doesn't vary depending on the
configuration. I'd hate to say it (because I need this feature) but this sounds to me like a RFE.

Can you think of a cleaner way to integrate applications that depend on JNI code with Netbeans such that different
configurations will run different architectures (think debug vs release, 32-bit vs 64-bit)?
Comment 7 _ gtzabari 2008-11-05 21:42:45 UTC
Does the run operation rely upon any build targets I could override? I'm looking for some sort of workaround (short of
hard-coding the value of ${config}) to get this to work.
Comment 8 _ gtzabari 2008-11-05 23:14:13 UTC
mkleint,

I stand corrected, ${config} works just fine. It just had a different value than what I expected. The next problem is
that I want to set:

run.classpath=\
  ../build/${config.dir}/foo.jar

where ${config.dir} is declared by my own Ant task (it depends on ${config} but differs from it). I need a way to expose
this property to the "run" and "libraries" related tasks. It looks like I can use "-pre-compile" for the libraries, but
it looks like "run" is missing a hook.

I can use "-post-compile" for the "run" Ant target, but it looks like "run project" doesn't use the "run" target so this
hook never gets used. Is it possible to modify "run project" so it begins using these hooks? Does "run project"
correspond to an existing Ant target?
Comment 9 _ gtzabari 2008-11-06 03:23:31 UTC
I think I've finally figured it out!

1) The configuration property files, found in nbproject/configs/<config-name>.properties, require literal values. You
cannot use Ant properties here.
2) You can override *any* property using these files, even "run.classpath". Cool! :)

The upside is that this makes for a great workaround. The downside is that you can't edit these values from the project
properties nor do I think you'll ever be able to. We've got to come up with a better solution in the long term.

I'm changing the summary and issue-type to reflect the fact that this is now a RFE. The current UI allows the use of
static configuration properties, I'd like to suggest looking into using dynamic configuration properties instead. That
is, have a single classpath, command-line properties but define it in terms of dynamic Ant properties.

I'd like to hear from the UI team on how feasible they think this is (is it doable or will it get too complex?). If you
decide to stick with static properties, the Project Properties UI would need to be modifies so Project classpath varies
per-configuration. Right now there is a single UI for classpath across *all* configurations.
Comment 10 Tomas Zezula 2008-11-06 08:45:20 UTC
Adding Jesse, an author of configurations to cc.
Comment 11 Jesse Glick 2008-11-07 02:19:47 UTC
You actually can use property substitutions in nbproject/configs/<config-name>.properties - but only for properties
defined at that point, which is going to be Java system properties, special things Ant core defines, and not much else.
This is intentional, because configs are supposed to be able to override other project properties, which would not be
possible if they were loaded later.

We do not expect to expose arbitrary properties to be overridden in configurations from the Properties dialog. That
said, letting the run classpath be overridden might be useful. Letting the _compile_ classpath vary by configuration is
not a good idea. It's not clear how you would produce a GUI to represent such overrides, anyway. IMHO the GUI would turn
out to be more buggy and complicated than just editing the property files (and writing some suggestions in wiki), since
this is a pretty advanced usage.

Regarding the "no main class found" dialog that can prevent you from running your app, I have never liked this and
wished the IDE would just trust me to do what I asked it to do. The worst that can happen is I get a
NoClassDefFoundError when I run the program. Please consider either killing this dialog or making it a warning with a
"shut up and let me continue" checkbox. Of course you can still invoke 'ant run' from a command shell, or in fact choose
the 'run' target from the build.xml node to bypass the dialog.
Comment 12 _ gtzabari 2008-11-07 05:43:07 UTC
> Please consider either killing this dialog

Either that or only pop it up if the "run" target fails due to "NoClassDefFoundError: <main-class>". Then you'll have
the best of both worlds.

> or making it a warning with a "shut up and let me continue" checkbox. Of course you can still invoke 'ant run'
> from a command shell, or in fact choose the 'run' target from the build.xml node to bypass the dialog.

The warning wouldn't have helped me because the underlying problem was that Netbeans wasn't letting me vary the
command-line per configuration. Running ant externally or through the built-in debugger reproduces productivity and is
too annoying for daily use.

Jesse, I see your point about dynamic properties being a UI nightmare. At the same time, I don't think this use-case is
as rare as you might think. Any Java program that uses JNI will likely need to use different LoadLibrary() statements
depending on whether it wants 32-bit, 64-bit, debug or release binaries to be loaded under the hood.

My suggestion is as follows:

- The UI allows users to configure static properties.
- Instead of importing the UI values directly into javac.classpath, run.classpath, etc you import them into some
temporary variables (say project.javac.classpath, project.run.classpath, etc).
- You then use new Ant targets to set "javac.classpath = project.javac.classpath" and let users override that

This way people can still use the UI to set static properties and manipulate those values dynamically from within Ant
scripts. My explanation isn't very clean but I hope you understand what I mean. You need something like -pre-compile,
compile, -post-compile but for project properties.
Comment 13 Jesse Glick 2008-11-07 17:04:45 UTC
Only pop up the dialog if the "run" target fails due to "NoClassDefFoundError: <main-class>" - may be possible, using a
custom AntLogger. Good suggestion.

Regarding JNI - sure but you can already vary VM arguments (or system properties or cmdline args) in a run config via
the GUI. Anyway there is already a separate RFE for better JNI support, but this is a complex topic. (JNA is probably a
better choice for many cases.)

What you are suggesting regarding redefining properties at runtime is already possible AFAIK. You just need to override
init (or similar), finally delegating back to the original init to load other properties as is. If you wish you can also
load project.properties using the 'prefix' option and then predefine some properties based on that. (The only catch is
that properties in project.properties which refer to other properties will not work when loading with prefix="...", but
I think in practice this would not matter.)
Comment 14 _ gtzabari 2009-01-04 20:28:05 UTC
> Anyway there is already a separate RFE for better JNI support, but this is a complex topic.

Where? I saw a handful of JNI issues but none of them covered this issue. The crux of the matter is that the Java code
depends upon different native libraries depending on the project configuration (debug vs release builds, different
platforms, etc). Right now it seems to be impossible to achieve under Netbeans. I don't see how JNA would help either.

All I want to do is take:

run.classpath=\
    ${javac.classpath}:\
    ${build.classes.dir}

from project.properties and override it as:

run.classpath=\
    $(configuration-specific-files):\
    ${javac.classpath}:\
    ${build.classes.dir}

using nbprojects/configs/*.properties

Granted there won't be an easy way to configure this from the GUI but at least it'll be implementable, which is a start.

As a simple example of why I need $(configuration-specific-files) note that Boost (the popular C++ library) has
different filenames for debug and release builds.
Comment 15 Jesse Glick 2009-01-06 01:35:53 UTC
So define e.g. added.run.classpath in various configs, and use it:

run.classpath=\
    ${added.run.classpath}:\
    ${javac.classpath}:\
    ${build.classes.dir}
Comment 16 djohnanderson 2010-02-08 13:39:25 UTC
Independently I just when down the same rathole -- I obfuscate, build different configurations to different directories and have struggled with the lack of a way to substitute ${config}.

This is a pretty common situation in most of the large commercial projects I've worked on so it's surprising to find out that it's NetBeans doesn't support it.

I got around the limitation of not being able to do substitutions in config properties by having init in my ant script write properties with substituted values -- I put substituted values in config/private.properties, e.g.

reference.swing.jar=/Users/john/Dev/Express/build/swing/Debug-dist/swing.jar
reference.core.jar=/Users/john/Dev/Express/build/core/Debug-dist/core.jar
reference.express-common.jar=/Users/john/Dev/Express/build/express-common/Debug-dist/express-common.jar
reference.PluginVersionCheck.jar=/Users/john/Dev/Express/build/PluginVersionCheck/Debug-dist/PluginVersionCheck.jar
home=/Users/john


It works ok, except I still occasionally get the main class not found bug. Switching configurations, which causes a rescan usually fixes the problem until the next time i restart netbeans or build another project.

I'd love to know what the source of the missing class bug really is -- it's the last of many NetBeans problems that I still haven't found a workaround for.

When you debug  program, where does Netbeans look for the files with the main class? I suspected it used debug.classpath, But for some reason when my main class is there I still get the main class bug.
Comment 17 Jesse Glick 2010-02-08 14:11:30 UTC
(In reply to comment #16)
> I got around the limitation of not being able to do substitutions in config
> properties by having init in my ant script write properties with substituted
> values -- I put substituted values in config/private.properties, e.g.
> 
> reference.swing.jar=/Users/john/Dev/Express/build/swing/Debug-dist/swing.jar

Should not be necessary. Put in nbproject/configs/debug.properties (_not_ nbproject/private/configs/debug.properties):

reference.swing.jar=../Express/build/swing/Debug-dist/swing.jar

or whatever your desired value is. When the debug config is active, swing.jar will be referenced from the stated location (all relative paths are resolved against ${basedir}).

You can also have reference.swing.jar defined in project.properties to some fallback value which will be used in case the active config does not override it. This is useful in case you just want to swap in a debug version of one or two libraries in certain configs.

nbproject/private/configs/*.properties may be used for per-user or per-computer settings you would not expect to share with others.

It is possible to have the compile-time classpath be sensitive to the active config, though this is generally a poor idea: changing config will force rescanning of project sources. Anyway it is rather nonsensical: there is some version of various libraries that your source code is expected to be compilable against, so if your source is not changing then neither should its classpath. Making the _runtime_ classpath be sensitive to config is fine, since this just affects how the Java launcher is run, not how code is compiled; you need only ensure that it contains enough that you do not get NoClassDefFoundError's, normally accomplished by making it a superset of the compile classpath.

One caveat, as explained in comment #11, is that it is not possible for this property file to refer to properties from nbproject/project.properties, because those are loaded strictly later.

> I still occasionally get the main class not found bug.

Should be filed separately if reproducible.

This is still open because of comment #9; it would be possible for the UI to expose more of the possibilities that the actual file format and Ant scripts already permit. I can't think of a good UI for it and I do not plan to work on it in the foreseeable future.
Comment 18 Martin Balin 2016-07-07 08:38:29 UTC
This old bug may not be relevant anymore. If you can still reproduce it in 8.2 development builds please reopen this issue.

Thanks for your cooperation,
NetBeans IDE 8.2 Release Boss