ThreadLocal с Tomcat - PullRequest
       7

ThreadLocal с Tomcat

0 голосов
/ 28 марта 2019

У меня есть класс контекста с переменной ThreadLocal, который я хочу использовать для хранения данных.
LDAPAttributesContextHolder

public class LDAPAttributesContextHolder {

    private static final ThreadLocal<List<Attributes>> threadLocalScope = new ThreadLocal<>();

    private LDAPAttributesContextHolder() {
        throw new IllegalStateException("ThreadLocal context class");
    }

    public static final List<Attributes> getAttributes() {
        return threadLocalScope.get();
    }

    public static final void setAttributes(List<Attributes> attributes) {
        threadLocalScope.set(attributes);
    }

    public static final void destroy() {
        threadLocalScope.remove();
    }
}

Я использую этот класс для хранения пользовательских атрибутов и использования его в другом сервисе.
Service1

@Override
    public boolean searchInLDAP(String userName, String email) {
        LOG.debug("Current thread is {}", Thread.currentThread().getName());
        LOG.debug("Start search user with login {} and email {} in LDAP directory", userName, email);
        List<Attributes> attributeList = new ArrayList<>();
        if(isEmpty(LDAPAttributesContextHolder.getAttributes())) {
            attributeList = ldapTemplate.search(query().base("ou=people").where("uid").is(userName).and("mail").is(email),
                    (AttributesMapper<Attributes>) attributes -> {
                        if(attributes == null) {
                            return null;
                        }
                        return attributes;
                    });
            LDAPAttributesContextHolder.setAttributes(attributeList);
        }
        LOG.debug("Status of searching user with login {} and email {} in LDAP is {}", userName, email, (!isEmpty(attributeList)) ? "success" : "failed");
        if(nonNull(attributeList) && !isEmpty(attributeList)) {
            logAttributes(userName);
        }
        return nonNull(attributeList) && !isEmpty(attributeList);
    }


Serivice2

public List<String> getAllFacultyGroupNamesByFacultyName() {
        String studentFacultyName = "";
        LOG.debug("Current thread is {}", Thread.currentThread().getName());
        LOG.debug("LDAPContextHolder size {}", LDAPAttributesContextHolder.getAttributes().size());
        List<Attributes> attributeList = LDAPAttributesContextHolder.getAttributes();
        LOG.debug("In method {} ,Size of attributes is  {}", Thread.currentThread().getStackTrace()[0].getMethodName(), attributeList.size());
        for(Attributes attributes : attributeList) {
            try {
                if(attributes.get(FACULTY_ATTRIBUTE) != null &&
                        attributes.get(ROLE_ATTRIBUTE) != null &&
                        !attributes.get(ROLE_ATTRIBUTE).get().toString().equals(ORGANIZATIONAL_PERSON)
                ) {
                    studentFacultyName = attributes.get(FACULTY_ATTRIBUTE).get().toString();
                    studentFacultyName = studentFacultyName.contains(IT_FACULTY.toLowerCase()) ? IT_FACULTY : studentFacultyName;
                    LOG.debug("Student faculty is {}", studentFacultyName);
                }
            } catch(NamingException e) {
                LOG.error("Error while parsing LDAP attributes. {}", e);
            }
        }

        return ...;
    }

Проблема в том, что в первом методе поток равен 120,но во-вторых, по какой-то причине поток равен 115, и когда я пытаюсь получить контекст, он выдает NullPointer.
Что я пропустил?

1 Ответ

0 голосов
/ 28 марта 2019

ThreadLocal содержит ссылку на поток . Таким образом, если он не инициализирован для каждого потока, вы получите исключения нулевого указателя. Из Javadoc:

Эти переменные отличаются от своих обычных аналогов тем, что каждый поток, который обращается к одному (с помощью своего метода get или set), имеет свою собственную, независимо инициализированную копию переменной.

Звучит так, будто вы хотите шаблон синглтона. Поскольку вы используете Spring Boot, вы можете создать bean-компонент типа LDAPAttributesContextHolder и автоматически связать его с компонентами / службами, где он используется.

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