lang="en-US"> SmartFoxServer 2X Tutorial: How To Create A Custom MySQL Login Extension –  Design1online.com, LLC

SmartFoxServer 2X Tutorial: How To Create A Custom MySQL Login Extension

As usual the documentation for SFS is really lacking in this area (or scattered across several pages and consequently vague– not sure why they do that). Here is my attempt at a reasonable tutorial on how to create a custom login extension for MySQL databases. This tutorial assumes you already have a MySQL database setup with at least one table and some data in it. It also assumes the database you’re using is jdbc accessible.

As always you can download the working files
but you’ll need to read the tutorial to get SFS setup and using them properly.

1. Setup the MySQL Database Driver

  1. Login to the SFS admin panel.
  2. Go to the Zone Configurator.
  3. Click on the zone you want to setup the database for.
  4. At the bottom of the screen click on the pencil to edit the zone.
  5. Find the Database Manager tab.
  6. Make sure you switch the Active slider to ON.
  7. In the Database Driver class type in: org.gjt.mm.mysql.Driver
  8. In the Connection String type in: jdbc:mysql://[localhost or IP address to the server]/[database name you want to use]
  9. Enter in your username and password necessary to connect to the database you entered in the connection string
  10. Put in a simple SQL query into the test SQL box. This isn’t required but SFS will notify you that there was a connection problem if you leave this blank. Something like SELECT id FROM users LIMIT 1 is a good query to enter assuming you have a users table on the database you’re using and it has some data in it.
  11. Press the submit button to save your changes.
  12. One thing to note, you can also change all of these settings if you go to the installation directory of SFS2x, find the Zones folder, then edit the [zonename].xml file. You’ll end up with something that looks like this:

<databaseManager active=”true”>
<driverName>org.gjt.mm.mysql.Driver</driverName>
<connectionString>jdbc:mysql://localhost/testDatabase</connectionString>
<userName>Jade</userName>
<password>somethingNoOneWillGuess</password>
<testSql>SELECT id FROM users LIMIT 1</testSql>
<maxActiveConnections>10</maxActiveConnections>
<maxIdleConnections>10</maxIdleConnections>
<exhaustedPoolAction>FAIL</exhaustedPoolAction>
<blockTime>3000</blockTime>
</databaseManager>

2. Create The Login Extension File

  1. Open your favorite Java IDE. I use Netbeans but any one will work.
  2. Create a new Java project. Name the project whatever you want, the project name isn’t important but the class names will be later.
  3. Create a new class with a file name of LoginExtension. This is case sensitive!
  4. When it asks for a package enter the following: sfs2x.extension.[whatever you want to call this extension].src
  5. Note that any extension you make MUST start with the blue colored portion above. If it doesn’t SFS won’t be able to find the .JAR file you’ll be creating later.
  6. In the red colored portion above you can enter whatever your want the name of this extension to be. I named mine login. This is important later as this is what you’ll give SFS so it knows which extension it’s supposed to be loading.
  7. The green .src is optional however I find that SFS sometimes has problems loading extensions if you don’t put the files in another level. This may also be something IDE related with how NetBeans is exporting the .JAR. Either way I would recommend it so if you have people working with different IDEs you won’t run into problems later.
  8. Next you need to import the SmartFoxServer java libraries. Where this is located will vary depending on the IDE you use, but generally you’ll find it under project > options > libraries. Click the button that says Add JAR/Folder or Add External JARS or something to that effect. Navigate to where you installed SFS and find the LIB folder (not the _LIB_ folder under extensions). Locate the sfs2x.jar and the sfs2x_core.jar files and add them to your project.
  9. In your class file enter the following then save your changes:
package sfs2x.extension.login.src;

import com.smartfoxserver.v2.extensions.SFSExtension;
import com.smartfoxserver.v2.core.SFSEventType;

public class LoginExtension extends SFSExtension {

 @Override
 public void init()
 {
 trace("Login extension starting.");

 // Register the login event
 addEventHandler(SFSEventType.USER_LOGIN, LoginHandler.class);
 }

 @Override
 public void destroy()
 {
 trace("Login extension stopped.");
 super.destroy();
 }
}

3. Create the Login Request Handler File

  1. Create another class called LoginHandler in the same project. It should have the same package as the last file you made.
  2. In this file you’ll need to enter the following:
