5

I've ran into a problem handling file names in javax.mail and some of those aspects need to be configured by session properties and some by system properties. Many classes of javax.mail seem to store the properties they work on in static fields, like in the following example for MimeBodyPart:

private static final boolean encodeFileName =
PropUtil.getBooleanSystemProperty("mail.mime.encodefilename", false);

From my understanding, this binds the concrete value of the system property to the life of the class in some concrete classloader. Whoever loads that class first, is the only one being able to influence the value. That was exactly what happened to me:

I knew that I needed to set some particular system property to influence file name handling and did so where I handled the file name, to keep things as close together as possible for documentation purposes etc. But for some reason, former code loaded the class of interest earlier, binding the wrong value to the static field. The only way to change this was to move setting my value to an earlier place in the call hierarchy, but it took me some time until I noticed the static-field thing.

That looks like a bad strategy to me, because I can't easily know which code with which I share the same classloader uses the same classes I do. In theory this would force me to set my system properties when starting the JVM already, making an implementation detail of my code an admin-detail in various different circumstances. If system properties are used at all instead of session-once, I would have expected those are queried live as well like session-once. Otherwise it's unnecessary difficult to change the corresponding settings under certain circumstances and use cases.

OTOH, the current approach might simply have some benefits I'm not aware of, like querying system properties is expensive as hell or alike.

So, what are the good reasons to do what MimeBodyPart does above?

Thorsten Schöning
  • 3,501
  • 2
  • 25
  • 46

2 Answers2

3

You're right, @maio290, it was purposely designed poorly. :-)

In a mutli-threaded application, querying the property dynamically doesn't really help.

In most cases these static properties were not expected to change over the lifetime of an application.

In some cases, the use of static was an unfortunate compromise because the code that needed it didn't have access to the Session. Changing all the APIs to pass the Session through explicitly would've made the code more complex.

Thread local storage was considered, but that depends too heavily on the threading model used by the application.

Wherever possible, Session properties were used, but in some cases there was no good way to do that so System properties were used.

Bill Shannon
  • 29,579
  • 6
  • 38
  • 40
  • 1
    I know for a **fact** [com.sun.mail.util.logging](https://eclipse-ee4j.github.io/mail/docs/api/com/sun/mail/util/logging/package-summary.html) was exclusively done using the Purposely Designed Poorly Driven Development. :-) – jmehrens Apr 03 '20 at 01:05
0

From my understanding, this binds the concrete value of the system property to the life of the class in some concrete classloader. Whoever loads that class first, is the only one being able to influence the value. That was exactly what happened to me.

Setting a property on the command line is much safer but, I understand your resistance to do so. From your question it is implied that you are using java.lang.System::setProperty to set the property. As you'll see in the documentation that there some scary warnings around doing that.

Per the API docs:

API Note: Changing a standard system property may have unpredictable results unless otherwise specified. See getProperties for details.

Per java.lang.System::getProperties:

API Note: Changing a standard system property may have unpredictable results unless otherwise specified. Property values may be cached during initialization or on first use. Setting a standard property after initialization using getProperties(), setProperties(Properties), setProperty(String, String), or clearProperty(String) may not have the desired effect.

The Java™ Tutorials -> System Utilities -> System Properties

Warning: Changing system properties is potentially dangerous and should be done with discretion. Many system properties are not reread after start-up and are there for informational purposes. Changing some properties may have unexpected side-effects.

In short, if you want it to always be set correctly you have to use the command-line.

jmehrens
  • 10,580
  • 1
  • 38
  • 47
  • Are properties for `javax.mail` those "standard properties" at all or isn't that text more related to path separators, user names and those kinds of things? Besides that, especially for `javax.mail`, setting things on the command line isn't safe at all in environments like application servers with many different apps with possibly many different needs. Setting things on runtime per app as needed is the correct thing to do instead, to not conflict with other apps. Problems arise when one app needs different settings in different circumstances. – Thorsten Schöning Apr 03 '20 at 07:27
  • @ThorstenSchöning Correct. For this case the applicable line from getProperties is the last sentence. The use of bold was just copied from the docs. The point of my answer was to hyper focus on the part about surprising behavior aspect of your question. JavaMail/JakartaMail is in compliance with the existing System.property behavior. – jmehrens Apr 03 '20 at 15:47