Implementing Java Money Links in OSGI

I am using the Java money reference implementation (JSR354) found here: http://javamoney.imtqy.com/ri.html

However, I use it in an OSGI environment. This gives me the following exception:

[qtp305372452-33] ERROR org.javamoney.moneta.spi.MonetaryConfig - Error loading javamoney.properties, ignoring bundleresource://7.fwk302155142:3/javamoney.properties
java.lang.IllegalStateException: AmbiguousConfiguration detected for 'load.ECBHistoricRateProvider.resource'.
    at org.javamoney.moneta.spi.MonetaryConfig.updateConfig(MonetaryConfig.java:90)
    at org.javamoney.moneta.spi.MonetaryConfig.<init>(MonetaryConfig.java:53)
    at org.javamoney.moneta.spi.MonetaryConfig.<clinit>(MonetaryConfig.java:39)
    at org.javamoney.moneta.DefaultMonetaryContextFactory.getContext(DefaultMonetaryContextFactory.java:38)
    at org.javamoney.moneta.Money.<clinit>(Money.java:79)
    at org.javamoney.moneta.internal.MoneyAmountBuilder.create(MoneyAmountBuilder.java:42)
    at org.javamoney.moneta.internal.MoneyAmountBuilder.create(MoneyAmountBuilder.java:33)
    at org.javamoney.moneta.spi.AbstractAmountBuilder.create(AbstractAmountBuilder.java:61)
    at com.eijsink.ef.module.pricing.Price.createAmount(Price.java:214)
    at com.eijsink.ef.module.pricing.Price.<init>(Price.java:73)
    at com.eijsink.ef.module.pricing.view.PriceField.storeValue(PriceField.java:210)
    at com.eijsink.ef.module.pricing.view.PriceField.lambda$6(PriceField.java:169)
    at com.eijsink.ef.module.pricing.view.PriceField$$Lambda$163/23040973.valueChange(Unknown Source)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:483)
    at com.vaadin.event.ListenerMethod.receiveEvent(ListenerMethod.java:508)
    at com.vaadin.event.EventRouter.fireEvent(EventRouter.java:198)
    at com.vaadin.event.EventRouter.fireEvent(EventRouter.java:161)
    at com.vaadin.server.AbstractClientConnector.fireEvent(AbstractClientConnector.java:977)
    at com.vaadin.ui.AbstractField.fireValueChange(AbstractField.java:1137)
    at com.vaadin.ui.AbstractField.setValue(AbstractField.java:548)
    at com.vaadin.ui.AbstractSelect.setValue(AbstractSelect.java:709)
    at com.vaadin.ui.ComboBox.changeVariables(ComboBox.java:674)
    at com.vaadin.server.communication.ServerRpcHandler.changeVariables(ServerRpcHandler.java:486)
    at com.vaadin.server.communication.ServerRpcHandler.handleInvocations(ServerRpcHandler.java:305)
    at com.vaadin.server.communication.ServerRpcHandler.handleRpc(ServerRpcHandler.java:184)
    at com.vaadin.server.communication.UidlRequestHandler.synchronizedHandleRequest(UidlRequestHandler.java:92)
    at com.vaadin.server.SynchronizedRequestHandler.handleRequest(SynchronizedRequestHandler.java:41)
    at com.vaadin.server.VaadinService.handleRequest(VaadinService.java:1408)
    at com.vaadin.server.VaadinServlet.service(VaadinServlet.java:350)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:848)
    at org.eclipse.equinox.http.servlet.internal.ServletRegistration.service(ServletRegistration.java:61)
    at org.eclipse.equinox.http.servlet.internal.ProxyServlet.processAlias(ProxyServlet.java:128)
    at org.eclipse.equinox.http.servlet.internal.ProxyServlet.service(ProxyServlet.java:76)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:848)
    at org.eclipse.equinox.http.jetty.internal.HttpServerManager$InternalHttpServiceServlet.service(HttpServerManager.java:386)
    at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:684)
    at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:501)
    at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:229)
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:137)
    at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:533)
    at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1088)
    at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:428)
    at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:193)
    at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1020)
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:135)
    at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:116)
    at org.eclipse.jetty.server.Server.handle(Server.java:370)
    at org.eclipse.jetty.server.AbstractHttpConnection.handleRequest(AbstractHttpConnection.java:494)
    at org.eclipse.jetty.server.AbstractHttpConnection.content(AbstractHttpConnection.java:982)
    at org.eclipse.jetty.server.AbstractHttpConnection$RequestHandler.content(AbstractHttpConnection.java:1043)
    at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:865)
    at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:240)
    at org.eclipse.jetty.server.AsyncHttpConnection.handle(AsyncHttpConnection.java:82)
    at org.eclipse.jetty.io.nio.SelectChannelEndPoint.handle(SelectChannelEndPoint.java:667)
    at org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run(SelectChannelEndPoint.java:52)
    at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:608)
    at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:543)
    at java.lang.Thread.run(Thread.java:744)