package sfs2x.extension.login.src;

import java.sql.SQLException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.PreparedStatement;
import com.smartfoxserver.bitswarm.sessions.ISession;
import com.smartfoxserver.v2.entities.data.SFSArray;
import com.smartfoxserver.v2.core.SFSEventParam;
import com.smartfoxserver.v2.core.ISFSEvent;
import com.smartfoxserver.v2.exceptions.SFSException;
import com.smartfoxserver.v2.exceptions.SFSLoginException;
import com.smartfoxserver.v2.exceptions.SFSErrorData;
import com.smartfoxserver.v2.exceptions.SFSErrorCode;
import com.smartfoxserver.v2.extensions.BaseServerEventHandler;
import com.smartfoxserver.v2.extensions.ExtensionLogLevel;

public class LoginHandler extends BaseServerEventHandler {

   @Override
   public void handleServerEvent(ISFSEvent event) throws SFSException
   {
        String username = (String) event.getParameter(SFSEventParam.LOGIN_NAME);
        String password = (String) event.getParameter(SFSEventParam.LOGIN_PASSWORD);

        ISession session = (ISession)event.getParameter(SFSEventParam.SESSION);

        try {
            //get a connection to the database
            Connection conn = getParentExtension().getParentZone().getDBManager().getConnection();

            //This will strip potential SQL injections
            PreparedStatement sql = conn.prepareStatement("SELECT id, password FROM members WHERE username = ?");
            sql.setString(1, username);

            // Obtain ResultSet
            ResultSet result = sql.executeQuery();

            //Put the result into an SFSobject array
            SFSArray row = SFSArray.newFromResultSet(result);

            //make sure there is a password before you try to use the checkSecurePassword function
            if (password.equals(""))
            {
                SFSErrorData data = new SFSErrorData(SFSErrorCode.LOGIN_BAD_PASSWORD);
                data.addParameter(username);
                throw new SFSLoginException("You must enter a password.", data);
            }

           //SFS always encrypts passwords before sending them so you need to decrypt the password
           //received from the database and compare that to what they entered in flash
           if (!getApi().checkSecurePassword(session, row.getSFSObject(0).getUtfString("password"), password))
           {
                SFSErrorData data = new SFSErrorData(SFSErrorCode.LOGIN_BAD_PASSWORD);

                data.addParameter(username);

                throw new SFSLoginException("Login failed for user: "  + username, data);
            }

            //this was in one of the SFS examples so I left it in there for testing purposes
            if (username.equals("Gonzo") || username.equals("Kermit"))
            {

                // Create the error code to send to the client
                SFSErrorData errData = new SFSErrorData(SFSErrorCode.LOGIN_BAD_USERNAME);
                errData.addParameter(username);

                // Fire a Login exception
                throw new SFSLoginException("Gonzo and Kermit are not allowed in this Zone!", errData);
            }

            //make sure you close the database connection when you're done with it, especially if you've
            //set a low number of maximum connections
            conn.close();

            //at this point you could trigger an joinRoom request if you wanted to, otherwise
            //this will return success to your LOGIN event listener
            trace("Login successful, joining room!");

        } catch (SQLException e) {
            trace(ExtensionLogLevel.WARN, " SQL Failed: " + e.toString());
        }
    }
}

4. Create the .JAR Executable

  1. Now that you have both extension files ready to go it’s time to setup the project for building a .JAR
  2. Return to your project > options and find the Build/Compile settings. Make sure your .JAR is set to export with class name warnings/errors (if the option is available) and that it’s set to compress the file. A smaller file means faster runtime.
  3. Build your project. If you have any errors your linker will let you know. You need a successful build to get a .JAR. Sometimes your project isn’t set to build .JAR files until execution. This is also a setting in your IDE that you can toggle somewhere.
  4. Last but not least, it’s time to find where your .JAR file was created. You’re going to need this file for the next step.

