복붙노트

[SPRING] 봄에 jndi에 선언적으로 객체를 바인딩하는 법?

SPRING

봄에 jndi에 선언적으로 객체를 바인딩하는 법?

우리는 평범한 독립형 스프링 애플리케이션을 가지고 있으며 jdbc 데이터 소스를 jndi에 넣어야합니다. (우리는 jboss treecache를 사용하며 jndi에 있어야 데이터 소스가 필요합니다).

일부 인터넷 검색은 봄철에 모든 jndi-lookup 예제를 찾았습니다. 객체는 이미 jndi (tomcat 또는 응용 프로그램 서버 등)에 저장되어 있지만, 다른 방법이 필요합니다. 다른 서비스에 삽입하는 일반 데이터 소스 인 Spring bean이 있습니다. 하지만 jndi에서만 필요하므로 TreeCache에 삽입 할 수 없습니다.

bean으로 선언 될 수있는 org.springframework.jndi.JndiTemplate을 찾았습니다. 예 :

<bean id="fsJndiTemplate" class="org.springframework.jndi.JndiTemplate">
    <property name="environment">
        <props>
            <prop key="java.naming.factory.initial">com.sun.jndi.fscontext.RefFSContextFactory</prop>
            <prop key="java.naming.provider.url">file:///c:\windows\temp</prop>
        </props>
    </property>
</bean>

다른 자바 빈의 init-method로부터 fsJndiTemplate.bind (name, obj) 자바 코드 이외의 다른 방법으로 바인딩하는 방법을 찾지 못했습니다. 선언적으로 할 수있는 방법이 있습니까?