An exception is not thrown when using the Java money classes, but instead it is logged only. Everything works, but this exception pops up all the time in my magazines, which is very annoying for me and my colleagues.

I traced the problem to this class in the library:

package org.javamoney.moneta.spi;

//imports

public final class MonetaryConfig {

    private static final Logger LOG = Logger
            .getLogger(MonetaryConfig.class.getName());

    private static final MonetaryConfig INSTANCE = new MonetaryConfig();

    private Map<String, String> config = new HashMap<>();
    private Map<String, Integer> priorities = new HashMap<>();

    private MonetaryConfig() {
        try {
            Enumeration<URL> urls = getClass().getClassLoader().getResources(
                    "javamoney.properties");
            while (urls.hasMoreElements()) {
                URL url = urls.nextElement();
                try {
                    Properties props = new Properties();
                    props.load(url.openStream());
                    updateConfig(props);
                } catch (Exception e) {
                    LOG.log(Level.SEVERE,
                            "Error loading javamoney.properties, ignoring "
                                    + url, e);
                }
            }
        } catch (IOException e) {
            LOG.log(Level.SEVERE, "Error loading javamoney.properties.", e);
        }
    }

    private void updateConfig(Properties props) {
        for (Map.Entry<Object, Object> en : props.entrySet()) {
            String key = en.getKey().toString();
            String value = en.getValue().toString();
            int prio = 0;
            if (key.startsWith("{")) {
                int index = key.indexOf('}');
                if (index > 0) {
                    String prioString = key.substring(1, index);
                    try {
                        prio = Integer.parseInt(prioString);
                        key = key.substring(index + 1);
                    } catch (NumberFormatException e) {
                        LOG.warning("Invalid config key in javamoney.properties: " + key);
                    }
                }
            }
            Integer existingPrio = priorities.get(key);
            if (Objects.isNull(existingPrio)) {
                priorities.put(key, prio);
                config.put(key, value);
            } else if (existingPrio < prio) {
                priorities.put(key, prio);
                config.put(key, value);
            } else if (existingPrio == prio) {
                throw new IllegalStateException(
                        "AmbiguousConfiguration detected for '" + key + "'.");
            }
            // else ignore entry with lower prio!
        }
    }

    public static Map<String, String> getConfig() {
        return Collections.unmodifiableMap(INSTANCE.config);
    }

}

The updateConfig () method throws an exception. The MonetaryConfig constructor registers it. The problem arises because the row

Enumeration<URL> urls = getClass().getClassLoader().getResources(
                "javamoney.properties");

2 URL- , : "bundleresource://7.fwk302155142/javamoney.properties" "bundleresource://7.fwk302155142: 3/javamoney.properties".

.JAR, 1 , .

- . OSGI ( ). , , ( , ).

- OSGI, , ?

: My Manifest

Bundle-ClassPath: jars/moneta-1.0-RC3.jar,
 jars/money-api-1.0-RC3.jar,
 jars/javax.annotation-api-1.2.jar
+4
2

URL-:

bundleresource://7.fwk302155142/javamoney.properties
bundleresource://7.fwk302155142:3/javamoney.properties

, - Bundle-Classpath. :3 Bundle-Classpath. , Bundle-Classpath .

+4

, , . , :

<dependency>
    <groupId>org.javamoney</groupId>
    <artifactId>moneta</artifactId>
    <version>1.1</version>
</dependency>

:

<dependency>
    <groupId>org.javamoney.moneta</groupId>
    <artifactId>moneta-core</artifactId>
    <version>1.3</version>
</dependency>

Java 8.

0

All Articles