21

I have a system that caches the tiny/simple results of an on-startup SOAP call

I need instances to be able to reload their cache on startup (in case the SOAP service is dead) and ALSO handle the possibility of multiple instances using this cache file

I chose to use java.util.prefs but Java's builtin automatic sync thread is intermittently failing (1% of time using default JVM 30s backing store sync) dumping the following the exception:

Jan 8, 2010 12:30:07 PM java.util.prefs.FileSystemPreferences syncWorld
WARNING: Couldn't flush user prefs: java.util.prefs.BackingStoreException: Couldn't get file lock.

I suspected this bug but this was fixed in 1.5(tiger-b40) and our java 5 on this box is "1.5.0_16-b02".

I now suspect that it might be because we have multiple JVMs sharing this Backing Store, although this doesn't seem to happen on our other machines.

Can anyone confirm this? What are the risks, if any?

If my approach is flawed what should I be using as an alternative?

HaveAGuess
  • 1,231
  • 1
  • 13
  • 23
  • 2
    give some code, don't expect us to guess – Bozho Jan 08 '10 at 13:06
  • 1
    Definitely sounds like it'd be related to having multiple JVMs trying to work with the same file. People tend to use databases for centralizing data to be shared and modified concurrently by multiple processes. – BryanD Jan 08 '10 at 19:53
  • 3
    The `java.util.prefs` API is a turkey. I suggest ignoring it and using something that other people actually use, like a database. – skaffman Jan 09 '10 at 21:59
  • I actually don't want to share the data at all, Im just trying to create a cheap config (from a SOAP call) cache. DB is too heavy-weight – HaveAGuess Feb 09 '10 at 14:43
  • For those who are voting up Bozho: There is no code, this is one of the Java SYSTEM threads that is failing! lol – HaveAGuess Apr 12 '11 at 09:51
  • This is an excellent critique of the Preferences API, and what can be done to work around issues such as Exceptions in the sync timer. http://www.allaboutbalance.com/articles/disableprefs/ I wrote my own File locking/caching using Java NIO into System.getProperty("java.io.tmpdir") Good luck! – HaveAGuess Apr 12 '11 at 10:12

4 Answers4

11

"I now suspect that it might be because we have multiple JVMs sharing this Backing Store"

This could absolutely be the case! If two JVMs attempt to lock the file at the same then this is what you'll see.

The exact details will depend on the type of lock, operating system and file system.

You might want to try wrapping the operation that causes this in a try/catch block, then retry the operation if it fails.

Kevin Wright
  • 49,540
  • 9
  • 105
  • 155
  • Saved dead link: http://web.archive.org/web/20170704120035/http://www.allaboutbalance.com/articles/disableprefs/ – Vadzim Dec 03 '19 at 14:14
1

I ran into the same issue with jetty. I found the following fixed the issue.

Add a .systemPrefs to your JRE directory and provide access to the user who is running the process which is complaining.

Once that is done, go to the Jetty directory and open the start.ini file

-Djava.util.prefs.userRoot={user's home directory}

-Djava.util.prefs.systemRoot={user's home directory}

Once finished adding those lines I restarted jetty and found that the errors were gone.

AVI
  • 5,516
  • 5
  • 29
  • 38
user2981810
  • 379
  • 4
  • 11
  • I guess this works by changing the store that that particular JRE uses, to avoid clashing with the other JRE you must be running. Thanks for sharing – HaveAGuess Sep 21 '14 at 00:46
0

Instead of using Preferences, just use any serializable Map and make a very simple cache class which serializes and deserializes it to a randomly-generated temporary filename (the filename being generated on first initialisation). Since it is only a cache, you can just catch any exceptions and reset the cache back to its initial state when an exception happens, so it will re-fetch from the original data source (the SOAP service in your case). So there's no need to worry about serialVersionUID or any of that compatibility stuff, if you don't want to.

Robin Green
  • 32,079
  • 16
  • 104
  • 187
  • The problem is I need instances to be able to reload their cache on startup (in case the SOAP service is dead) and ALSO handle the possibility of multiple instances using this cache file. I'll add to OP – HaveAGuess Apr 14 '11 at 21:14
0

To fix this alter ownership of the /etc/.java/.systemPrefs folder to your user and root like this:

sudo chown 777 user /etc/.java/.systemPrefs