Embedding fonts without the transcode error

Here’s one I struggled with for the better part of an afternoon and for an hour in the morning. I got things working though.

Point of order number one: the magic solution came from this page:

http://www.flexfreaks.com/forums/viewtopic.php?id=96

from which I quote:

go to your project properties (right-click on your project would be easiest), then go to “Flex Compiler”, then under “Additional compiler arguments:” add “-managers flash.fonts.AFEFontManager”.

Next, here’s my stylesheet. Notice that I created only one fontFamily, but pointed the different weights to different TTF files:

.standardLabelText
{
	embedFonts: true;
	fontSize:12px;
	fontFamily:embedDanna;
	fontWeight: normal;
}

Button, ComboBox
{
	embedFonts: true;
	fontSize: 10px;
	fontWeight: bold;
	fontFamily: embedDanna;
}

@font-face
{
    src: url("fonts/verdana.ttf");
    fontFamily: "embedDanna";
    fontWeight: normal;
    fontStyle: normal;
}

@font-face
{
    src: url("fonts/verdanab.ttf");
    fontFamily: "embedDanna";
    fontWeight: bold;
    fontStyle: normal;
}

I was then able to use states and transformations, and the labels on the HBox I was targeting no longer hung there grinning like Cheshire cats.

As an aside, let me ask you – why does it make sense to make a developer jump through hoops to learn how to accomplish this kind of thing? You’d kind of hope that Flex would be smart enough to send you an alert or error message or email or tweet that said “Hmmm, looks like you’re trying to transform a font that’s not embedded. I can help you with that.”

Recipe: how to auto-close idle connections

Requirement:

I want to close idle connections for some applications, and make sure that connections stay open 24/7 for other applications.

Solution:

Edit the <AutoCloseIdleClients> element in my Server.xml file – then add and configure <AutoCloseIdleClients> elements in my Vhost.xml or Application.xml files. Season to taste.

Background and Analysis:

Bear with me. I’m picking my way through this.

I ran up against a situation in my home-grown connection pooling application. I noticed that connected clients – including pool-to-pool connections – were disconnecting. I also noticed that I was exceeding the 10-connection limit on the developer version of FMIS, by the way. So, I decided to get to the bottom of the issue and find out whether the disconnects were caused by the server maxing out the connection allotment, or if they were caused by some sort of timeout.

Adobe book-and-verse is a little confusing on the matter of the timeout. The config-admin guide tells me that the timeout is disabled by default. But it also tells me that the default timeout is 10 minutes.  So, which is it?

A closer inspecton reveals that if one switches the default <AutoCloseIdleClients> by merely changing the enable attribute from “false” to “true”, then you will indeed enable a global 10 minute timeout – because the Server.xml as it ships sets the MaxTimeOut to 600 seconds:

<AutoCloseIdleClients enable="false">
    <CheckInterval>60</CheckInterval>
    <MaxIdleTime>600</MaxIdleTime>
</AutoCloseIdleClients>

All this seems pretty straightforward, I guess. But then again, the way the documentation is written, it makes it seem like there’s a 10-minute timeout lurking around even if <AutoCloseIdleClients> is not enabled.

I’m conducting an informal inquiry at the moment – I’ve got a bunch of clients connected to my pool They’ve been idle for about 30 minutes now. None have disconnected of their own accord – so I guess I can conclude that there is no 10-minute default lurking somewhere in the background. Enabled=”false” means enabled=”false”.

But it does raise the question for me: if I did want to enable an auto timeout for a client, but not for the pool, how would I go about doing that?

What I might try goes as follows:

Server.xml – flip AutoCloseIdleClients enabled to true. Maybe even give it a massive, healthy timeout value, say, 60 minutes. (Question for Adobe: other that enabled=false, is there a value for “infinity – and beyond”? How about -1?….)

Pool application: set AutoCloseIdleClients enabled to false in the Application.xml file. That way, the pool never hangs up its connections due to timeout.

Client application: set AutoCloseIdleClients to true, and feed it my timeout value in the Application.xml file.

In theory, this should work. Guess we’ll see…

Not working as advertised

Adobe documentation, book and verse:

The availability and number of debugging sessions is set in the AllowDebugDefault and MaxPendingDebugConnections elements of the Application.xml configuration file. By default, debugging is not allowed. To override the debug setting in the Application.xml file, add the following code to an application’s server-side code:
application.allowDebug = true;

(Developer’s guide for 3.5)

And:

1 Open the Application.xml file of the virtual host or application you want to configure.
2 Locate the following XML:
<Debug>
<MaxPendingDebugConnections>50</MaxPendingDebugConnections>
<AllowDebugDefault>false</AllowDebugDefault>
</Debug>
3 Set the AllowDebugDefault element to true.
Note: Debug connections count against license limits.
4 Save and validate the file.
5 Restart the server.

(Configuration and Administration Guide for 3.5)

But yet, when I try these soutions and look at my shared obejcts, I get this in the server log:

