Server Connections

In a PureWeb application, the service and the client are separate entities that communicate with each other over the Internet through the web server. Logically, therefore, the first steps of implementing the APIs revolve around setting up the connections between these components. This will allow you to interact with your service from your client as you progress through your application's development.

Connection Workflow

There are two basic connection workflows for PureWeb applications, one for managed services and one for unmanaged services.

In a managed service, the PureWeb server is responsible for starting and stopping the service when the client first connects. In this scenario, the connections follow this basic workflow:

  • The client requests a session from the server.
  • The server responds by launching the service.
    • This is done automatically by the server. The server manages applications using its plug-in architecture.

  • The service, on startup, connects to the server and establishes the session.
    • The code for connecting the service creates and initializes in particular StateManagerServer, which handles all communications with the server.

  • The client code is sent to the end user's browser.

  • The client connects to the established session.
    • The client uses an event listener to determine when the service has established the session. For more information on events that the client can listen to, see Useful PureWeb Events.

The diagram below illustrates the connections workflow for a managed service with an HTML5 client.


The basic application connection workflow for an unmanaged service is as follows:

  • An external entity (the end user, or another process or application) launches the service, outside of the PureWeb server.
    • In the code, the Start method must provide the IP address of the server as a parameter, as well as the port that the server uses to receive connections from the service.

  • The service, on startup, connects to the server and establishes the session.
    • The code for connecting the service creates and initializes StateManagerServer, which handles all communications with the server.

    • The service is now recognized by the server as a queued unmanaged application.
  • The client connects to the established session.
    • The client uses an event listener to determine if the service has established the session.

Application URLs

The PureWeb SDK supports different URL schemes for launching and connecting the client.

Launch URL

The launch URL can follow one of two schemes. These are referred to as the "app" and the "view" URL schemes, named this way because of the last element in their respective path:

http://localhost:8080/pureweb/app?...

http://localhost:8080/pureweb/view?...

The key difference is in the workflow:

  • When you launch your client by providing an app URL in your browser, the PureWeb server starts the service application right away, and then it delivers the necessary client files (.html, .js, .css) to the browser. When the connect method is called in the client, the service application is already running, and the connection is completed.
  • When you launch your client by providing a view URL, the PureWeb server delivers all the necessary client files to your browser (.html, .js, .css), but nothing more. The service application will not get started until the client converts the view URL to an app URL and calls the connect method with this new URL. This gives you the added flexibility of displaying the client in the browser without being connected to the service.

Launching a client using an app URL is still supported for legacy reasons, but it is recommended to always launch your application using a view URL instead.

URL Parameters

Regardless of whether you use an app or a view URL, the supported parameters are the same:

[protocol]://[host:port]/pureweb/[URL scheme]?name=[appname]&client=[client]&_diagnostics=[true or false]&unmanaged=[true or false]

where:

  • URL Scheme is either app or view.
  • appname is the name of the service application. This name must match the name that you provide in the application's plug-in file. Although it does not strictly have to match the name of the application that you provided when you initialized the StateManager object in your service, it's a good idea to be consistent across the board.
  • client is a parameter which is mandatory for client applications that are not native apps of mobile devices. Accepted values are flex, silverlight, and html5. For native mobile apps (Android, iOS), simply omit the parameter.
  • The _diagnostics parameter is optional. If specified with the value true, the client application will open with the Diagnostics Panel enabled. This panel is useful during client development, but you would typically not include it in a production application.
  • The unmanaged=true parameter is mandatory if connecting to an unmanaged service. For managed services, you can simply omit this parameter altogether.
  URLs must be encoded and compliant with RFC-3986. Invalid characters could prevent the service from starting or cause other unexpected results.

URL Format for Connecting the Client

The client-side connect method expects an app URL; if you launched your client using a view URL (recommended), the SDK will automatically convert it to an app URL when it connects the client.

Connecting the Service

Whether you intend to deploy the service as managed or unmanaged, the code for establishing the connection to the PureWeb server is essentially the same. It involves initializing the StateManagerServer and StateManager classes and calling the Start method.

Although the code for connecting the service is relatively short, it is responsible for implementing much of the behind-the-scene details that make PureWeb applications work smoothly and shelter developers from the burden of managing the complexities of image remoting and synchronized application state management.

When connecting an unmanaged service, you must specify the IP address and port of the server; this is not necessary when connecting a managed service.

The code below illustrates how to connect a service to the PureWeb server.

C++