5. Configure SFS to Use the Login Extension

  1. Before you can run your extension you have to make your extension .JAR file available to SFS and then configure your zone to load the extension and attach it to your zone. (you can also put extensions on a room level if you need to).
  2. Start by going to the location of where you installed SFS. Locate the Extensions folder. Now create a new folder that matches the name of your extension. In my example I used login as the name of my extension so I would create a folder called login.
  3. Next copy the .JAR you created and paste it into the folder you just created.
  4. Go back to the SFS Admin console — you can also do this by going to the zone’s xml file.
  5. Now go to the Zone Configuration and edit the same zone that you setup your database connection on. This time click on the Zone Extension tab.
  6. In the name field enter the name of your extension. In my example I called my extension login and I created a login folder so I would enter the word login into this box.
  7. Our extension is a .JAR so we’re going to leave the type at JAVA.
  8. In the File box enter the package and filename for your main extension file like so: sfs2x.extension.login.src.LoginExtension
  9. Now click on the general tab and turn on the Use Custom login. Even if you have the extension setup properly SFS will continue to use it’s built in login functionality if this is not turned on.
  10. This completes the extension portion of the tutorial. Now let’s build a .SWF file to test our extension and make sure it’s working properly.

6. Restart SFS

Make sure you restart SmartFox before testing your extensions. This will load in the .JAR files you placed in the extensions folder and check to make sure your database configuration is setup properly. Additionally you should check the SFS console for any errors it encounters as it tries to test your database connection and load your extension.

7. Create A .SWF to Test Your Extension

Since I’ve created a .zip with the .fla and .swf already created for you I’m not going to go into detail here. In a nutshell this file connects to SFS then attempts to use the login extension you just created. If you have it setup properly:

  • you’ll get an error message if you leave the password blank
  • you’ll get an error message if you have a username of Gonzo
  • you’ll get an error if the username and password you’ve supplied don’t match a username/password found in your database
  • Otherwise you’ll get a successful LOGIN event triggered and you can go from there.

Troubleshooting &
Frequently Asked Questions

Why doesn’t my login work  even though my extension is setup correctly?

  • Make sure you have a record in the database table you’re referencing and that the correct username/password information exists for that user.
  • Make sure you’re using the correct database and accessing the correct table.
  • Make sure SFS is connecting to your database. To do that shut down SFS then restart it again using the SFS console. You’ll see a message at the top concerning your database connection if the test SQL query you entered in the SFS admin panel fails.

Why do I get null object errors?

  • I found these happen for a wide variety of reasons. One may be that you’re not checking for an empty password string when you use the checkSecurePassword function. Another may be that your result set isn’t returning any data. I’ve also found this happens if your database connection isn’t configured properly. Sorry but that’s all the help I have to offer for this one.

Why do I get extension files not found errors?

  • I believe this has something to do with how your IDE is building the .JAR file. Refer back to the login extension we made above. If you put your LoginExtension and LoginHandler files in package extension sfs2x.extension.login you may get this error. Try changing the package extension on both files to sfs2x.extension.login.src. Rebuild your .JAR file and replace the old one in your extension/login folder.
  • Check to make sure you’ve entered the correct package path in the File box on your SFS admin panel. If you have a typo in the name it won’t be able to use your .JAR.

Why do I get  invalid path directory errors?

  • When you create an extension you have to create a folder with the extension name and place it into your extension folder wherever you installed SFS.  In our example above I created an extension called login. So in my extensions folder I create a new folder called login and place the .JAR file I created inside.
  • Your .java files have the wrong package name.  Make sure your package name is formatted as follows with the blue part being required, the red part changed to your extension name and the green part is optional: sfs2x.extension.name_of_your_extension.src

Why do I get the .JAR cannot be found errors?

  • Your .JAR file hasn’t been placed in the right location. Go to where you’ve installed SFS, then find the extensions folder. You should have created a folder inside of the SFS extensions folder with the name of your extension. Your  .JAR file should be placed here and not in the _LIB_ folder like most of their website tells you to do (weird huh?). If anyone has an explanation for this one and cares to comment or elaborate about this oddity then please do.

Why aren’t my changes to my .JAR  going into effect?

  • If you re-build your .JAR file then you have to copy/paste it back into the extensions/your_extension_name folder. If you don’t do that SFS will never get an updated version of your code.