Mon 07:41:05 AM: Connection rejected by server. Reason : [ Server.Reject ] : Invalid uri :
rtmp:///fabCustomer/penny?_fcs_debugreq_=72139185

When I solve this, I’ll post the solution. I found another post out there after hours of Googling – basically a “Me Too” post that no one answered. I’m connecting with 2 clients, so I should have enough connections to debug with before I hit the max of 10 on the developer’s license.

Grrrr.

More FMS tidbits

From flashemdiaserver_config_admin.pdf, page 43:

Note: If the shared object is available for debugging the application, the Administration Console displays its properties.
If the shared object is not available for debugging, an error message is displayed.

This would explain why I see no data displayed when I look at ShreadObjects in the Admin console. Guess it pays to real all the documentation, even the bits you aren’t interested in.

A quick look at flashmediaserver_SSLR.pdf yields this:

application.allowDebug
A boolean value that lets administrators access an application with the Administration API
approveDebugSession() method (true) or not (false). A debug connection lets administrators view information
about shared objects and streams in the Administration Console.
The default value for this property is false and is set in the Application.xml file:
<Application>

<Debug>
<AllowDebugDefault>false</AllowDebugDefault>
</Debug>

</Application>
Setting application.allowDebug to true in a server-side script overrides the value in the Application.xml file.
Availability
Flash Media Server 2

We’ll give it a try. Stay tuned.

Also overlooked this one, for future reference:

