Finding a cool way to test my framework

Hello all,



So I now have this nifty framework for distributed programming, but no real way to test it and find any kinks.

This is where you come in. I need help finding a cool way to test it. I came up with a 3D chat application, but other then that, I'm stumped. mostly due to my total lack of #d programming skills.



If I want to build such a chat application with JME3, I would need JME3 (DUHHH), some sort of GUI system and something through which the clients can communicate with the server.



I just DLed the JME 3 sources so I'll be working on those examples over the next few days. Then I plan on figuring out the client side of the chat application.



Any suggestions on those would be most welcome.



Mark

ractoc said:

So I now have this nifty framework for distributed programming, but no real way to test it and find any kinks.

Could you explain further what exactly that "framework for distributed programming" is and delivers?
Cheers,
Normen

The project can be found at: http://sourceforge.net/projects/pffj/

The wiki can be found at: http://sourceforge.net/apps/mediawiki/pffj/index.php?title=Main_Page



But in short, it lets you write distributed programs with J2SE. No knowledge of distributed programming is needed since everything that has to do with the distributed part of things is done by the framework. All you do is write plugins which communicate via PluginMessages. Then, in the config XML you declare which plugins there are, which are local and which are remote. For accessing the remote plugins, there are currently two methods. First you can straight configure every remote server in the config. This was the first method I implemented. Since this turned out to be very inflexible since every time you would add a new server, you would also need to alter each and every existing configuration XML, I now implemented a PluginRegistry. When you put a reference to the PluginRegistry in the config XML, it will register all local plugins with the registry, and each time a remote plugin is needed, it will check the registry for the connection data. There is some caching invloved for performance, but that's the general idea.



There are 3 test cases, local, distributed with server references and distributed with a registry reference. When you take a look at the test case you'll notice that the only real difference between the 3 test cases is the config file. What this means is that you can switch from a single server environment to a distributed environment without any code alterations. Adding more servers is just as easy.



Because the framework is nothing more then an intelligent messaging controller with all the actual logic residing in the plugins you write yourself, this framework should be usable in almost every scenario.



I am not quite happy with the network performance yet, so there is a bit of tweaking to be done there. But for that I'm currently looking for someone with more experience in that area then me. The basic idea of the framework works like a charm though.



Current features implemented:

  • Plugin engine
  • Messaging system
  • Distributed messaging
  • Plugin registry



    Features still planned:
  • Registry clustering (for stability and reliability)
  • Plugin clustering (should in theory work, just not quite happy with the implementation)
  • Dynamic load balancing for plugins (when one plugin sees heavy use it will be activated as local on more servers)
  • Configuration on the fly (will allow adding new plugin instances, with new PluginIDs from code instead of just from config. This can be usefull for a chat app for instance in case of new chatrooms)



    no deadlines on the new features at this time. With the new kid expected any day now I have no idea how much time I can put into this thing.



    Example configs:

    Stand-Alone:


<config>
   <plugins>
      <plugin id="readFile"
         class="com.ractoc.pffj.test.plugins.read.ReadTextFilePlugin">
         <parameters>
            <parameter name="processMessagePlugin" value="writeFile" class="string" />
         </parameters>
      </plugin>
      <plugin id="writeFile"
         class="com.ractoc.pffj.test.plugins.write.WriteTextFilePlugin">
         <parameters>
            <parameter name="fileName" value="c:/temp/test_out.txt" class="string" />
         </parameters>
      </plugin>
   </plugins>
</config>



Server reference:
Reader:


<config>
   <servers>
      <server id="writer" port="1234" address="localhost" />
   </servers>
   <plugins>
      <plugin id="readFile"
         class="com.ractoc.pffj.test.plugins.read.ReadTextFilePlugin">
         <parameters>
            <parameter name="processMessagePlugin" value="writeFile" class="string" />
         </parameters>
      </plugin>
      <plugin id="writeFile"
         class="com.ractoc.pffj.test.plugins.write.WriteTextFilePlugin">
         <server refid="writer" />
      </plugin>
   </plugins>
</config>


Writer:


<config>
   <servers>
      <!-- local server, does not need to be referenced in the plugin. -->
      <server id="writer" port="1234" />
   </servers>
   <plugins>
      <plugin id="writeFile"
         class="com.ractoc.pffj.test.plugins.write.WriteTextFilePlugin">
         <parameters>
            <parameter name="fileName" value="c:/temp/test_out.txt"
               class="string" />
         </parameters>
      </plugin>
   </plugins>