package sfs2x.extension.login.src;import java.sql.SQLException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.PreparedStatement;
import com.smartfoxserver.bitswarm.sessions.ISession;
import com.smartfoxserver.v2.entities.data.SFSArray;
import com.smartfoxserver.v2.core.SFSEventParam;
import com.smartfoxserver.v2.core.ISFSEvent;
import com.smartfoxserver.v2.exceptions.SFSException;
import com.smartfoxserver.v2.exceptions.SFSLoginException;
import com.smartfoxserver.v2.exceptions.SFSErrorData;
import com.smartfoxserver.v2.exceptions.SFSErrorCode;
import com.smartfoxserver.v2.extensions.BaseServerEventHandler;
import com.smartfoxserver.v2.extensions.ExtensionLogLevel;public class LoginHandler extends BaseServerEventHandler {@Override
public void handleServerEvent(ISFSEvent event) throws SFSException
{
String username = (String) event.getParameter(SFSEventParam.LOGIN_NAME);
String password = (String) event.getParameter(SFSEventParam.LOGIN_PASSWORD);ISession session = (ISession)event.getParameter(SFSEventParam.SESSION);

try {
//get a connection to the database
Connection conn = getParentExtension().getParentZone().getDBManager().getConnection();

PreparedStatement sql = conn.prepareStatement(“SELECT id, password FROM members WHERE username = ?”);
sql.setString(1, username);

// Obtain ResultSet
ResultSet result = sql.executeQuery();

//Put the result into an object array
SFSArray row = SFSArray.newFromResultSet(result);

if (password.equals(“”))
{
SFSErrorData data = new SFSErrorData(SFSErrorCode.LOGIN_BAD_PASSWORD);
data.addParameter(username);
throw new SFSLoginException(“You must enter a password.”, data);
}

if (!getApi().checkSecurePassword(session, row.getSFSObject(0).getUtfString(“password”), password))
{
SFSErrorData data = new SFSErrorData(SFSErrorCode.LOGIN_BAD_PASSWORD);

data.addParameter(username);

throw new SFSLoginException(“Login failed for user: ”  + username, data);
}

if (username.equals(“Gonzo”) || username.equals(“Kermit”))
{

// Create the error code to send to the client
SFSErrorData errData = new SFSErrorData(SFSErrorCode.LOGIN_BAD_USERNAME);
errData.addParameter(username);

// Fire a Login exception
throw new SFSLoginException(“Gonzo and Kermit are not allowed in this Zone!”, errData);
}

conn.close();
trace(“Login successful, joining room!”);

} catch (SQLException e) {
trace(ExtensionLogLevel.WARN, ” SQL Failed: ” + e.toString());
}
}
}

