Announcement Announcement Module
Collapse
No announcement yet.
Interesting Singleton Interaction Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Interesting Singleton Interaction

    My application uses Spring to wire in a class that opens a port and handles requests that come in on that port. I've written it so that I can, through Spring configs, add new instances of that port handler on different ports, without adding additional code. Each port listener runs in it's own thread, and does not, and should not, know of the other listeners and any connections being handled on those ports. So I set up each port listener as a non-singleton:

    Code:
        <bean id="ConfigGroupMgr" class="ConfigGroupMgrBean">
            <property name="socketMgrList">
                <list>
                    <ref local="DefaultSocketManager" />
                    <ref local="TestSocketManager" />
                </list>
            </property>
        </bean>
        
        <bean id="DefaultSocketManager" class="SocketManager" autowire="constructor" singleton="false">
            <!-- Description -->
            <constructor-arg type="java.lang.String" index="0">
                <value>XML-RPC Manager</value>
            </constructor-arg>
            <!-- Port -->
            <constructor-arg type="int" index="1">
                <value>3742</value>
            </constructor-arg>
            <!-- Timeout -->
            <constructor-arg type="int" index="2">
                <value>5000</value>
            </constructor-arg>
        </bean>
        
        <bean id="TestSocketManager" class="SocketManager" autowire="constructor" singleton="false">
            <!-- Description -->
            <constructor-arg type="java.lang.String" index="0">
                <value>Test Manager</value>
            </constructor-arg>
            <!-- Port -->
            <constructor-arg type="int" index="1">
                <value>3743</value>
            </constructor-arg>
            <!-- Timeout -->
            <constructor-arg type="int" index="2">
                <value>5000</value>
            </constructor-arg>
        </bean>
    From the logs, it looks like they are setup right:

    370 [main] (LoggingBean.java:94) INFO GroupManager - Bean [loggingBean] Total Socket Managers: 2
    370 [main] (LoggingBean.java:99) DEBUG GroupManager - Bean [loggingBean] Starting Socket Manager Thread...
    371 [Thread-1] (LoggingBean.java:94) INFO GroupManager - Bean [loggingBean] XML-RPC Manager listening on port: 3742
    373 [main] (LoggingBean.java:99) DEBUG GroupManager - Bean [loggingBean] Starting Socket Manager Thread...
    373 [Thread-2] (LoggingBean.java:94) INFO GroupManager - Bean [loggingBean] Test Manager listening on port: 3743
    423 [Thread-2] (LoggingBean.java:99) DEBUG GroupManager - Bean [loggingBean] Test Manager: Waiting for request on 3743
    423 [Thread-1] (LoggingBean.java:99) DEBUG GroupManager - Bean [loggingBean] XML-RPC Manager: Waiting for request on 3742

    So it's found both SocketManager configurations (SocketManager is the class managing a specific port). It sets up the port and the timeout ok (XML-RPC: 3742, Test: 3743). Lastly, both threads are announced that they are listening on their respective ports. Everything looks dandy.

    I run a test and connect to 3742 via telnet:

    telnet localhost 3742

    It connected fine, so I typed some text that I know will show up in the log so I can see the connection lifecycle.

    Back in the log, I see (remember, 3742 is XML-RPC, 3743 is Test):

    5433 [Thread-3] (LoggingBean.java:94) INFO GroupManager - Bean [loggingBean] (Test Manager) Starting new Socket Connection H
    andler from /0:0:0:0:0:0:0:1%0:52158
    6648 [Thread-3] (LoggingBean.java:94) INFO GroupManager - Bean [loggingBean] test
    12393 [Thread-3] (LoggingBean.java:94) INFO GroupManager - Bean [loggingBean] (Test Manager) Closing socket connection from
    /0:0:0:0:0:0:0:1%0:52158
    12394 [Thread-3] (LoggingBean.java:99) DEBUG GroupManager - Bean [loggingBean] (Test Manager) Socket closed.

    "Socket Connection Handler" is another class that is instantiated from the Socket Handler, but is not managed by Spring (the socket connection is created at run-time). So "Socket Connection Handler" shouldn't be cached.

    You'll notice that even though I telnetted to 3742 (XML-RPC Port), the "Test" handler on 3743 handled the request.

    Telnetting to 3743 tells me that the host is unavailable (so 3743 is closed). If I'm connected to 3743 FIRST, then connect to 3742, my connection on 3743 is forcefully dropped by the server and the 3742 connection is handled. After that 3743 won't listen any longer.

    Each Socket Handler runs in it's own thread, and spins off new threads for each socket connection (I know of NIO and MINA, but I'm still contemplating how I would integrate it with my app and Spring, or if it would even resolve this issue).

    Any ideas why these objects, seemingly non-singletons, are somehow aware of each other even though they are configured with singleton=false?

  • #2
    Observations...

    Not a solution necessarily (I can't see from your post what is going on under the covers), but two observations:

    1) the xml fragment you posted only references the two SocketManager instances once, as properties of a singleton bean, so they are effectively singletons (only instanmtiated once each), unless there is something else you are not showing. So singleton="false" seems like the wrong thing to do here.

    2) autowire="constructor" might seriously screw you up here (maybe the cause of your problem?). It seems inappropriate, as you are explicitly setting the constructor args, to use autowire="constructor" as well. I have no idea what will happen, but if you have another bean somehere else with the right type (Integer?) it might pop into your SocketManager in an autowire. Autowire is pretty evil actually - best avoided for production code.
    Last edited by Dave Syer; Aug 2nd, 2006, 01:37 AM.

    Comment


    • #3
      Ok.... I'm retard....

      I had a static variable in one of my java files that was futzing everything up:

      Took out "static" and it seems fine. Sorry about that guys.. sometimes you need to explain and detail your own program to find those little gotchas.

      Comment

      Working...
      X