Announcement Announcement Module
Collapse
No announcement yet.
Secure JMS and Spring with WebLogic Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Secure JMS and Spring with WebLogic

    There are a couple of threads which address the issues with Secure JMS and WebLogic. The understood resolution is to get the InitialContext for each QueueConnection (otherwise WebLogic will throw the dreaded security exception, access denied).

    See these two threads for reference:

    http://forum.springsource.org/showthread.php?t=62373

    http://jira.springframework.org/browse/SPR-4720

    The bug referenced above ends with the implementation of a flag "exposeAccessConext" but I am getting new error messages after using this flag. The exception is below:

    Cannot resolve reference to bean 'queueConnectionFactory' while setting bean prope
    rty 'connectionFactory'; nested exception is org.springframework.beans.factory.BeanCreationExce ption: Error creating bean with n
    ame 'queueConnectionFactory' defined in ServletContext resource [/WEB-INF/spring-config/infrastructure-config.xml]: Invocation o
    f init method failed; nested exception is java.lang.IllegalAccessError: class weblogic.jms.client.$Proxy235 cannot access its su
    perinterface weblogic.jms.client.Reconnectable.

    Here is my config:

    Code:
    <bean id="jndiTemplate" class="org.springframework.jndi.JndiTemplate">
    <property name="environment">
    <props>
    <prop key="java.naming.factory.initial">weblogic.jndi.WLInitialContextFactory</prop>
    <prop key="java.naming.provider.url">t3://myserver.com</prop>
    <prop key="java.naming.security.authentication">simple</prop>
    <prop key="java.naming.security.principal">jmsuser<prop>
    <prop key="java.naming.security.credentials">jmspassword</prop>
    </props>
    </property>
    </bean>
    
    <bean id="queueConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
    <property name="exposeAccessContext" value="true"/>
    <property name="jndiTemplate" ref="jndiTemplate" />
    <property name="jndiName" value="my/jms/QueueConnectionFactory" />
    </bean>
    
    <bean id="testJmsEventSender" class="troy.jms.EvenSender">
    <property name="jmsTemplate">
    <bean class="org.springframework.jms.core.JmsTemplate">
    <property name="defaultDestination" ref="testDestination" />
    <property name="connectionFactory" ref="queueConnectionFactory" />
    </bean>
    </property>
    </bean>
    
    Also, how can <jee:jndi-lookup> be used, I didn't think that lookup accepted the properties required to accept the credentials?
    Thanks!

  • #2
    I have the same problem

    I have the same problem ?

    Does anyone know a solution for this ?

    Comment


    • #3
      Where is the exception thrown? (stack trace would be helpfull)

      weblogic.jms.client.$Proxy235 looks alot like the dynamic proxy for
      weblogic.jms.client.Reconnectable.

      All this seems very familliar, have you seen this thread?
      http://forum.springsource.org/showthread.php?t=63338
      Last edited by honeybunny; Jan 25th, 2010, 08:35 AM. Reason: added reference

      Comment


      • #4
        What is the final solution after all reading messages from a secured jms queue (sprin

        Thx honeybunny

        The problem i faced is that i was unable to read (consume) messages from a secured queue.

        What i did was the solution you did with the Decorator but that one you also said in another post that it consumes a lot of resources and you wil use some ThreadLocal one based

        Did you do that ?

        What is the final solution after all reading messages from a secured jms queue (spring + weblogic 10.3) ?

        The SPR's are confusing related to this.(SPR-4720)

        Below is the stacktrace if i use

        Code:
        <property name="exposeAccessContext" value="true"/>
        Code:
        [ERROR] ContextLoader - Context initialization failed <org.springframework.beans
        .factory.BeanCreationException: Error creating bean with name 'connectionFactory
        ' defined in class path resource [applicationContext.xml]: Invocation of init me
        thod failed; nested exception is java.lang.IllegalAccessError: class weblogic.jm
        s.client.$Proxy105 cannot access its superinterface weblogic.jms.client.Reconnec
        table>org.springframework.beans.factory.BeanCreationException: Error creating be
        an with name 'connectionFactory' defined in class path resource [applicationCont
        ext.xml]: Invocation of init method failed; nested exception is java.lang.Illega
        lAccessError: class weblogic.jms.client.$Proxy105 cannot access its superinterfa
        ce weblogic.jms.client.Reconnectable
                at org.springframework.beans.factory.support.AbstractAutowireCapableBean
        Factory.initializeBean(AbstractAutowireCapableBeanFactory.java:1338)
                at org.springframework.beans.factory.support.AbstractAutowireCapableBean
        Factory.doCreateBean(AbstractAutowireCapableBeanFactory.java:473)
                at org.springframework.beans.factory.support.AbstractAutowireCapableBean
        Factory$1.run(AbstractAutowireCapableBeanFactory.java:409)
                at java.security.AccessController.doPrivileged(Native Method)
                at org.springframework.beans.factory.support.AbstractAutowireCapableBean
        Factory.createBean(AbstractAutowireCapableBeanFactory.java:380)
                at org.springframework.beans.factory.support.AbstractBeanFactory$1.getOb
        ject(AbstractBeanFactory.java:264)
                at org.springframework.beans.factory.support.DefaultSingletonBeanRegistr
        y.getSingleton(DefaultSingletonBeanRegistry.java:222)
                at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBe
        an(AbstractBeanFactory.java:261)
                at org.springframework.beans.factory.support.AbstractBeanFactory.getBean
        (AbstractBeanFactory.java:185)
                at org.springframework.beans.factory.support.AbstractBeanFactory.getBean
        (AbstractBeanFactory.java:164)
                at org.springframework.beans.factory.support.DefaultListableBeanFactory.
        preInstantiateSingletons(DefaultListableBeanFactory.java:423)
                at org.springframework.context.support.AbstractApplicationContext.finish
        BeanFactoryInitialization(AbstractApplicationContext.java:728)
                at org.springframework.context.support.AbstractApplicationContext.refres
        h(AbstractApplicationContext.java:380)
                at org.springframework.web.context.ContextLoader.createWebApplicationCon
        text(ContextLoader.java:255)
                at org.springframework.web.context.ContextLoader.initWebApplicationConte
        xt(ContextLoader.java:199)
                at org.springframework.web.context.ContextLoaderListener.contextInitiali
        zed(ContextLoaderListener.java:45)
                at weblogic.servlet.internal.EventsManager$FireContextListenerAction.run
        (EventsManager.java:458)
                at weblogic.security.acl.internal.AuthenticatedSubject.doAs(Authenticate
        dSubject.java:321)
                at weblogic.security.service.SecurityManager.runAs(Unknown Source)
                at weblogic.servlet.internal.EventsManager.notifyContextCreatedEvent(Eve
        ntsManager.java:168)
                at weblogic.servlet.internal.WebAppServletContext.preloadResources(WebAp
        pServletContext.java:1744)
                at weblogic.servlet.internal.WebAppServletContext.start(WebAppServletCon
        text.java:2909)
                at weblogic.servlet.internal.WebAppModule.startContexts(WebAppModule.jav
        a:973)
                at weblogic.servlet.internal.WebAppModule.start(WebAppModule.java:361)
                at weblogic.application.internal.flow.ModuleStateDriver$3.next(ModuleSta
        teDriver.java:204)
                at weblogic.application.utils.StateMachineDriver.nextState(StateMachineD
        river.java:26)
                at weblogic.application.internal.flow.ModuleStateDriver.start(ModuleStat
        eDriver.java:60)
                at weblogic.application.internal.flow.ScopedModuleDriver.start(ScopedMod
        uleDriver.java:200)
                at weblogic.application.internal.flow.ModuleListenerInvoker.start(Module
        ListenerInvoker.java:117)
                at weblogic.application.internal.flow.ModuleStateDriver$3.next(ModuleSta
        teDriver.java:204)
                at weblogic.application.utils.StateMachineDriver.nextState(StateMachineD
        river.java:26)
                at weblogic.application.internal.flow.ModuleStateDriver.start(ModuleStat
        eDriver.java:60)
                at weblogic.application.internal.flow.StartModulesFlow.activate(StartMod
        ulesFlow.java:27)
                at weblogic.application.internal.BaseDeployment$2.next(BaseDeployment.ja
        va:635)
                at weblogic.application.utils.StateMachineDriver.nextState(StateMachineD
        river.java:26)
                at weblogic.application.internal.BaseDeployment.activate(BaseDeployment.
        java:212)
                at weblogic.application.internal.DeploymentStateChecker.activate(Deploym
        entStateChecker.java:154)
                at weblogic.deploy.internal.targetserver.AppContainerInvoker.activate(Ap
        pContainerInvoker.java:80)
                at weblogic.deploy.internal.targetserver.operations.AbstractOperation.ac
        tivate(AbstractOperation.java:566)
                at weblogic.deploy.internal.targetserver.operations.ActivateOperation.ac
        tivateDeployment(ActivateOperation.java:136)
                at weblogic.deploy.internal.targetserver.operations.ActivateOperation.do
        Commit(ActivateOperation.java:104)
                at weblogic.deploy.internal.targetserver.operations.AbstractOperation.co
        mmit(AbstractOperation.java:320)
                at weblogic.deploy.internal.targetserver.DeploymentManager.handleDeploym
        entCommit(DeploymentManager.java:816)
                at weblogic.deploy.internal.targetserver.DeploymentManager.activateDeplo
        ymentList(DeploymentManager.java:1223)
                at weblogic.deploy.internal.targetserver.DeploymentManager.handleCommit(
        DeploymentManager.java:434)
                at weblogic.deploy.internal.targetserver.DeploymentServiceDispatcher.com
        mit(DeploymentServiceDispatcher.java:161)
                at weblogic.deploy.service.internal.targetserver.DeploymentReceiverCallb
        ackDeliverer.doCommitCallback(DeploymentReceiverCallbackDeliverer.java:181)
                at weblogic.deploy.service.internal.targetserver.DeploymentReceiverCallb
        ackDeliverer.access$100(DeploymentReceiverCallbackDeliverer.java:12)
                at weblogic.deploy.service.internal.targetserver.DeploymentReceiverCallb
        ackDeliverer$2.run(DeploymentReceiverCallbackDeliverer.java:67)
                at weblogic.work.SelfTuningWorkManagerImpl$WorkAdapterImpl.run(SelfTunin
        gWorkManagerImpl.java:464)
                at weblogic.work.ExecuteThread.execute(ExecuteThread.java:200)
                at weblogic.work.ExecuteThread.run(ExecuteThread.java:172)
        Caused by: java.lang.IllegalAccessError: class weblogic.jms.client.$Proxy105 can
        not access its superinterface weblogic.jms.client.Reconnectable
                at java.lang.reflect.Proxy.defineClass0(Native Method)
                at java.lang.reflect.Proxy.getProxyClass(Proxy.java:504)
                at java.lang.reflect.Proxy.newProxyInstance(Proxy.java:581)
                at org.springframework.aop.framework.JdkDynamicAopProxy.getProxy(JdkDyna
        micAopProxy.java:117)
                at org.springframework.aop.framework.ProxyFactory.getProxy(ProxyFactory.
        java:110)
                at org.springframework.jndi.JndiObjectFactoryBean$JndiObjectProxyFactory
        .createJndiObjectProxy(JndiObjectFactoryBean.java:303)
                at org.springframework.jndi.JndiObjectFactoryBean$JndiObjectProxyFactory
        .access$000(JndiObjectFactoryBean.java:273)
                at org.springframework.jndi.JndiObjectFactoryBean.afterPropertiesSet(Jnd
        iObjectFactoryBean.java:176)
                at org.springframework.beans.factory.support.AbstractAutowireCapableBean
        Factory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1369)
                at org.springframework.beans.factory.support.AbstractAutowireCapableBean
        Factory.initializeBean(AbstractAutowireCapableBeanFactory.java:1335)
                ... 51 more
        Thx for any help.

        Comment


        • #5
          The problem i faced is that i was unable to read (consume) messages from a secured queue.
          In my case I put the same security on the ConnectionFactory that I did on all of my queues. If you have the security on the queue alone, you _probably_ need to perform a JNDI lookup for the queue in each thread; perhaps you could decorate DestinationResolver -- just a guess though.

          What i did was the solution you did with the Decorator but that one you also said in another post that it consumes a lot of resources and you wil use some ThreadLocal one based. Did you do that ?
          Yes, and it worked. I maintained a ThreadLocal for every thread that called my JMS helper. That way I only looked it up when needed.
          This solution is kind of poor, since it ends up populating every thread with the lookup credentials, and does not ever remove them. If you are only using the JMS queue from within the threads that spring's DefaultMessageListener container creates, then its not much concern. I'm not sure what would happen (security wise) with this approach if you were somehow able to hookup the DefaultMessageListenerContainer to a "app-server provided" thread pool or task manager.

          What is the final solution after all reading messages from a secured jms queue (spring + weblogic 10.3) ?
          The SPR's are confusing related to this.(SPR-4720)
          Totally!, I really think that managed security for JMS on weblogic is intended to be used only in the EJB model (from MDB not MDP). I got it to work using the above approach, but it was a mess; and we have since switched to using ActiveMQ directly -- it was only thing we could get to work reliably (across different web containers). That said, weblogic's JMS seemed to offer the best support for writing standalone clients in terms of security consistency.

          Code:
          public class WeblogicJMSHelper implements JMSHelper, ConnectionFactory, DestinationResolver, InitializingBean {
          	private final ThreadLocal<Boolean> m_jndiLookupPerformed = new ThreadLocal<Boolean>();
          
          	/**
          	 * ConnectionFactory interface
          	 */
          	public Connection createConnection() throws JMSException {
          		s_logger.info("createConnection(): " + Thread.currentThread().getName());
          		refreshCredentialsAndLookup();
          		return m_connectionFactory.createConnection();
          	}
          
          	private boolean wasLookupPerformed() {
          		Boolean b = m_jndiLookupPerformed.get();
          		if (b == null) return false;
          		return b.booleanValue();
          	}
          ...
          	private void refreshCredentialsAndLookup() throws JMSException {
          		JMSException jmsException = null;
          		if (!wasLookupPerformed()) {
          			ConnectionFactory factory = null;
          			
          			try {
          				// try to do a lookup in JNDI
          				factory = getConnectionFactory();
          			}
          			catch (JMSException ex) {
          				// log the error
          				s_logger.error("JNDI lookup of connection factory failed for thread:" + Thread.currentThread().getName(), ex);
          				if (ex.getLinkedException() != null) {
          					s_logger.error("linked exception is:", ex.getLinkedException());
          				}
          				
          				// store the reference so we can throw it later, if this is the first call
          				jmsException = ex;
          			}
          			
          			synchronized (m_lookupGaurd) {
          				// only keep one reference, not sure if jndi returns  
          				// the same object or a different one, but one CF should
          				// be sufficient
          				if (m_connectionFactory == null) {
          					if (factory != null) {
          						// set the shared reference
          						m_connectionFactory = factory;
          						
          						m_jndiLookupPerformed.set(Boolean.TRUE);
          					}
          					else {
          						// throw the exception since otherwise we get an NPE later on
          						JMSException jmsex = new JMSException("initial JNDI lookup of connection factory failed");
          						jmsex.setLinkedException(jmsException);
          						throw jmsex;
          					}
          				}
          			}
          		}
          	}
          ...
          }
          Last edited by honeybunny; Jan 25th, 2010, 10:22 AM.

          Comment


          • #6
            Thank you so much !

            Thx you for the detailed response !!!

            Comment


            • #7
              Originally posted by honeybunny View Post
              In my case I put the same security on the ConnectionFactory that I did on all of my queues. If you have the security on the queue alone, you _probably_ need to perform a JNDI lookup for the queue in each thread; perhaps you could decorate DestinationResolver -- just a guess though.
              Now that i re read your post:

              Yes i have a queue only and security is on the queue alone.

              To understand better ...why is this cae different then yours ?

              and how can i achive this using DestinationResolver

              Thx again.

              Comment


              • #8
                In my case the security was on the connection factory, so in order to use it to create the connection -- I needed to do the JNDI lookup in the thread where I was creating the connection (and the one where I was using it).

                You might try doing a JNDI lookup in each thread where you need the Destination.

                Comment


                • #9
                  Code:
                  <bean id="jndiTemplate"
                  		class="org.springframework.jndi.JndiTemplate">
                  		<property name="environment">
                  			<props>
                  				<prop key="java.naming.factory.initial">
                  					weblogic.jndi.WLInitialContextFactory
                  				</prop>
                  				<prop key="java.naming.provider.url">
                  					t3://localhost:7001
                  				</prop>
                  				<prop key="java.naming.security.principal">
                  					username
                  				</prop>
                  				<prop key="java.naming.security.credentials">
                  					password
                  				</prop>
                  			</props>
                  		</property>
                  	</bean>
                  
                  <bean id="connectionFactory"
                  		class="org.springframework.jndi.JndiObjectFactoryBean">
                  		<property name="jndiTemplate">
                  			<ref bean="jndiTemplate" />
                  		</property>
                  		<property name="jndiName">
                  			<value>MyConnectionFactory</value>
                  		</property>
                  	</bean>
                  
                  	<bean id="queue"
                  		class="org.springframework.jndi.JndiObjectFactoryBean">
                  		<property name="jndiTemplate">
                  			<ref bean="jndiTemplate" />
                  		</property>
                  		<property name="jndiName">
                  			<value>MyQueue</value>
                  		</property>
                  
                  	</bean>
                  
                  	<bean id="listenerContainer"
                  		class="org.springframework.jms.listener.DefaultMessageListenerContainer">
                  		<property name="concurrentConsumers" value="5" />
                  		<property name="connectionFactory" ref="connectionFactory" />
                  		<property name="destination" ref="queue" />
                  		<property name="messageListener" ref="notificationListener" />
                  		<property name="sessionTransacted" value="true" />
                  
                  	</bean>
                  So this is the configuration i use

                  Security in weblogic is done on queue level

                  How can i use Destination and DestinationResolver ?

                  Thx for patience

                  Comment


                  • #10
                    I thought about it a bit and I am doubting that DestinationResolver would work since I think these may be cached. Decorating (Subclassing and modifying the connection factory) works with ConnectionFactory because you can arrange things so the CF is called once per listener container thread.

                    I think you might want to try undoing the 'exposeAccessContext' thing. I think that might be causing your exception -- its exposing something which is a dynamic proxy (instead of a specific subclass).

                    Code:
                    <bean id="connectionFactory"
                    		class="com.myclass.WeblogicJMSHelper"> <!-- from above sample -->
                    		<property name="jndiTemplate">
                    			<ref bean="jndiTemplate" />
                    		</property>
                    		<property name="jndiName">
                    			<value>MyConnectionFactory</value>
                    		</property>
                    	</bean>
                    
                    	<bean id="queue"
                    		class="org.springframework.jndi.JndiObjectFactoryBean">
                    		<property name="jndiTemplate">
                    			<ref bean="jndiTemplate" />
                    		</property>
                    		<property name="jndiName">
                    			<value>MyQueue</value>
                    		</property>
                    
                    	</bean>
                    
                    	<bean id="listenerContainer"
                    		class="org.springframework.jms.listener.DefaultMessageListenerContainer">
                    		<property name="concurrentConsumers" value="1" />
                    		<property name="connectionFactory" ref="connectionFactory" />
                    		<property name="destination" ref="queue" />
                    		<property name="messageListener" ref="notificationListener" />
                    		<property name="sessionTransacted" value="true" />
                    
                    	</bean>
                    Last edited by honeybunny; Jan 26th, 2010, 10:00 AM.

                    Comment

                    Working...
                    X