</config>



Registry reference:
Reader:


<config>
   <registry address="localhost" port="1111" />
   <servers>
      <!-- local server, does not need to be referenced in the plugin. -->
      <server id="writer" port="4321" />
   </servers>
   <plugins>
      <plugin id="readFile"
         class="com.ractoc.pffj.test.plugins.read.ReadTextFilePlugin">
         <parameters>
            <parameter name="processMessagePlugin" value="writeFile"
               class="string" />
         </parameters>
      </plugin>
      <plugin id="writeFile"
         class="com.ractoc.pffj.test.plugins.write.WriteTextFilePlugin"
         remote="true" />
   </plugins>
</config>


Writer:


<config>
   <registry address="localhost" port="1111" />
   <servers>
      <!-- local server, does not need to be referenced in the plugin. -->
      <server id="writer" port="1234" />
   </servers>
   <plugins>
      <plugin id="writeFile"
         class="com.ractoc.pffj.test.plugins.write.WriteTextFilePlugin" remote="false">
         <parameters>
            <parameter name="fileName" value="c:/temp/test_out.txt"
               class="string" />
         </parameters>
      </plugin>
   </plugins>
</config>



All that is needed to use the framework is to startup the PluginController and feed it some message that starts the whole thing:


final ExecutorService threadExecutor = Executors.newSingleThreadExecutor();
try {
    threadExecutor.submit((Callable<Integer>) new PluginController("/config/standAlone.xml")).get();
    final StartReadingMessage srMsg = new StartReadingMessage();
    srMsg.setFileName(fileName);
    final StartReadingMessageResult srResult = (StartReadingMessageResult) PluginController.getCurrentPluginController().processMessage("readFile", srMsg);
    if (srResult.getErrorCode() != ReadTextFileErrorCodes.SUCCESS) {
        System.out.println("Error reading processing file, code=" + srResult.getErrorCode());
    }
} catch (final InterruptedException e) {
    System.exit(-1);
} catch (final ExecutionException e) {
    System.exit(-2);
} catch (final PluginException e) {
     System.exit(-2);
}



This startup message is off course only needed in some cases. In the example, the framework is useed to read a textfile line-by-line in the ReaderPlugin and write that file line-by-line in the WriterPlugin. The startup message just tells the ReaderPlugin which file to read.

There is much more to tell about the framework, but this should give you a general idea.

So, and now to bring my wiki up to date so what I explain in there is actually what's in the latest version of the code...

Mark

Oh, and if you have any questions, or are interested in helping out, let me know.

Ok, so its really complete networking on the UI level… How is access from the Java world organized? Via the nifty methods for accessing UI data?

Most networked games will probably use their own network stack for the "real" networking, but one application that comes to my mind right now is of course chat and online game partner finding. Theres a UI demo for something like that in nifty already, maybe you can extend that to really work and become something like gamespy, with an example how to get the connection data to initialize the "real" network connection after the participants found each other.



Cheers,

Normen

Didn't know there was something like that already as a nifty example. Will look into that later.



But on the network side… This framework isn't meant to replace the client-server communication you have between your game client and your game server (although in theory it should be able to). The idea I have is that you would write a dedicated plugin which handles that part.

The plugins I'm talking about aren't your standard UI plugins. They can contain any code you want. As an example I use the read file / write file. But I already worked on a now discontinued project where the framework was used as the game server core. Here we had a network plugin which handled the communication with the client, a Player pluging which handled all player related stuff, a Character Plugin and a Chat Plugin.

When the player logged in, the client would send a message to the network plugin, which would then send a LoginPluginMessage to the PlayerPlugin. There the credentials were checked. If they checked out, the PleyerPlugin would send a GetCharacterListing message to the Character Plugin which would return the list of characters for that player (if any). Then that list would be returned to the client. And so on. So now real UI related stuff at all.



I am playing with the idea to bring this whole framework to the client as well though. Which would create a plugin drinven game client. Since I'm fairly new to actually building game clients, that's a long way off though. (unless someone is interested in helping out… ;)).



But would a GameSpy like app be something you guys would be interested in at all? I mean, it's nice to have it as a testbed, but I would love it even more if it would later actually be used.



On a side not, I updated the examples section of the wiki, it now also contains the server reference test case.

All that needs doing now is to add the registry functionality throughout the wiki…