59 Responses

  1. Vishwas says:

    Nice tutorial, thnx.

    However i am getting this error , probably related to the jar files sfs2x.jar and sfs2x-core.jar

    Exception in thread “main” java.lang.NoClassDefFoundError: com/thoughtworks/xstream/io/HierarchicalStreamDriver
    at com.smartfoxserver.v2.SmartFoxServer.(SmartFoxServer.java:141)
    at com.smartfoxserver.v2.SmartFoxServer.getInstance(SmartFoxServer.java:133)
    at com.smartfoxserver.v2.Main.main(Main.java:24)
    Caused by: java.lang.ClassNotFoundException: com.thoughtworks.xstream.io.HierarchicalStreamDriver
    at java.net.URLClassLoader$1.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    … 3 more

  2. Vishwas says:

    ok, i would reinstall it this time. thnx.
    btw, i got this error when i tried to run your example ( that is availabe for download here)

    [SFS – INFO] Object going out:
    (byte) c: 0
    (short) a: 0
    (sfs_object) p:
    (utf_string) api: 0.9.4
    (utf_string) cl: FlashPlayer:External:WIN 10,0,2,54

    [SFS – INFO] Data written: Binary Size: 74
    12 00 03 00 01 63 02 00 00 01 61 03 00 00 00 01 …..c….a…..
    70 12 00 02 00 03 61 70 69 08 00 05 30 2E 39 2E p…..api…0.9.
    34 00 02 63 6C 08 00 22 46 6C 61 73 68 50 6C 61 4..cl..”FlashPla
    79 65 72 3A 45 78 74 65 72 6E 61 6C 3A 57 49 4E yer:External:WIN
    20 31 30 2C 30 2C 32 2C 35 34 .10,0,2,54

    [SFS – INFO] Data Read: Binary Size: 70
    48 54 54 50 2F 31 2E 31 20 34 30 30 20 42 61 64 HTTP/1.1.400.Bad
    20 52 65 71 75 65 73 74 0D 0A 43 6F 6E 6E 65 63 .Request..Connec
    74 69 6F 6E 3A 20 63 6C 6F 73 65 0D 0A 53 65 72 tion:.close..Ser
    76 65 72 3A 20 4A 65 74 74 79 28 36 2E 31 2E 32 ver:.Jetty(6.1.2
    36 29 0D 0A 0D 0A 6)….

    Error: Unexpected header byte: 72
    at com.smartfoxserver.v2.core::SFSIOHandler/handleNewPacket()[/Users/Lapo/Documents/Flex Builder 3/SFS2X_AS3_API/src/com/smartfoxserver/v2/core/SFSIOHandler.as:102]
    at com.smartfoxserver.v2.core::SFSIOHandler/onDataRead()[/Users/Lapo/Documents/Flex Builder 3/SFS2X_AS3_API/src/com/smartfoxserver/v2/core/SFSIOHandler.as:74]
    at com.smartfoxserver.v2.bitswarm::BitSwarmClient/onSocketData()[/Users/Lapo/Documents/Flex Builder 3/SFS2X_AS3_API/src/com/smartfoxserver/v2/bitswarm/BitSwarmClient.as:351]

    • Jade says:

      Did you get this error before you re-installed SmartFox 2X or after? If there’s a problem with your installation then my examples won’t work either.

  3. Vishwas says:

    May i know please, where did you download the mysql connector from. And in which folder of sfs 2x did you put it in ?
    Thanks .

  4. Mike says:

    This was a great tutorial, thanks for taking the time to write it!

    • Jade says:

      You’re welcome! It was so frustrating trying to figure it out with the SFS documentation I wanted to save someone else the headache.

  5. Angel says:

    how do i test the connection? the swf files, when i open them in firefox only has a text box and a connect button. there is no field for me to enter the login id nor password.

  6. Angel says:

    ah thanks.. is there another way to test? as i do not have the software to edit the .fla file

    • Jade says:

      @Angel – No, there isn’t for this tutorial. You’ll need a copy of Adobe Flash to be able to create games and applications for Smart Fox Server.

  7. John says:

    i followed your tutorial but I’m getting this error

    17:21:36,125 ERROR [main] db.SFSDBManager –
    ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    Exception: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException
    Message: Communications link failure

    The last packet sent successfully to the server was 0 milliseconds ago. The driv
    er has not received any packets from the server.
    Description: The DBManager Test SQL failed
    Please double check your SQL code and make sure that Database server is running.

    i’m using SFS2x RC3 with MySql 5.5 on Windows XP

    • Jade says:

      Hey John, make sure the database you’re trying to login to and access is up and running. If it is and you still have problems try re-installing SFS2x because your driver could be corrupted.

  8. John says:

    hi Jade, i realized that the connection string for my setup is jdbc:mysql://localhost:3306/game. now it connects but i’m still getting another error:

    ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    >> Zone: test
    ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

    09:15:07,172 INFO [main] Extensions – {LoginExtension}: Login extension sta
    rting.
    09:15:07,176 INFO [main] api.SFSApi – Room created: [ Room: AdminRoom, Id:
    2, Group: default, isGame: false ]
    09:15:07,181 INFO [main] core.AdminToolService – AdminTool Service started
    09:15:08,139 INFO [main] http.SFSHttpServer – Http Server started.
    09:15:08,177 WARN [main] bootLogger – Was not able to bind socket: { 127.0.
    0.1:9933, (Tcp) }
    09:15:08,180 ERROR [main] bootLogger – No bound sockets! Check the boot logs
    for possible problems!
    09:15:08,184 INFO [main] v2.SmartFoxServer – Listening Sockets:
    09:15:08,185 INFO [main] v2.SmartFoxServer –

    and the boot logs shows:

    24 Sep 2011 09:15:08,153 INFO [main] bootLogger – Session manager ready: com.smartfoxserver.bitswarm.sessions.DefaultSessionManager@1db88745
    24 Sep 2011 09:15:08,163 INFO [main] bootLogger – ReaderSelector opened
    24 Sep 2011 09:15:08,175 INFO [main] bootLogger – AcceptSelector opened
    24 Sep 2011 09:15:08,177 WARN [main] bootLogger – Was not able to bind socket: { 127.0.0.1:9933, (Tcp) }
    24 Sep 2011 09:15:08,178 INFO [main] bootLogger – Controller started: com.smartfoxserver.v2.controllers.SystemController — Queue: 0/20000
    24 Sep 2011 09:15:08,179 INFO [main] bootLogger – Controller started: com.smartfoxserver.v2.controllers.ExtensionController — Queue: 0/20000
    24 Sep 2011 09:15:08,180 INFO [main] bootLogger – IOHandler: com.smartfoxserver.v2.protocol.SFSIoHandler@61ed627d
    24 Sep 2011 09:15:08,180 INFO [main] bootLogger – SocketReader started
    24 Sep 2011 09:15:08,180 INFO [main] bootLogger – SocketAcceptor initialized
    24 Sep 2011 09:15:08,180 ERROR [main] bootLogger – No bound sockets! Check the boot logs for possible problems!
    24 Sep 2011 09:15:08,181 INFO [main] bootLogger – Socket Writer started (pool size:1)
    24 Sep 2011 09:15:08,181 INFO [Scheduler1-thread-1] bootLogger – Scheduler started: scheduler
    24 Sep 2011 09:15:08,182 INFO [main] bootLogger – Security Manager started
    24 Sep 2011 09:15:08,183 INFO [main] bootLogger – [[[ ===— Boot sequence complete —=== ]]]

    • Jade says:

      Are you sure you don’t have some other service already running on localhost like xampp or wampp? If you are then smartfox won’t start up properly. You should also check to make sure your firewall isn’t blocking it. If that still doesn’t work your best bet is to post on the SFS forums.

  9. John says:

    i solved it after some time. the caused was windows firewall blocking the port. once an exception was created it could bind to the socket.

  10. Keith says:

    Thanks for the Tutorial… Quick question, I keep getting an error from the server saying that a folder named DBlogin cannot be located (it was a custom login attempt i tried to create before coming to this one). I deleted that folder out of the extensions and replaced it with this tutorial login folder.

    When I go to the admin panel .. zone extension editor.. the login folder is still not showing up, neither is my deleted folder. What can / should i do at this point?

    Thanks

  11. Keith says:

    Yes, ive restarted the server several times. Another question on top of that one…

    The .Java files associated with the making of the jar file. Where do those need to go? In the extension folder as well?

    • Jade says:

      I know there’s a patch for 2X which might be the reason you’re having problems. In addition I’ve downloaded my settings from the SFS2X folder from where I installed it so you can copy/paste my settings into yours. Click here to download it. Just make sure you don’t delete the bat and exes from that folder then restart the server when you’ve copied everything over.

    • Jade says:

      You can save the .java files wherever you want. SFS2X only needs the packaged jar to work properly.

  12. Meenakshi says:

    Hi .. Thanks for the tutorial but I do not get my database connected.
    I get “Login extension starting.” and “Login extension stopped.” in my console once i put the jar file in Extension folder of server.

    I would like to know why this is happening and wat should i check to overcome the problem.

    • Jade says:

      Have you tried restarting SFS2X? Have you checked the logs to see if there’s an error being reported? If restarting it doesn’t fix it my guess would be that 1) your database connection info is wrong 2) your database is refusing the connection or 3) your database isn’t setup to use the correct port.

  13. Jeff says:

    Great tutorial; thanks!

  14. Gav says:

    The official SFS documentation is indeed somewhat unhelpful in this area. Having “org.gjt.mm.mysql.Driver”, for example, in a plain-text, copy and paste-able format is helpful. The official documented code is predominantly embedded in images.

    As a beginner with 2X, I was able to implement this in it’s entirety, experiencing zero problems. Everything just seems to click in to place when you follow this guide and it’s a highly recommended learning experience. It covers any and all gaps in the process of developing what I consider a sophisticated server side extension on SFS.

    Thank you very much for posting this most useful guide.

  15. manish says:

    Hi jade,

    First of all thanks for the great tutorial!

    I have got
    “{fps}: SQL Failed: java.sql.SQLException: The DBManager is NOT active in this Zone. SQL Query failed. Please activate it the DBManager from the AdminTool”

    Even thought I have Activated the Database manager from the admin area, but it sill gives me error!

    My db manager XML is as follows:

    org.gjt.mm.mysql.Driver
    jdbc:mysql://122.X.X.X:3306/quizshow
    quizshow
    quizshow
    SELECT id FROM users LIMIT 1
    10
    10
    FAIL
    3000

    Thanks and waiting for you response,
    Manish

  16. manish says:

    I had forget to add driver jar at SmartFoxServer2XSFS2Xlib,

    Now I put mysql-connector-java-5.1.20-bin.jar there, but after that I get below error:
    {fps}: SQL Failed: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure

    Please help!!!!

    • Jade says:

      Hey Manish, it sounds like your mysql database isn’t jdbc accessible. It could be that you’re running something else on the same port, the port is blocked by another program, or mysql isn’t configured to accept jdbc connections.

    • Gav says:

      Try connecting through the local machine 127.0.0.1 otherwise you might need to change your database server/user privileges to allow connections from all addresses.

  17. manish says:

    Thanks for the help,

    I have put the server and mysql database at the same location and it works fine.

    Thanks

  18. scott says:

    Thank you for the tutorial. I’ve got the whole thing running. I am using avatar chat with this. The only problem is the avatar never enters any room even when you click the rooms on the list.

    TypeError: Error #1009: Cannot access a property or method of a null object reference.
    at AvatarChat/onAvAreaClick()
    any help?

    • Jade says:

      You usually get this error when an object is null or undefined. Have you tried putting trace statements in the function to narrow down where it’s happening? It could be that your rooms list is empty or that you haven’t joined a zone properly. It could also be something else totally unrelated. What’s the code in onAvAreaClick()?

  19. scott says:

    Your tutorial is different than the source files you include with it.

  20. Scott says:

    The source file you posted are the sources from the adobe tutorial.

  21. Scott says:

    I need to set this up with the avatar chat example. The user logs in and it placed into a room but their avatar wont show up. How do I made it place the avatar in the room as well as join the room?

  22. manish says:

    Hi Jade,

    I need your help again!

    I am working on multiuser iphone game, I have written same kind of code on both the machines to calling same extension.

    When I call an extension it returns the response to all the clients.
    but at the same time another machine’s user also request for same data, due to this my counter increases and return the next game state rather then first when was needed for both the machines.

    Do we have any locking process or finding that which extension request is running on the server made by the first user, so that I will use that check, so that user2 do not request for same data.

    Please Help!!!

    Thanks in advance.

    • Jade says:

      @manish – It sounds like you need to separate your state logic from your request logic. That way when a user is requesting data it doesn’t move the game out of the proper state.

  23. Rafael says:

    Hi, thanks for the tutorial… i dont know whats happens but when I go to the Zone Extension tab my file doesnt appears in the “Name” items.

    My jar is on extension folder:
    C:Program FilesSmartFoxServer2XSFS2Xextensionsgamelogin.jar

    Do you know why i cant see the login option on extensions admin?

    Thanks

    • Jade says:

      Did you restart SFS after you moved your extension into the folder? Also, make sure you add something else to the end of the extension name in your java file so it’s along the lines of sfs2x.extension.login.src — I’ve found if you don’t put .src after the extension name it won’t always find your extension even if it exists.

  24. Scott says:

    I’m using this with Avatar Chat from SFS 2x Examples and it does not physically place the character in the room, the user enters the room but can not be seen. I get an error when I try to click anywhere to walk and when I try to type a message.

  25. Scott says:

    It works fine when the custom login is not enabled, but when I’m using your extension i get the following error when i log in.
    TypeError: Error #1009: Cannot access a property or method of a null object reference.
    at AvatarChat/onRoomJoin()
    at flash.events::EventDispatcher/dispatchEventFunction()
    at flash.events::EventDispatcher/dispatchEvent()
    at com.smartfoxserver.v2.controllers::SystemController/fnJoinRoom()
    at com.smartfoxserver.v2.controllers::SystemController/handleMessage()
    at com.smartfoxserver.v2.core::SFSProtocolCodec/dispatchRequest()
    at com.smartfoxserver.v2.core::SFSProtocolCodec/onPacketRead()
    at com.smartfoxserver.v2.core::SFSIOHandler/handlePacketData()
    at com.smartfoxserver.v2.core::SFSIOHandler/onDataRead()
    at com.smartfoxserver.v2.bitswarm::BitSwarmClient/onSocketData()

    If i try to click somewhere in the room to move it gives me this error:

    TypeError: Error #1009: Cannot access a property or method of a null object reference.
    at AvatarChat/onAvAreaClick()

    • Jade says:

      Without seeing the code for AvatarChat/onRoomJoin() my best guess would be that you haven’t retrieved the rooms list yet. SFS2X needs the rooms list before you can try and join a room. You probably accidentally removed that step when you updated the code for the custom login extension. Make sure SFS2X is successfully loading the rooms list before it triggers the joinRoomRequest. If the rooms list isn’t loaded yet then the joinRoomRequest fails and may cause the null object reference. That could also explain why the UI loads but the click/movement fails because the user has been validated through the login extension but isn’t in a room.

  26. Scott says:

    They are in the room where the list of rooms is displayed. It reads 1/20 so the avatar is in the room but is not visible.

  27. Scott says:

    I didn’t create my own extension either I used the files you linked to in the beginning. “As always you can download the working files”
    http://design1online.com/examples/flash/sfs2x_mysql_login_extension.zip

    • Jade says:

      Did you enter the sample SQL statement in your SFS admin panel and check the logs to make sure you’re properly connecting to your database? Are you sure your database is JDBC accessible and that the username/password you’re entering exist in the database? What do your SFS error logs say? It should give a more detailed explanation on why the join room request is failing.

  28. scott says:

    I have an SQL statement, it works fine there are no errors with it. My database is JDBC accessible because I can login to different accounts in my database.

  29. Scott says:

    Are you sure that theres nothing that needs to be added to the extension so it puts the avatar in the room?

    • Jade says:

      The only thing the extension is designed to do is to validate the login information exists in the database and send out an event in response to the login attempt. Everything else needs to be handled by whatever code you’re using.

  30. PyrO says:

    Hey there nice tutorial 😉
    But this part here can get an nullpointer exception

    if (!getApi().checkSecurePassword(session, row.getSFSObject(0).getUtfString(“password”), password))

    the reason why it can happen is because if you dont set a password for the db this call crashes with the said nullpointer.

    for testing/building the game locally i dont use a pw for my database so i noticed this one 😉

    here is a quick fix for it
    String dbpw;
    try {
    dbpw = row.getSFSObject(0).getUtfString(“password”);
    }
    catch(Exception e) {
    dbpw = “”;
    }
    if (!getApi().checkSecurePassword(session, “”+dbpw, password))

  31. Daniél K. says:

    I think you should before storing the results in an array check first whether a result is available.

    // Execute query
    ResultSet res = stmt.executeQuery();

    // Check if ResultSet is empty
    if(!res.next())
    {
    // Throw new exception
    throw new SFSLoginException(“Login failed, can’t find user: ” + username);
    }

    // Go back to the previous result
    res.previous();

    // Convert the ResultSet to SmartFoxServerArray
    SFSArray row = SFSArray.newFromResultSet(res);

    By the way i hope i can help anything and I’m sorry for my bad english. ^^

  32. pango says:

    Thanks alot Jade! =) Work like a charm.

  33. There is a (new?) naming convention in which the jar has to end in “Extension” e.g. “loginExtension.jar”. SFS cannot find the extension otherwise.

    Tripped me up for a while, hope this helps someone.

  34. iinakrapu43 says:

    First of all I would like to say awesome blog! I had a quick question that I’d like to ask if you don’t mind. I was curious to find out how you center yourself and clear your head prior to writing. I’ve had a difficult time clearing my thoughts in getting my thoughts out. I truly do enjoy writing but it just seems like the first 10 to 15 minutes are wasted simply just trying to figure out how to begin. Any suggestions or tips? Kudos!

    • design1online says:

      I just try to jot down all the header titles and a short blurb to summarize what I want to say in each section. Then I go back and fill in each section with more detailed content.

Leave a Reply