switch (cnEvt.info.code) {

case “NetConnection.Connect.Success”:
// … do stuff
break;

case “NetConnection.Connect.AppShutdown”:
// … do shutdown stuff
break;

case “NetConnection.Connect.Closed”:
// … do something
break;

Turns out that “Closed” gets called before “AppShutDown” (capitalization critical here) – so I neglected to write a case for “Closed” in earlier code – what was I thinking? Putting a trace on my event.info.code helped me catch that.

Flash and Remote Shared Objects: ChangeList demystified

Demystified for the benefit of my own understanding of course. Maybe if I take it step-by-step it will make some sense. I’ve been reading “Learning Flash Media Server 3” and I find I’m reading the same part over and over. I figure if I write it in my own words it’ll start to sink in.

Consider the following code:

ballSO = SharedObject.getRemote("ballSO", myNC.uri, false);
ballSO.connect(myNC);
ballSO.addEventListener(SyncEvent.SYNC, updateBallPos);

So, here we have ballSO created on the Flash Media Server, and we’ve added an EventListener to is, so that every time the SharedObject on the Flash Media Server changes, we can catch a SYNC event and do some stuff in our application. As is says in the book: “Whenever a client changes a shared object’s data property, the action invokes a sync event”.

Another way of say this is: whenever a client uses setProperty() to register a state change on a SharedObject, the following happens:

· The SharedObject’s data property changes in some way

· The SharedObject calls setDirty(), which informs the FMS that the value of a property in the SharedObject has changed

But back to our event listener.

The thing that makes SyncEvent stand out among other EventListeners is its changeList property:

  • The changeList is an array of objects.
  • Each object in the changeList array “contains properties that describe the changed members of a remote shared object”.
  • The properties of each changeList array object are:
    • code
    • name
    • oldValue

The code property is of special interest; It allows us to figure out what’s happening on the server. When we initially create our SharedObject, all the properties are initialized to empty strings.


Here are the values that code can have (with my shorthand explanation):

  • clear – either you just connected successfully, or all properties of the object have been deleted
  • success – the client (you) have changed the SO
  • reject – the client (you) did not successfully change the SO
  • change – another client (not you) has changed the SO
  • delete – the object you’re trying to change not longer exists

Here’s a basic implementation of our SyncEvent handler function:


private function updateBallPos(se:SyncEvent):void {
   for(var i:int = 0; i < se.changeList.length; i++) { 
     if (se.changeList[i].code == "change") {
       switch (se.changeList[i].name) {
         case "xPos":
           this.x = ballSO.data.xPos;
           break;
 
         case "yPos":
           this.y = ballSO.data.yPos;
           break;
      } 
    }
  }

}

OK – we loop through our SyncEvent (“se”) looking for an object in the changeList whose code is “change”. Then we’re using a switch construct to look for the value of that object’s “name” attribute that matches something that we want to change or keep in sync.

So – and here’s the part that has me wrapped around the axle – we update our local client based on the a value of the SharedObject’s data object.

OK so – if we consider ballSO.data as (what we would call in Perl) an associative array (or hash), then we can get to dynamically created data using something like the technique in the switch cases in this code snippet:


 var currentDataIndex:String;
 
 // note: the string myName is defined in the class constructor

 for(var i:int = 0; i < se.changeList.length; i++) {
   if (se.changeList[i].code == "change") {
     switch (se.changeList[i].name) {
       case myName + "xPos":
         currentDataIndex = myName + "xPos";
         this.x = ballSO.data[currentDataIndex];
         break;
 
       case myName + "yPos":
         currentDataIndex = myName + "yPos";
         this.y = ballSO.data[currentDataIndex];
         break;
       } 
     }

Of course, defensive programming would have us write cases for all the conditions:


if(se.changeList[i].code == "success") { ... }
if(se.changeList[i].code == "reject") { ... }

Always reinventing the wheel

I fired up Eclipse yesterday, since I’m working with a j2ee developer who mentioned the Spring framework. Being the curious person that I am, I once again thought maybe it would be a good idea to dip my toe in the water.

Being – OK I admit it – middle-aged, I often forget stuff that I’ve done recently. So I was pleasantly surprised to see that I had a relatively recent version of Eclipse (Ganymede) up and running, and that I had even done some “HelloWorld” type stuff a few months ago. (Case in point, I went upstairs to fix the toilet chain, and found evidence that I had done so previously. Totally gone from my memory. Vanished. But based on the materials, I could tell it was me had done it. But I digress….)

So, I found I had written the following code, which is way cooler that HelloWorld:

package com.sendai77.hello;
import javax.servlet.*;
import javax.servlet.http.*;
import java.sql.*;
import javax.sql.*;
import javax.naming.*;

public class HelloDB extends HttpServlet {
    DataSource pool;
    public void init() throws ServletException {
        Context env = null;

        try {
            env = (Context) new InitialContext().lookup("java:comp/env");

            pool = (DataSource) env.lookup("jdbc/TestDB");

            if (pool == null){
                throw new ServletException ("null pool: TestDB is an unknown datasource");
            }
        }

        catch (NamingException ne){
            throw new ServletException(ne.getMessage());
        }
    }


    public void doGet (HttpServletRequest req, HttpServletResponse resp) throws ServletException, java.io.IOException {

        String theSQL = "select * from test_users";
        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;
        //ResultSetMetaData rsm = null;

        resp.setContentType("text/html");

        java.io.PrintWriter out = resp.getWriter();

        out.println("<html>");
        out.println("<head><title>Hello Database</title></head>");
        out.println("<body>");
        out.println("<h2>Hello, Database!</h2>");

        try {
            // get the connection pool
            conn = pool.getConnection();
            // make the stmt
            stmt = conn.createStatement();
            // execute the query
            rs = stmt.executeQuery(theSQL);
            // get the metadata
            //rsm = rs.getMetaData();

            while(rs.next()){
                out.println("<p>" + rs.getString(1) + " " + rs.getString(2) + " " + rs.getString(3) + "</p>");
            }
        }

        catch (Exception e) {
            throw new ServletException(e.getMessage());
        }

        finally  {
            try{
                if (stmt != null){
                    stmt.close();
                }
                if (conn != null){
                    conn.close();
                }
            }
            catch (Exception sqle) {
                throw new ServletException(sqle.getMessage());
            }
        }


        out.println("</body>");
        out.println("</html>");
    }

    public void doPost (HttpServletRequest req, HttpServletResponse resp)  throws ServletException, java.io.IOException {
        doGet(req, resp);
    }
}

Nothing terribly new and exciting here, except I couldn’t for the life of me recall how to set Tomcat up to resolve the jdbc call. So I’m writing this post to remind myself.

Looking in the META-INF folder for this webapp I find a file called “context.xml” which has the following content:

<?xml version="1.0" encoding="UTF-8"?>

<Context path="/hello" docBase="hello"
        debug="5" reloadable="true" crossContext="true">

    <!-- maxActive: Maximum number of dB connections in pool. Make sure you
         configure your mysqld max_connections large enough to handle
         all of your db connections. Set to 0 for no limit.
         -->

    <!-- maxIdle: Maximum number of idle dB connections to retain in pool.
         Set to -1 for no limit.  See also the DBCP documentation on this
         and the minEvictableIdleTimeMillis configuration parameter.
         -->

    <!-- maxWait: Maximum time to wait for a dB connection to become available
         in ms, in this example 10 seconds. An Exception is thrown if
         this timeout is exceeded.  Set to -1 to wait indefinitely.
         -->

    <!-- username and password: MySQL dB username and password for dB connections  -->

    <!-- driverClassName: Class name for the old mm.mysql JDBC driver is
         org.gjt.mm.mysql.Driver - we recommend using Connector/J though.
         Class name for the official MySQL Connector/J driver is com.mysql.jdbc.Driver.
         -->

    <!-- url: The JDBC connection url for connecting to your MySQL dB.
         The autoReconnect=true argument to the url makes sure that the
         mm.mysql JDBC Driver will automatically reconnect if mysqld closed the
         connection.  mysqld by default closes idle connections after 8 hours.
         -->

  <Resource name="jdbc/TestDB" auth="Container" type="javax.sql.DataSource"
               maxActive="100" maxIdle="30" maxWait="10000"
               username="tester" password="password" driverClassName="com.mysql.jdbc.Driver"
               url="jdbc:mysql://localhost:3306/test?autoReconnect=true"/>

</Context>

So there it is. The only mystery remaining to me is: did Eclipse generate this file? Did I cadge it from Tomcat? Did I google it up?….

handy stuff i’d like to remember