Results 1 to 9 of 9

Thread: How to 'wire' dynamic Maps.

  1. #1

    Question How to 'wire' dynamic Maps.

    Hi

    Here's my scenario. I have a class that checks a map to see if instance of ClassAlgo exists. If not it does new ClassAlgo, stores that in the Map and continues.

    I'd LOVE that instances of class Algo be handles by Spring (so long as EACH instance is unique) as I want to tu benefit from the DAO stuff and even being able to use the 'ant style' placeholders to set up that instance with default (user-defined) variables.

    Sample Java code: (in SomeOrganiser.java)
    Code:
        // this key can change every request (but I may only have a few dozen in my app worse case.
        // algo map is a HashMap<String, ClassAlgo> as a field / attribute of the SomeOrganiser class.
        ClassAlgo algo = this.algoMap.get( someKey );
        if ( algo == null ) {
           algo = new ClassAlgo( someKey );
           this.algoMap.put( someKey, algo );
        }
        // From here on out we use algo as normal.
    Spring Code / Configs:
    Code:
    <bean id="OrganizerClass" class="com.foo.bar.SomeOrganiser"/>
        <!-- What do I do here to get my ALgoMap setup for my ClassAlgo instances 
            if I dont know how many I need OR the key they will be represented by. -->
    </bean>
    
    <bean id="ClassAlgo" class="com.foo.bar.ClassAlgo">
        <property name="registeredHosts" value="${registered.hosts}"/>
        <property name="interval" value="${interval}"/>
    </bean>
    And these placeholders would be picked up from the .propeties file as so:
    Code:
    registered.hosts=http://foo.com/myurl|http://bar.com/myOtherUrl
    interval=1000

  2. #2
    Join Date
    May 2007
    Location
    Saint Petersburg, Russian Federation
    Posts
    1,189

    Default

    You can just introduce your own class that implements java.util.Map interface and delegates the implementation to the aggregated Map instance. The only purpose of this class is to put necessary entry to the map if necessary during get() processing. You can just inject instance of that class whenever necessary.

  3. #3

    Default

    So then, from a Spring MVC (and maybe I have to take this thread to the web forum) how do I get the 'instance of the class when necessary'?

    I was looking at some docs and I thought could try this:
    Code:
          WebApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext( request.getSession().getServletContext() );
          ctx.getBean( "classAlgo" );
    but this doesn't seem elegant for my solution as the class needing to get instances of ClassAlgo is pretty far removed from the Controller where I can get the WebApplicationContext (as I need the HttpServletContext).

    I.E. Controller calls Manager calls a Facade_to_the_algos calls the HashMapManager. It's in the HAshmap manager where I need todo the 'getBean()'.

    Looking at similar solution using ApplicationContext I worry that if I pass in my bean configuration XML files I'll reload the whole app (thus creating all new instances of my beans) and this would break the running web application.

    So I'm stuck on where to turn.(Other than passing that WebContext all over the place and polluting my code with web based only implementations.

    Thanks for the help.


    Quote Originally Posted by denis.zhdanov View Post
    You can just introduce your own class that implements java.util.Map interface and delegates the implementation to the aggregated Map instance. The only purpose of this class is to put necessary entry to the map if necessary during get() processing. You can just inject instance of that class whenever necessary.

  4. #4

    Default

    Hi

    Okay I read further / researched....

    If I just make my SomeOrganiser implement BeanFactoryAware and I then use this factory to create instances of my bean "ClassAlgo" (assuming I configure it as scope prototype) will this solve the problem for my need?

  5. #5
    Join Date
    May 2007
    Location
    Saint Petersburg, Russian Federation
    Posts
    1,189

    Default

    Quote Originally Posted by JeanNiBee View Post
    Hi

    Okay I read further / researched....

    If I just make my SomeOrganiser implement BeanFactoryAware and I then use this factory to create instances of my bean "ClassAlgo" (assuming I configure it as scope prototype) will this solve the problem for my need?
    Ideally you shouldn't perform context.getBean() at all. All dependencies should be resolved by spring. E.g. your configuration may looks like the following:

    HTML Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="
      http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
    
        <bean id="hashMapManager" class="com.HashMapManager"/>
    
        <bean id="manager" class="com.MyManager">
            <property name="hashMapManager" ref="hashMapManager"/>
        </bean>
    
        ....
    
    </beans>

  6. #6

    Default

    Okay so I think this is where I'm getting lost.

    The Organiser (which has an instance of Hashmap) is declared in a <bean> reference and if I subclass java.util.HashMap by my own class, the <bean> definition will show a property of that sub-classed type.

    My issue is 'after' this point, when I have to put stuff into the HashMap.. I have no way of ever knowing in advance how many instance of SomeAlgo will go in there. This is all done through the reading of files sent into the system for processing. So I can't (*or dont know how*) to declare these instances as properties (in <bean> definition) of my subclassed HashMap.

    So.. I thought I should, create a <bean> definition for SomeAlgo, scoped as Prototype.. then when I need a new one I can call a ctx.getBean( "somealgo" ) and get an instance to put into my HashMap.

    So I'd change your example to this. (and then use getBean() in my HashMap manager).

    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="
      http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
    
        <bean id="hashMapManager" class="com.HashMapManager"/>
    
        <bean id="somealgo" class="com.SomeAlgo" scope="prototype"/>
    
        <bean id="manager" class="com.MyManager">
            <property name="hashMapManager" ref="hashMapManager"/>
        </bean>
        ....
    </beans>
    I apologize for being a bit dense, Spring has been wonderful to me but also confusing at time. This being one of those confusing concepts). You've been very patient with me so far and I appreciate that.

    -
    Jean

    Quote Originally Posted by denis.zhdanov View Post
    Ideally you shouldn't perform context.getBean() at all. All dependencies should be resolved by spring. E.g. your configuration may looks like the following:

    HTML Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="
      http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
    
        <bean id="hashMapManager" class="com.HashMapManager"/>
    
        <bean id="manager" class="com.MyManager">
            <property name="hashMapManager" ref="hashMapManager"/>
        </bean>
    
        ....
    
    </beans>

  7. #7
    Join Date
    May 2007
    Location
    Saint Petersburg, Russian Federation
    Posts
    1,189

    Default

    Quote Originally Posted by JeanNiBee View Post
    Okay so I think this is where I'm getting lost.

    The Organiser (which has an instance of Hashmap) is declared in a <bean> reference and if I subclass java.util.HashMap by my own class, the <bean> definition will show a property of that sub-classed type.

    My issue is 'after' this point, when I have to put stuff into the HashMap.. I have no way of ever knowing in advance how many instance of SomeAlgo will go in there. This is all done through the reading of files sent into the system for processing. So I can't (*or dont know how*) to declare these instances as properties (in <bean> definition) of my subclassed HashMap.
    I'm afraid the problem is still unclear for me. As far as I understand there are multiple 'manager' beans that process incoming requests. There is a common processing scenario that is population of the shared cache with the algorithm instance if necessary (if the cache doesn't contain such an algorithm yet). That SomeAlgo instance is built on the basis of the incoming request parameters.

    I just recommended to do the following:
    1. Create dedicated class that represents a cache that create new instance on the incoming parameter basis if necessary;
    2. Register that instance at the spring and inject it to all necessary 'managers';


    I'm afraid I don't see a necessity to define algo instance as a prototype and retrieve it instead of creating that instance via new operator when necessary.

    Quote Originally Posted by JeanNiBee View Post
    I apologize for being a bit dense, Spring has been wonderful to me but also confusing at time. This being one of those confusing concepts). You've been very patient with me so far and I appreciate that.

    -
    Jean
    Welcome

  8. #8

    Default

    Okay so quick corrections (very small).

    1. I have 1 manager (Stateless) that receives messages and passes them out to instances of the Algo (stateful) beans.

    2. Using 'new SomeAlgo" Is what I do currently, BUT these algorithms have some default variables (user defined) at startup that I want to manage via spring and it's properties injection / configurators.

    So my bean definition would evolve to look like this: (Maybe I should have just posted my code in more detail from the beginning)

    Ex.:
    Code:
    <bean id="somealgo" class="com.SomeAlgo" scope="prototype">
      <property name="adjustmentInterval" value="${interval.adjust}"/>
      <property name="observationInterval" value="$(interval.observe)"/>
    </bean>
    So this is why I want to replace Spring 'prototype' and manual injection (as I have no idea if I can auto inject into Hashes) instead of keeping my 'new SomeAlgo()" code.



    Quote Originally Posted by denis.zhdanov View Post
    I'm afraid the problem is still unclear for me. As far as I understand there are multiple 'manager' beans that process incoming requests. There is a common processing scenario that is population of the shared cache with the algorithm instance if necessary (if the cache doesn't contain such an algorithm yet). That SomeAlgo instance is built on the basis of the incoming request parameters.


    I just recommended to do the following:
    1. Create dedicated class that represents a cache that create new instance on the incoming parameter basis if necessary;
    2. Register that instance at the spring and inject it to all necessary 'managers';


    I'm afraid I don't see a necessity to define algo instance as a prototype and retrieve it instead of creating that instance via new operator when necessary.



    Welcome

  9. #9
    Join Date
    May 2007
    Location
    Saint Petersburg, Russian Federation
    Posts
    1,189

    Default

    Quote Originally Posted by JeanNiBee View Post
    Okay so quick corrections (very small).

    1. I have 1 manager (Stateless) that receives messages and passes them out to instances of the Algo (stateful) beans.

    2. Using 'new SomeAlgo" Is what I do currently, BUT these algorithms have some default variables (user defined) at startup that I want to manage via spring and it's properties injection / configurators.

    So my bean definition would evolve to look like this: (Maybe I should have just posted my code in more detail from the beginning)

    Ex.:
    Code:
    <bean id="somealgo" class="com.SomeAlgo" scope="prototype">
      <property name="adjustmentInterval" value="${interval.adjust}"/>
      <property name="observationInterval" value="$(interval.observe)"/>
    </bean>
    So this is why I want to replace Spring 'prototype' and manual injection (as I have no idea if I can auto inject into Hashes) instead of keeping my 'new SomeAlgo()" code.
    Ok, so you create SomeAlgo with particular property from the 'manager' if such algorithm is not exists yet. You want to preconfigure known algorithm properties via spring as well. Understood

    Yes, you prototype-based approach works fine for such situation. Also you can look at the following stuff that may ease your code/configuration:

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •