Как перечислить свойства источника данных JBoss AS 7 в коде Java? - PullRequest
3 голосов
/ 14 марта 2012

Я использую JBoss AS 7.1.0.CR1b. У меня есть несколько источников данных, определенных в моем standalone.xml, например

        <subsystem xmlns="urn:jboss:domain:datasources:1.0">
            <datasources>
                <datasource jndi-name="java:/MyDS" pool-name="MyDS_Pool" enabled="true" use-java-context="true" use-ccm="true">
                    <connection-url>some-url</connection-url>
                    <driver>the-driver</driver>
                    [etc]

Все отлично работает.

Я пытаюсь получить доступ к информации, содержащейся в моем коде, в частности к свойствам connection-url и driver.

Я пытался получить источник данных из JNDI, как обычно, но, похоже, он не предоставляет доступ к этим свойствам:

// catches removed
InitialContext context;
DataSource dataSource = null;
context = new InitialContext();
dataSource = (DataSource) context.lookup(jndi);

ClientInfo и DatabaseMetadata из объекта Connection из этого источника данных также не содержат таких гранулярных свойств JBoss.

Мой код будет работать внутри контейнера с указанным источником данных, поэтому все должно быть доступно. Я посмотрел на интерфейс IronJacamar org.jboss.jca.common.api.metadata.ds.DataSource и его реализующий класс, и у них, кажется, есть доступные перехватчики необходимой мне информации, но я не могу найти информацию о том, как создавать такие объекты с этими уже развернутыми ресурсами в контейнер (только конструктор в impl включает в себя ввод всех свойств вручную).

Интерфейс командной строки JBoss AS 7 позволяет вам перемещаться и перечислять источники данных как систему каталогов. http://www.paykin.info/java/add-datasource-programaticaly-cli-jboss-7/ предоставляет отличный пост о том, как использовать то, что я считаю API управления Java, для взаимодействия с подсистемой, но, похоже, это связано с подключением к целевому серверу JBoss. Мой код уже работает на этом сервере, поэтому наверняка должен быть более простой способ сделать это?

Надеюсь, кто-нибудь может помочь. Большое спасибо.

1 Ответ

5 голосов
/ 14 марта 2012

То, что вы действительно пытаетесь сделать, - это управленческое действие. Лучший способ - использовать доступные API управления.

Вот простой автономный пример:

public class Main {

    public static void main(final String[] args) throws Exception {
        final List<ModelNode> dataSources = getDataSources();
        for (ModelNode dataSource : dataSources) {
            System.out.printf("Datasource: %s%n", dataSource.asString());
        }
    }

    public static List<ModelNode> getDataSources() throws IOException {
        final ModelNode request = new ModelNode();
        request.get(ClientConstants.OP).set("read-resource");
        request.get("recursive").set(true);
        request.get(ClientConstants.OP_ADDR).add("subsystem", "datasources");
        ModelControllerClient client = null;
        try {
            client = ModelControllerClient.Factory.create(InetAddress.getByName("127.0.0.1"), 9999);
            final ModelNode response = client.execute(new OperationBuilder(request).build());
            reportFailure(response);
            return response.get(ClientConstants.RESULT).get("data-source").asList();
        } finally {
            safeClose(client);
        }
    }

    public static void safeClose(final Closeable closeable) {
        if (closeable != null) try {
            closeable.close();
        } catch (Exception e) {
            // no-op
        }
    }


    private static void reportFailure(final ModelNode node) {
        if (!node.get(ClientConstants.OUTCOME).asString().equals(ClientConstants.SUCCESS)) {
            final String msg;
            if (node.hasDefined(ClientConstants.FAILURE_DESCRIPTION)) {
                if (node.hasDefined(ClientConstants.OP)) {
                    msg = String.format("Operation '%s' at address '%s' failed: %s", node.get(ClientConstants.OP), node.get(ClientConstants.OP_ADDR), node.get(ClientConstants.FAILURE_DESCRIPTION));
                } else {
                    msg = String.format("Operation failed: %s", node.get(ClientConstants.FAILURE_DESCRIPTION));
                }
            } else {
                msg = String.format("Operation failed: %s", node);
            }
            throw new RuntimeException(msg);
        }
    }
}

Единственный другой способ, который я могу придумать, - это добавить модуль, который опирается на внутренние компоненты сервера. Это можно сделать, но я бы сначала использовал API управления.

...