해결법

  1. ==============================

    1.JndiTemplate을 사용하여 오브젝트 맵을 이름으로 바인딩하는 JndiExporter를 작성할 수 있습니다.

    JndiTemplate을 사용하여 오브젝트 맵을 이름으로 바인딩하는 JndiExporter를 작성할 수 있습니다.

    <bean id="jndiExporter" class="org.xxx.JndiExporter">
        <property name="jndiTemplate" ref="jndiTemplate">
        <property name="objects">
              <map>
                <entry key="name1" value="bean1"/>
                <entry key="name2" value="bean2"/>
                <entry key="name3" value="bean3"/>
                <entry key="name4" value="bean4"/>
              </map>
        </property>
    </bean>
    

    JndiExporter는 삽입 된 BeanFactory로 스프링 빈을 검색하기 위해 BeanFactoryAware를 구현해야한다.

    이것은 가능한 한 가지 일 수 있습니다 :)

  2. ==============================

    2.질문에 감사드립니다. Treydone 솔루션의 변형을 작성하여 실제 코드를 사용하는 것이 유용 할 수 있다고 생각합니다 (꽤 짧습니다).

    질문에 감사드립니다. Treydone 솔루션의 변형을 작성하여 실제 코드를 사용하는 것이 유용 할 수 있다고 생각합니다 (꽤 짧습니다).

    public class JndiExporter implements InitializingBean {
    
        private final JndiTemplate template = new JndiTemplate();
    
        private Map<String, Object> jndiMapping = null;
    
        @Override
        public void afterPropertiesSet() throws Exception {
                for(Entry<String, Object> addToJndi: jndiMapping.entrySet()){
                        template.bind(addToJndi.getKey(), addToJndi.getValue());
                }
        }
    
        public void setJndiMapping(Map<String, Object> jndiMapping) {
                this.jndiMapping = jndiMapping;
        }
    
    }
    

    BeanFactoryAware 대신 InitializingBean을 구현했습니다. 이렇게하면 다음과 같은 구성이 가능합니다.

    <bean id="jndiExporter" class="com.ra.web.util.JndiExporter">
        <property name="jndiMapping">
            <map>
                <entry key="bean1" value-ref="other_spring_bean_id" />
                <entry key="bean2" value="literal_value" />
            </map>
        </property>
    </bean>
    
  3. ==============================

    3.나는 이것이 오래된 질문이라는 것을 알았지 만, 커스텀 코드없이 이것을 할 수있는 방법이있다. 상당히 자세한 내용이지만 100 % 선언적입니다.

    나는 이것이 오래된 질문이라는 것을 알았지 만, 커스텀 코드없이 이것을 할 수있는 방법이있다. 상당히 자세한 내용이지만 100 % 선언적입니다.

    <!-- inside container, use JndiTemplate -->
    <bean id="jndiBinder" class="org.springframework.jndi.JndiTemplate"/>
    <!-- outside container (e.g. for tests), use SimpleNamingContextBuilder -->
    <!-- <bean id="jndiBinder" class="org.springframework.mock.jndi.SimpleNamingContextBuilder" factory-method="emptyActivatedContextBuilder"/> -->
    
    <!-- use MethodInvokingFactoryBean to call 'bind' on 'jndiBinder' -->
    <bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
        <property name="targetObject" ref="jndiBinder"/>
        <property name="targetMethod" value="bind"/>
        <property name="arguments">
            <array>
                <value type="java.lang.String">java:comp/UserTransaction</value>
                <ref bean="atomikosUserTransaction"/>
            </array>
        </property>
    </bean>
    
    <!-- define as many bindings as you need -->
    <bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
        <property name="targetObject" ref="jndiBinder"/>
        <property name="targetMethod" value="bind"/>
        <property name="arguments">
            <array>
                <value type="java.lang.String">another/jndi/name</value>
                <value>literal_value</value>
            </array>
        </property>
    </bean>
    

    MethodInvokingFactoryBean은 또한 System 속성을 읽는 bean이 MethodInvokingFactoryBean에 의존하는 한 Atomikos를 사용할 때 시스템 속성 (예 : Atomikos를 사용할 때 편리함)을 설정하는 데 사용할 수 있습니다.

    <bean id="atomikosSystemProps" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
        <property name="targetObject">
            <bean class="java.lang.System" factory-method="getProperties"/>
        </property>
        <property name="targetMethod" value="putAll"/>
        <property name="arguments" ref="atomikosJtaProps"/>
    </bean>
    <bean id="atomikosJtaProps" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
        <property name="properties">
            <props>
                <prop key="com.atomikos.icatch.no_file">true</prop>
                <prop key="com.atomikos.icatch.hide_init_file_path">true</prop>
                <prop key="com.atomikos.icatch.service">com.atomikos.icatch.standalone.UserTransactionServiceFactory</prop>
                <prop key="com.atomikos.icatch.log_base_dir">/opt/txlogs</prop>
            </props>
        </property>
    </bean>
    <bean id="atomikosUserTransactionService" class="com.atomikos.icatch.config.UserTransactionServiceImp" init-method="init" destroy-method="shutdownForce" depends-on="atomikosSystemProps"/>
    
  4. ==============================

    4.안녕하세요    이 문제에 대한 표준 또는 모범 사례 유형 접근법은 없습니다. 당신은 자신의 접근 방식을 가지고 올 것입니다. 다음은 문제를 해결할 수있는 또 다른 접근법입니다.

    안녕하세요    이 문제에 대한 표준 또는 모범 사례 유형 접근법은 없습니다. 당신은 자신의 접근 방식을 가지고 올 것입니다. 다음은 문제를 해결할 수있는 또 다른 접근법입니다.

  5. ==============================

    5.코드가 Servlet 컨테이너 외부에서 실행되는 경우 (예 : 유닛 테스트에서 JNDI 컨텍스트를 에뮬레이션해야합니다. 그렇지 않으면 "환경에 클래스 이름을 지정해야합니다 ..."오류가 발생합니다.

    코드가 Servlet 컨테이너 외부에서 실행되는 경우 (예 : 유닛 테스트에서 JNDI 컨텍스트를 에뮬레이션해야합니다. 그렇지 않으면 "환경에 클래스 이름을 지정해야합니다 ..."오류가 발생합니다.

    JndiTemplate보다 SimpleNamingContextBuilder가 더 적합합니다.

    public class JndiExporter implements InitializingBean {
    
    private final SimpleNamingContextBuilder contextBuilder = new SimpleNamingContextBuilder();
    
    private Map<String, Object> jndiMapping = null;
    
    @Override
    public void afterPropertiesSet() throws Exception {
        for (Entry<String, Object> addToJndi : jndiMapping.entrySet()) {
            contextBuilder.bind(addToJndi.getKey(), addToJndi.getValue());
        }
    
        contextBuilder.activate();
    }
    
    public void setJndiMapping(Map<String, Object> jndiMapping) {
        this.jndiMapping = jndiMapping;
    }
    

    "contextBuilder.activate ();"를 간과하지 마십시오. 선.

  6. from https://stackoverflow.com/questions/5974779/how-to-putbind-object-to-jndi-in-spring-declaratively by cc-by-sa and MIT license