launchdarkly/java-server-sdk

Classpath FeatureStore for offline use

klubi opened this issue · 4 comments

klubi commented

Is your feature request related to a problem? Please describe.
Would like to run component tests of dockerized springboot app in offline mode.

Describe the solution you'd like
FeatureStore (or FeatureStoreFactory) implementation that would allow to use file already stored in jar.

Describe alternatives you've considered
FeatureStore (or FeatureStoreFactory implementation that would allow to use provided InputStream for data source.

Additional context
I wasn't able to find a way to use flag configuration file stored in boot jar.

simplified version of my code:

@Autowired
private ResourceLoader resourceLoader;

FileDataSourceBuilder fileSource = FileData.dataSource()
    .filePaths(resourceLoader.getResource("classpath:ldConfig-ct.json").getURI().getRawPath())
    .autoUpdate(false);

Builder config = new Builder()
    .dataSource(fileSource)
    .events(Components.noEvents())
    .build();

I've been getting bean creation exception with below exception as a reason:

Caused by: java.lang.NullPointerException: null
	at java.base/sun.nio.fs.UnixPath.normalizeAndCheck(UnixPath.java:75) ~[na:na]
	at java.base/sun.nio.fs.UnixPath.<init>(UnixPath.java:69) ~[na:na]
	at java.base/sun.nio.fs.UnixFileSystem.getPath(UnixFileSystem.java:280) ~[na:na]
	at java.base/java.nio.file.Path.of(Path.java:147) ~[na:na]
	at java.base/java.nio.file.Paths.get(Paths.java:69) ~[na:na]
	at com.launchdarkly.client.integrations.FileDataSourceBuilder.filePaths(FileDataSourceBuilder.java:40) ~[launchdarkly-java-server-sdk-4.13.0.jar!/:4.13.0]

I can see how that'd be useful, but unfortunately in the current implementation it just is not possible to do it as simply as you're hoping to, because the kind of path you get from getResource(...).getURI().getRawPath() is not a real file path and can't be used as such.

I think it would not be too hard for us to change the implementation to support something like this, but it will probably have to wait until after the upcoming 5.0.0 release. In the meantime, the only workaround I can think of would be to create a temporary file— I mean, a real file on the filesystem— copy the data from your classpath file into that, and use that.

klubi commented

Yeah, that makes sense, using path that points to inside of a jar is tricky.

What about InputStream or Resource?

Workaround you suggest won't work in our CI setup :/

I think if the abstraction was to support both files and classpath resources, it would probably be represented as a URI. Of course this would mean that the auto-update feature would not always work, because that's based on a filesystem watcher.

This feature made it into today's 5.0.0 release. The API we settled on is that you simply call classpathResources instead of (or in addition to) filePaths. Unlike Spring's ResourceLoader.getResource(), the string parameter does not use a "classpath:" prefix.