Announcement Announcement Module
Collapse
No announcement yet.
Cant retrieve Bean by it's id via BeanFactory Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Cant retrieve Bean by it's id via BeanFactory

    Hi,

    I am registering Bean manually to the container this way:

    Code:
    public class AppContextExtendingBean implements ApplicationContextAware{
    
    
        @Override
        public void setApplicationContext(ApplicationContext applicationContext) throws BeansException{
    
            AutowireCapableBeanFactory beanFactory = applicationContext.getAutowireCapableBeanFactory();
    
    
       
            addBean(beanFactory);
    
        }
    
        // create the object manually and then inject it into the spring context
        private void addBean(AutowireCapableBeanFactory beanFactory){
            MyObject myObject=new MyObject("foo","phleem");
            myObject.setBar("baz");
            beanFactory.autowireBean(myObject);
            beanFactory.initializeBean(myObject, "bean2");
        }

    Now this bean is alive and working.

    Now i am trying to destroy this bean manuall this way:

    Code:
    AbstractBeanFactory factory = (AbstractBeanFactory) beanFactory;
    			factory.destroyScopedBean("bean2");
    and I get this error



    Code:
    org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'bean2' is defined
    	at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:529)
    	at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1095)
    	at org.springframework.beans.factory.support.AbstractBeanFactory.destroyScopedBean(AbstractBeanFactory.java:977)
    	at com.fixgw.sessions.SessionFactory.removeSessionByIntSessionId(SessionFactory.java:107)
    	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    	at java.lang.reflect.Method.invoke(Unknown Source)
    	at sun.reflect.misc.Trampoline.invoke(Unknown Source)
    	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    	at java.lang.reflect.Method.invoke(Unknown Source)
    	at sun.reflect.misc.MethodUtil.invoke(Unknown Source)
    	at javax.management.modelmbean.RequiredModelMBean.invokeMethod(Unknown Source)
    	at javax.management.modelmbean.RequiredModelMBean.invoke(Unknown Source)
    	at org.springframework.jmx.export.SpringModelMBean.invoke(SpringModelMBean.java:90)
    	at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(Unknown Source)
    	at com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(Unknown Source)
    	at mx4j.tools.adaptor.http.InvokeOperationCommandProcessor.executeRequest(InvokeOperationCommandProcessor.java:164)
    	at mx4j.tools.adaptor.http.HttpAdaptor$HttpClient.run(HttpAdaptor.java:980)

    Why the container doesn't find bean with name bean2?

    thanks,
    ray.

  • #2
    Because it isn't in control of the bean. For bean desctruction it needs to know what to do, this is retrieved from the BeanDefinition and as you are in control of that bean that isn't available...

    Comment


    • #3
      Could you provider another solution how could I destroy that bean programmaticly?

      or how should I add it manually in first place in a way I could "put my hands on it" in a later stage?

      thanks.

      Comment


      • #4
        I have just one question why? Why do you want a bean instance you create to be managed by spring?! I don't get that, what is your usecase...

        Comment


        • #5
          Okie Ill tell you why.

          I have topic.

          this topic has subscribers.

          now those subscribers will be registered to this topic on the fly.

          The same goes for un-registration.

          I want each subscriber to be a spring bean coz I want it to be managed by the container and have all services on it(AOP, auto wiring, etc..) as long as it's subscribed. when it's destroyed I want it to be off the container.

          so I found a way to register subscribers dynamiclly but cant unregister(destroy) them on demand (as you already know)

          any other soltuion to my usecase will be acceptable !!

          this is how a subscriber looks like:


          Code:
          public class Subscriber implements MessageListener
          																											
          {
          	protected FixSessionDTO fixSessionDTO;
          
          
          	protected static Logger log = Logger.getLogger(AbstractSessionBean.class);;
          
          
          
          
          	@Autowired
          	ConnectionFactory connectionFactory;
          
          
          
          
          	DefaultMessageListenerContainer messageListeners;
          
          
          
          
          	private Topic topicDestination;
          
          
          
          
          	public Topic getTopicDestination()
          	{
          		return topicDestination;
          	}
          
          
          
          
          	public void setTopicDestination(Topic topicDestination)
          	{
          		this.topicDestination = topicDestination;
          	}
          
          
          	public Subscriber (FixSessionDTO fixSessionDTO, Topic topicDestination)
          	{
          		super();
          		this.fixSessionDTO = fixSessionDTO;
          		this.topicDestination = topicDestination;
          	}
          
          
          	public FixSessionDTO getFixSessionDTO()
          	{
          		return fixSessionDTO;
          	}
          
          
          
          
          	public void setFixSessionDTO(FixSessionDTO fixSessionDTO)
          	{
          		this.fixSessionDTO = fixSessionDTO;
          	}
          
          
          
          
          	@PostConstruct
          	public void init()
          	{
          
          
          
          
          		try
          		{
          			System.out.println("AbstractSessionBean.init()." + fixSessionDTO.toString());
          			messageListeners = new DefaultMessageListenerContainer();
          			CachingConnectionFactory cacheFactory = new CachingConnectionFactory();
          			cacheFactory.setTargetConnectionFactory(connectionFactory);
          			cacheFactory.setReconnectOnException(true);
          			cacheFactory.setExceptionListener(new ExceptionListener()
          			{
          
          
          
          
          				public void onException(JMSException e)
          				{
          					log.error("Error", e);
          				}
          			});
          			cacheFactory.setSessionCacheSize(1);
          
          
          
          
          			messageListeners.setConnectionFactory(connectionFactory);
          			messageListeners.setDestinationName(topicDestination.getTopicName());
          			messageListeners.setMaxConcurrentConsumers(1);
          			messageListeners.setSessionAcknowledgeModeName("AUTO_ACKNOWLEDGE");
          			messageListeners.setMessageListener(this);
          			messageListeners.setPubSubDomain(true);
          			messageListeners.setAcceptMessagesWhileStopping(false);
          			messageListeners.setConcurrentConsumers(1);
          			messageListeners.setSessionTransacted(false);
          			messageListeners.setReceiveTimeout(1000);
          			messageListeners.setMaxMessagesPerTask(300);
          			messageListeners.initialize();
          			messageListeners.start();
          
          
          
          
          		}
          		catch (Exception e)
          		{
          			e.printStackTrace();
          		}
          	}
          
          
                 @Override
          	public void onMessage(Message message)
          	{
          		
          	  // do something with the msg
          	}
          
          
          
          
          
          	@PreDestroy
          	public void destroy()
          	{
          		try
          		{
          			log.debug("Destroying MDB. details=" + fixSessionDTO.toString());
          			if (messageListeners != null)
          			{
          				messageListeners.stop();
          				messageListeners.shutdown();
          				messageListeners.destroy();
          			}
          		}
          		catch (Exception e)
          		{
          			log.error("Couldnt destroy MDB. details=" + fixSessionDTO.toString(), e);
          		}
          
          
          
          
          	}
          
          	public void stop()
          	{
          		messageListeners.stop();
          	}
          
          
          
          
          	public void start()
          	{
          		messageListeners.start();
          	}
          }

          connectionFactory being wired from the configuration file. but the property class FixSessionDTO I must set on the subscriber on the fly also.


          ray
          Last edited by ray.frid; Jul 16th, 2012, 05:21 AM.

          Comment


          • #6
            The only thing you get is autowiring and that is something you can do without registering your bean as a spring bean. However I would probably use Spring Integration that gives an easy way to (un)subscribe to channels.

            Code:
            private SubscribableChannel channel;
            
            public void subscribe() {
            
              MessageHandler handler = new MessageHandler();
              channel.subscribe(handler);
            
            }
            
            public void unsubscribe() {
            
             channel.unsubscribe(handler);
            }

            Comment


            • #7
              I guess now that I miss lots of information.

              So you saying I should download the Spring integration libs(which contains the SubscribableChannel class)

              and each listener of mine suppose to implement that SubscribableChannel. in this way Ill be able to send a message to each spring bean a message like stop,start etc.. but still how will I dispose those "channels" from the container bean when I wont need to use them anymore? (thanks for your patience)

              ray.

              Comment


              • #8
                No.. You need a MessageHandler not a channel!!! Also you shouldn't make it a container managed bean but control it yourself (you are also constructing it yourself!) you can still do autowiring if you need (you could even make it a prototype scoped bean to let the container act as a factory for your bean). After unsubscribing it and programmed correctly it will be garbage collected.

                No need to make things more complex as needed...

                Comment


                • #9
                  A bit more patience and I am getting there.. was struggling with this for days now.


                  1. So if you think I shouldnt make it as a container managed bean. why do I need the MessageHandler for?

                  I am thinking about having a hashmap table which will hold all my pojos.

                  and if for example I need to "speak" with some pojo I will just retrive it from the hashmap and execute a method.

                  2. Could you please detail this: (you could even make it a prototype scoped bean to let the container act as a factory for your bean)



                  thanks.

                  Comment


                  • #10
                    1. So if you think I shouldnt make it as a container managed bean. why do I need the MessageHandler for?
                    You need something that handles the message doesn't it?! Nothing/thin air//dev/null/ cannot handle a message. You need an object to handle the message. But not the whole world has to be managed by the spring container! As mentioned yuo can still have the dependencies injected without making it a container managed bean (I suggest a read of the javadoc for the ApplicationContext/BeanFactory.

                    2. Could you please detail this: (you could even make it a prototype scoped bean to let the container act as a factory for your bean)
                    I suggest a read of the reference guide on scopes. You can simply add it to your applicationcontext and when you need an instance call getBean("your-id) to get a fresh instance which is then under your control (saves you the step of calling autowire on the BeanFactory and you can get more leverage of the Spring AOP stuff).

                    I suggest you learn the framework and how it can help you instead of trying to hammer your solution in/around the framework (like the Map idea ).

                    Comment


                    • #11
                      Gotcha.

                      (heh love your sarcasm comments)

                      your second point is nice. I can use the container to create for me beans. and If I remember right prototype beans can be dispose by me(I mean they must be disposed by me the container wont dispose them)

                      BUT how will I retrieve specific instances of running-prototype beans form the container in order to dispose them? I know I shouldnt use getBean.. it's a memory killer.

                      Comment


                      • #12
                        You should hold on to that bean somewhere in memory (it BeanFactory doesn't know it!) and after you unsubscribe from the channel it isn't referenced anymore and as such will eventually be GC'ed. How and where depends on your creation/destroy logic (is it a button press, tied to the session etc.).

                        Comment


                        • #13
                          Ok I have process your posts over and over here and I just need your blessing.

                          I have rid of the Singletons and now I am creating dynamiclly/programaticlly prototype beans using application context this way:

                          Code:
                                                        FixSessionDTO fixSessionDTO = new FixSessionDTO();
                          				fixSessionDTO.setInetrnalSessionId(internalSessionId);
                                                         SessionMDB sessionMDB = (SessionMDB) context.getBean("sessionMDB");
                          
                          				sessionMDB.setFixSessionDTO(fixSessionDTO);
                          				sessionMDB.setTopicDestination(topicDestination);
                          				sessionMDB.init();




                          now SessionMdb looks like this:

                          @Scope(value="prototype")
                          @Component("sessionMDB")
                          public class SessionMDB extends AbstractSessionBean
                          {

                          private SubscribableChannel channel;

                          public SessionMDB(FixSessionDTO fixSessionDTO, Topic topicDestination)
                          {
                          super(fixSessionDTO, topicDestination);
                          }



                          public SessionMDB()
                          {
                          super();
                          // TODO Auto-generated constructor stub
                          }



                          private final static Logger log = Logger.getLogger(SessionMDB.class);

                          @Override
                          public void onMessage(Message message)
                          {

                          }
                          }


                          Code:
                          @ManagedResource
                          public abstract class AbstractSessionBean implements MessageListener//, AbstractSessionBeanManagedOperations// 																											
                          {
                          
                          	protected FixSessionDTO fixSessionDTO;
                          	
                          	protected static Logger log = Logger.getLogger(AbstractSessionBean.class);;
                          
                          	@Autowired
                          	ConnectionFactory connectionFactory;
                          
                          	DefaultMessageListenerContainer messageListeners;
                          
                          	private Topic topicDestination;
                          
                          	public Topic getTopicDestination()
                          	{
                          		return topicDestination;
                          	}
                          	
                          	
                          	
                          
                          	public AbstractSessionBean()
                          	{
                          		super();
                          		// TODO Auto-generated constructor stub
                          	}
                          
                          
                          
                          
                          	public void setTopicDestination(Topic topicDestination)
                          	{
                          		this.topicDestination = topicDestination;
                          	}
                          
                          	
                          	public AbstractSessionBean(FixSessionDTO fixSessionDTO, Topic topicDestination)
                          	{
                          		super();
                          		this.fixSessionDTO = fixSessionDTO;
                          		this.topicDestination = topicDestination;
                          	}
                          
                          	
                          	public FixSessionDTO getFixSessionDTO()
                          	{
                          		return fixSessionDTO;
                          	}
                          
                          	public void setFixSessionDTO(FixSessionDTO fixSessionDTO)
                          	{
                          		this.fixSessionDTO = fixSessionDTO;
                          	}
                          
                          	//@PostConstruct
                          	public void init()
                          	{
                          
                          		try
                          		{
                          			System.out.println("AbstractSessionBean.init()." + fixSessionDTO.toString());
                          			messageListeners = new DefaultMessageListenerContainer();
                          			CachingConnectionFactory cacheFactory = new CachingConnectionFactory();
                          			cacheFactory.setTargetConnectionFactory(connectionFactory);
                          			cacheFactory.setReconnectOnException(true);
                          			cacheFactory.setExceptionListener(new ExceptionListener()
                          			{
                          
                          				public void onException(JMSException e)
                          				{
                          					log.error("Error", e);
                          				}
                          			});
                          			cacheFactory.setSessionCacheSize(1);
                          
                          			messageListeners.setConnectionFactory(connectionFactory);
                          			messageListeners.setDestinationName(topicDestination.getTopicName());
                          			messageListeners.setMaxConcurrentConsumers(1);
                          			messageListeners.setSessionAcknowledgeModeName("AUTO_ACKNOWLEDGE");
                          			messageListeners.setMessageListener(this);
                          			messageListeners.setPubSubDomain(true);
                          			messageListeners.setAcceptMessagesWhileStopping(false);
                          			messageListeners.setConcurrentConsumers(1);
                          			messageListeners.setSessionTransacted(false);
                          			messageListeners.setReceiveTimeout(1000);
                          			messageListeners.setMaxMessagesPerTask(300);
                          			messageListeners.initialize();
                          			messageListeners.start();
                          
                          		}
                          		catch (Exception e)
                          		{
                          			e.printStackTrace();
                          		}
                          	}
                          
                          	@PreDestroy
                          	public void destroy()
                          	{
                          		try
                          		{
                          			log.debug("Destroying MDB. details=" + fixSessionDTO.toString());
                          			if (messageListeners != null)
                          			{
                          				messageListeners.stop();
                          				messageListeners.shutdown();
                          				messageListeners.destroy();
                          			}
                          		}
                          		catch (Exception e)
                          		{
                          			log.error("Couldnt destroy MDB. details=" + fixSessionDTO.toString(), e);
                          		}
                          
                          	}
                          
                          	@ManagedOperation
                          	public void stop()
                          	{
                          		messageListeners.stop();
                          	}
                          
                          	@ManagedOperation
                          	public void start()
                          	{
                          		messageListeners.start();
                          	}

                          two questions:
                          1. I thought if I need to use Spring integration in order to have it's Messages mechanisem why couldnt I use the same topic I am already subscribed to retrieve "adminisitartion" messages to do administration things like 'stop','start','die'..

                          2. incase you like idea 1. how will I destroy the prototype bean. just called this.destroy() and close all connections and hope the GC will do the rest for me?

                          Comment


                          • #14
                            I still don't see why you need them on demand but that probably is just me.

                            The problem I see with this implementation is that each MessageListenerContainer uses its own thread pool, own threads etc. With the Spring Integration approach you would only have a single listener which dispatches to several consumers. You now create a new one, attach it to the topic and receive messages.

                            To cleanup call the destroy method and make sure that the other beans used (fixSessionDTO) aren't referenced some where else.

                            Comment


                            • #15
                              You dont see why I need them on demand since this is only part of the architecture.

                              The big picture is that each subscriber has it's own "life" exactly like new web session.

                              As soon as users connect to my application(not via web. but via diff protocol) I get from them specific inputs and I have to subscribe them to a topic when the users leave I need to unsubscribe thier "session" which means the listener.

                              Thats why I need it "on demand" each subscriber has it's own parameters.

                              Now each subscriber is also associated to a group(which get different messages). So I have also different topics. that's

                              why I made MessageListenerContainer programticly because each subscriber will have specific topic destination which will get on runtime.

                              are you getting me or a sarcastic comment is on the way?:P

                              Comment

                              Working...
                              X