System.setProperty, используемый потоком, влияет на другой поток при взаимодействии с внешними сетевыми элементами. Как это решить? - PullRequest
3 голосов
/ 06 марта 2012

В моем приложении у меня есть две темы. Каждый поток связывается с различными внешними объектами.

Допустим, T1 -> N1 & T2 -> N2 (T1 и T2 - два потока. N1 и N2 - внешние объекты. Связь - это SOAP через HTTPS.)

Производитель N1 попросил использовать файл хранилища ключей UPCC_client.store для аутентификации, и для этого мы использовали следующий код,

System.setProperty("javax.net.ssl.keyStore", "<file path>");
System.setProperty("javax.net.ssl.keyStorePassword", "<password>");
System.setProperty("javax.net.ssl.trustStore","<file path>");
System.setProperty("javax.net.ssl.trustStorePassword", "<password>");

Приложение было перезапущено с вышеуказанными свойствами, установленными в потоке T1, без проблем. У T2 начались проблемы, так как свойства, установленные T1, используются T2. Основной причиной этого является System.setProperty - область применения JVM. Как решить эту проблему?

Ответы [ 3 ]

16 голосов
/ 06 марта 2012

Я подозреваю, что у вас есть проблема дизайна, чтобы выполнить это требование.

Единственный способ обойти это, я могу придумать, это сделать ваши свойства ThreadLocal.

public class ThreadLocalProperties extends Properties {
    private final ThreadLocal<Properties> localProperties = new ThreadLocal<Properties>() {
        @Override
        protected Properties initialValue() {
            return new Properties();
        }
    };

    public ThreadLocalProperties(Properties properties) {
        super(properties);
    }

    @Override
    public String getProperty(String key) {
        String localValue = localProperties.get().getProperty(key);
        return localValue == null ? super.getProperty(key) : localValue;
    }

    @Override
    public Object setProperty(String key, String value) {
        return localProperties.get().setProperty(key, value);
    }
}

// Make the properties thread local from here. This to be done globally once.
System.setProperties(new ThreadLocalProperties(System.getProperties()));

// in each thread.
System.setProperty("javax.net.ssl.keyStore", "my-key-store");

Если не возникает путаницы, System.setProperties () не просто устанавливает свойства, она заменяет коллекцию и ее реализацию.

// From java.lang.System
 * The argument becomes the current set of system properties for use
 * by the {@link #getProperty(String)} method.

public static void setProperties(Properties props) {
    SecurityManager sm = getSecurityManager();
    if (sm != null) {
        sm.checkPropertiesAccess();
    }
    if (props == null) {
        props = new Properties();
        initProperties(props);
    }
    System.props = props;
}

ИспользуяВ этом методе поведение Системных свойств меняет на локальный поток для вызовов setProperty () и getProperty ()

3 голосов
/ 17 мая 2013

Я прибыл сюда в поисках решения для установки системных свойств для потока. Я использовал превосходный пример @Peter Lawrey, приведенный выше, и это было как раз то, что мне было нужно, с одним исключением - мой код должен был выполняться внутри контейнера сервлета (Tomcat), и поэтому я был обязан быть хорошим гражданином и не изменять ожидаемого поведения setProperty () для любого другого веб-приложения, работающего в том же экземпляре JVM. Чтобы решить эту проблему, я переименовал метод Питера setProperty() в setLocalProperty():

    public Object setThreadLocalProperty(String key, String value) {
        return localProperties.get().setProperty(key, value);
    }

С этим одним изменением результат состоит в том, что вызов setProperty () изменит свойство глобально - что будет желательным поведением для других потоков в JVM. Чтобы изменить свойство только для локального потока, вместо этого вызывается setThreadLocalProperty().

Таким образом, если у вас есть полный контроль над экземпляром приложения, код Питера должен работать для вас отлично. Однако, если ваше приложение живет в общей JVM - или если у вас есть необходимость иначе «наслоить» системные свойства на глобальные и локальные потоки, то одна модификация выше должна работать для вас.

0 голосов
/ 06 марта 2012

Существуют программные способы настройки хранилища ключей и хранилища доверенных сертификатов, см. Справочное руководство JSSE , но почему, по вашему мнению, вам вообще нужны разные хранилища ключей и хранилища доверенных сертификатов? Склад доверенных сертификатов - это список всех ЦС, которым вы доверяете: действительно ли они отличаются в разных контекстах; а хранилище ключей - это ваша личность: действительно ли они отличаются в разных контекстах? и если да, то почему?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...