int main(int argc, char *argv[])
{
    CSI::CountedPrt<CSI::PureWeb::Server::StateManagerServer> server;
    CSI::CountedPrt<CSI::PureWeb::Server::StateManager> StateManager;

    // Ini CSI / PureWeb libraries
    CSI::Library::Initialize();
    CSI::Threading:UiDispatcher::InitMessageThread();    //this thread is the UI thread

    //Create PureWeb object instances
    server = new CSI::PureWeb::Server::StateManagerServer();
    StateManager = new CSI::PureWeb::Server::StateManager("Scribble");

    if (argc > 1 && QString(argv[1]).contains("PureWeb", Qt::CaseInsensitive))
    {
        stateManager->PluginManager().RegisterPlugin("QtMessageTickler", new QtMessageTickler());
        server->Start(stateManager.get());
        server->ShutdownRequested() += PureWebCommon::OnPureWebShutdown;
    }

This code accomplishes the following:

  • Declares the StateManagerServer object in the main function (line 3). This implements an input and output thread to receive input and commands from the client, as well as to send responses to clients.
  • Declares the StateManager object in the main function (line 4). This class is responsible for much of the behind-the-scene code that makes PureWeb applications work smoothly: it is responsible for creating and updating application state, responding to input events and commands sent from the client, and generating responses such as updated images in views to send back to the client application.
  • Initializes the StateManager class with the service application's name (line 12).
  • Starts the server using the Start method (line 17).
  • To connect an unmanaged service, you would provide the IP address and port parameters on this line:

    server.Start(StateManager, IPAddress.Parse([server_ip], [port]);

    The default port that the PureWeb server uses to receive connections from the service is TCP port 8082. You can change this value, see Configuring the Ports.

.Net

static class Program
 {
    public static PureWeb.Server.StateManager StateManager;
    [STAThread]
    static void Main()
    {
         StateManager = new PureWeb.Server.StateManager ("MyApp", Dispatcher.CurrentDispatcher);
         StateManager.Uninitialized += new EventHandler(StateManager_Uninitialized);

         StateManagerServer server = new StateManagerServer();
        if (!string.IsNullOrEmpty(System.Environment.GetEnvironmentVariable("PUREWEB_PORT")))
        {
              server.Start(StateManager);
         }
    }
         static void StateManager_Uninitialized(object sender, EventArgs e)
     {
        Application.Exit();
     }
}			

This code accomplishes the following:

  • Declares a static instance of the StateManager class (line 3), so that it can be used globally by the rest of the application. This class is responsible for much of the behind-the-scene code that makes PureWeb applications work smoothly: it is responsible for creating and updating application state, responding to input events and commands sent from the client, and generating responses such as updated images in views to send back to the client application.
  • Initializes the StateManager class with the service application's name (line 7).
  • Adds an event handler to the PureWeb session uninitialization event, to allow for graceful disconnect (line 8).
  • Creates and initializes an instance of the StateManagerServer class (line 10). This implements an input and output thread to receive input and commands from the client, as well as to send responses to clients. Assuming the PUREWEB_PORT environment variable is defined, this starts the PureWebsession.
  • Starts the server using the server.start method (line 14).
  • To connect an unmanaged service, you would provide the IP address and port parameters on this line:

    server.Start(StateManager, IPAddress.Parse([server_ip], [port]);

    The default port that the PureWeb server uses to receive connections from the service is TCP port 8082. You can change this value, see Configuring the Ports.

  • Provides the uninitialization event handler, which shuts the application down when the session is terminated (line 17).

Java

public static void main(String[] args) throws StartupException, InterruptedException 
{
     // create state manager and server and start
    stateManager = new StateManager("ScribbleAppJava");

    server = new StateManagerServer();
    stateManager.addUninitializedHandler(new EventHandler<EmptyArgs>()
    {
        public void invoke(Object sender, @SuppressWarnings("hiding") EmptyArgs args)
        { 
            System.exit(0);
        }
      });
    server.start(stateManager);
}			

This code accomplishes the following:

  • Creates an instance of the StateManager class and initializes this class with the service application's name (line 4). This class is responsible for much of the behind-the-scene code that makes PureWeb applications work smoothly: it is responsible for creating and updating application state, responding to input events and commands sent from the client, and generating responses such as updated images in views to send back to the client application. The StateManager accomplishes this by using a collection of plug-ins such as XmlStateManager, CommandHandler, and ViewManager.
  • Creates and initializes an instance of the StateManagerServer class (line 6). This implements an input and output thread to receive input and commands from the client, as well as to send responses to clients.
  • Adds an event handler to the PureWeb session uninitialization event, to allow for graceful disconnect (line 7).
  • Starts the server using the server.start method (line 14). This starts the input/output thread running.
  • To connect an unmanaged service, you would provide the IP address and port parameters on this line:

    server.start(stateManager, [server_ip], [port]);

    The default port that the PureWeb server uses to receive connections from the service is TCP port 8082. You can change this value, see Configuring the Ports.

You can also configure rules for service-server interactions, specifically timeout values, in the PureWeb server configuration files. For more information, see Service-Server Interaction Properties.

Connecting the Client

In the client-side code, there are three main segments to implementing a connection to the server:

  • Determine when the service's connection becomes active. To accomplish this, the client application uses listeners and handlers for the events automatically raised by the WebClient object. Typically, the handlers will define a response for each distinct connection status (active, disconnected, stalled, etc.).
  • Generate a URL that targets the correct server and specifies the client platform.
  • Use the construed URL in conjunction with the client API's connect method to actually establish the connection and display the client application's main page.

In the example below, the server authentication credentials are hard-coded into the application for illustration purposes. In a production application, you would likely handle authentication by using a custom login page.

iOS

Your view controller should use the <PWWebClientDelegate> protocol:

@interface MasterViewController : UIViewController <PWWebClientDelegate>

You should then implement the following methods:

  • (void)connectedChanged;
  • (void)sessionStateChanged;

At this point, you can connect:

PWFramework *framework = [PWFramework sharedInstance];
 framework.client.delegate = self;
// Setup the authentication info
PWBasicAuthorizationInfo  *authInfo = [PWBasicAuthorizationInfo basicAuthorizationWithName:@"myusername" password:@"mypassword"];
framework.client.authorizationInfo = authInfo;
// Connect
[framework.client connect:@"http://myhostname:8080/pureweb/app?name=ScribbleApp"];
					

The callbacks connectedChanged and sessionStateChanged will be called.

Silverlight

Framework.Instance.Client.IsStalledChanged += new EventHandler(Client_IsStalledChanged);
Framework.Instance.Client.SessionStateChanged += new EventHandler(Client_SessionStateChanged);
            
void Client_IsStalledChanged(object sender, EventArgs e)
{
string message = Framework.Instance.Client.IsStalled ? "Stalled" : "Not stalled";
Trace.WriteLine(message);
}

void Client_SessionStateChanged(object sender, EventArgs e)
{
    if (Framework.Instance.Client.SessionState == SessionState.Failed)    
        {
            Framework.Client.Disconnect();
            MessageBox.Show("The connection to the server has been closed.");
        }
        {
            MessageBox.Show("You are now logged out and disconnected.");
        }
     else if (Framework.Instance.Client.SessionState == SessionState.Connecting)
        {
            MessageBox.Show("You are now logged out and disconnected.");
        }
        else if (Framework.Instance.Client.SessionState == SessionState.Active)
            {
            if (Framework.Client.IsConnected)
                {
                    // Bring the user to your application's main page.
                 }
            }
        }

System.Diagnostics.Debug.Assert(HtmlPage.IsEnabled);
// Get the current URL from the browser window
var href = (string)HtmlPage.Window.Eval("document.location.href");
// Start a new session with default credentials
Framework.Instance.Client.AuthorizationInfo = new BasicAuthorizationInfo() { Name = "admin", Password = "admin" };
// Call the PureWeb framework's connect method using the URL you created
Framework.Instance.Client.Connect(href);    

In line 1, the code adds a handler for stalled connections on the server (Client_IsStalledChanged).

In line 2, the code adds a handler to determine what state the session is in (Client_SessionStateChanged).

In lines 4 - 8, the code defines the content of the handler for stalled connections (Client_IsStalledChanged). In this example, the handler simply logs the event.

In lines 10 - 31, the code defines the content of the handler for changed session status (Client_IsStalledChanged). The handler determines the action that the application must perform for each state. For the sake of keeping the example simple, the code for each case (failed, disconnecting, etc.) alerts the user of the current state with message boxes, but actual applications would be expected to properly handle changes in session state.

Lines 34 - 40 establish the connection to the PureWeb server. This code must be placed after the initialization code.

You can configure rules for client-server interactions in the PureWeb server configuration files, such as client activity timeout and user process limit. For more information, see Client-Server Interaction Properties.