0

GWT Google Map (Static and Dynamic)

In my project, my client want to use Google map.
I had put the Google Map V3 but due to poor internet connection, the retrieval time is very slow. They want to use static map.

I decide to create an option for them to choose whether to use dynamic or static Google map. To change between dynamic and static just simply change the instance.

The dynamic map, I use a library from http://code.google.com/p/gwt-google-maps-v3/

SitemapPanel.java
package com.vcari.jscadav2.client;

import com.extjs.gxt.ui.client.widget.LayoutContainer;
import com.google.gwt.user.client.Element;

public abstract class SiteMapPanel extends LayoutContainer{

    @Override
    protected void onRender(Element parent, int index) {
        super.onRender(parent, index);
    }
    
     public abstract void setMapCenter(Double latitude, Double longitude, int zoomLevel);
}



SiteMapStaticMapPanel.java (Static Map)
This solution is working for GWT 2.4. Please refer to my new post below for solution. http://peyotest.blogspot.com/2011/09/gwt-24-static-google-map-in-frame-not.html

package com.vcari.jscadav2.client;

import com.extjs.gxt.ui.client.widget.layout.FitLayout;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.ui.Frame;

public class SiteMapStaticMapPanel extends SiteMapPanel {

    public SiteMapStaticMapPanel(){
        super();
    }    
    
    Frame frame = new Frame();

    @Override
    protected void onRender(Element parent, int index) {
        super.onRender(parent, index);
        setLayout(new FitLayout());
        setBorders(false);
        add(frame);
    }
    
    /**
     * Set map center to the defined latitude and longitude
     * @param latitude
     * @param longitude
     */
    public void setMapCenter(Double latitude, Double longitude, int zoomLevel) {                
       Integer width=this.getWidth();
       Integer height=this.getHeight();
       String url="http://maps.google.com/maps/api/staticmap?center={0},{1}&zoom={2}&size={3}x{4}&maptype=roadmap&sensor=false";
       url+="&markers=color:red7C%{0},{1}";
       url=String.format(url, latitude,longitude,zoomLevel,width,height);
       url=url.replace("{0}", latitude.toString());
       url=url.replace("{1}", longitude.toString());
       url=url.replace("{2}", String.valueOf(zoomLevel));
       url=url.replace("{3}", width.toString());
       url=url.replace("{4}", height.toString());
       url=url.replace("{5}",  Application.areaName);
      
       frame.setUrl(url);
    }
}



Dynamics Google Map Version 3

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.vcari.jscadav2.client;

import com.extjs.gxt.ui.client.widget.layout.FitLayout;
import com.google.gwt.maps.client.MapOptions;
import com.google.gwt.maps.client.MapTypeId;
import com.google.gwt.maps.client.MapWidget;
import com.google.gwt.maps.client.base.LatLng;
import com.google.gwt.maps.client.overlay.Marker;
import com.google.gwt.user.client.Element;

/**
 *
 * @author peyo
 */
public class SiteMapV3Panel extends SiteMapPanel {

    private Marker marker;
    private MapWidget mapWidget;

    public SiteMapV3Panel() {
        setLayout(new FitLayout());
                      
        final MapOptions options = new MapOptions();
        // Zoom level. Required
        options.setZoom(8);
        // Open a map centered on Cawker City, KS USA. Required
        options.setCenter(new LatLng(5.519216, 116.822204));
        // Map type. Required.
        options.setMapTypeId(new MapTypeId().getRoadmap());

        marker=new Marker();
        
        // Enable maps drag feature. Disabled by default.
        options.setDraggable(true);
        // Enable and add default navigation control. Disabled by default.
        options.setNavigationControl(true);
        // Enable and add map type control. Disabled by default.
        options.setMapTypeControl(true);
        mapWidget = new MapWidget(options);
        mapWidget.setSize("800px", "600px");
        add(mapWidget);
    }
    
   
    @Override
    protected void onRender(Element parent, int index) {
        super.onRender(parent, index);
    }

    /**
     * Set map center to the defined latitude and longitude
     * @param latitude
     * @param longitude
     */
    public void setMapCenter(Double latitude, Double longitude, int zoomLevel) {                
        mapWidget.getMap().setZoom(zoomLevel);
        mapWidget.getMap().panTo(new LatLng(latitude, longitude));
        marker.setPosition(new LatLng(latitude, longitude));
        marker.setMap(mapWidget.getMap());
        marker.setTitle(Application.areaName);
    }
}

2

PHP Fatal error: date(): Timezone database is corrupt - this should *never* happen!

When I tried to execute a script that using date function on my Vortex, i got this error message.

"PHP Fatal error: date(): Timezone database is corrupt - this should *never* happen!".

Actually, this happened a long time ago, but only today I gave my efficient time tried to solve this problem. Luckily,I found the solution with just a few minutes.

Solution :

Make sure that web server(I'm using lighttpd on vortex) has enough access to read
/etc/localtime
/usr/share/zoneinfo

if localtime is not exist, you can copy the file from any Linux system.
1

GXT Remote Paging With GWT RPC

This code example shows how to make GXT grid with remote paging to work with GWT RPC.That's means you can use POST to send the request. I'm not sure whether it can be done before.

To do that,we need just need to use RpcProxy and override the load method.

Anyway, I put the sample code below.
I take it from GXT demo code.

final ExampleServiceAsync service = (ExampleServiceAsync) Registry.get(Examples.SERVICE);
RpcProxy<PagingLoadResult<Post>> proxy = new RpcProxy<PagingLoadResult<Post>>() {

    @Override
    public void load(Object loadConfig, AsyncCallback<PagingLoadResult<Post>> callback) {
        service.getPosts((PagingLoadConfig) loadConfig, callback);
    }
};

// loader  
final PagingLoader<PagingLoadResult<ModelData>> loader = new BasePagingLoader<PagingLoadResult<ModelData>>(proxy);
loader.setRemoteSort(true);
ListStore<Post> store = new ListStore<Post>(loader);

GXT ModelData Cloning

It's easy to clone a GXT ModelData.

 public static void cloneModelData(ModelData source, ModelData dest) {
        Iterator<String> iterator = source.getPropertyNames().iterator();
        while (iterator.hasNext()) {
            String key = iterator.next();
            dest.set(key, source.get(key));
        }
    }
0

PHP XML-RPC Client Simplified

In my previous for XML-RPC client helper, I suggested to create a client instance to make your methods exposed and developer friendly. But may be some of us are too lazy write all the wrapper code. There is solution for that.

In this case you still need to create client instance which extends XMLRPCClientHelper, but this time you don't need to write all the wrapper code. Just simply add __call overload methods.

It's easy but you need to remember the service API.

Here is the code:

<?php
class TestXMLRPCClientSimplified extends XMLRPCClientHelper {
    public function __call($name, $arguments) {
        return $this->sendRequest("$name", $arguments);
    }    
}
?>

0

PHP XML-RPC Client Helper

I wrote a helper for XMLRPC client.
I also added the automatic base64 type setting for bytes data.
Just need to create the client instance and supply the service URL, then you can start to call the service.

To make you client methods is expose and developer friendly, you can create your own client class which extends XMLRPCClientHelper.

<?php
class TestXMLRPCClient extends XMLRPCClientHelper {

    /**
     * Add two number
     * @param <int> $A
     * @param <int> $B
     * @return <int>
     */
    public function add($A, $B) {
        $params = array($A, $B);
        return $this->sendRequest("add", $params);
    }
}
?>


Here is the simple example :

$url = "http://192.168.56.1:5678/service.rem";
$client = new TestXMLRPCClient();
$client->setURL($url);
$result=$client->add(1,4);  //test add
print "Add Result: $result <br>\n";

It also support the exception when there is any error occurs it will throw the exception.So you just need to use try and catch to handle that.

XMLRPCClientHelper.php. This file also included in my training materials on my previous post.

<?php

/**
 * This helper class help to create a simple XML-RPC client
 * @author Mohamad Fairol Zamzuri B Che Sayut <mfz_peyo@yahoo.com>
 */
class XMLRPCClientHelper {

    private $url;

    /**
     * Get URL
     */
    public function getURL() {
        return $this->url;
    }

    /**
     * Set URL
     * @param <string> $url URL
     */
    public function setURL($url) {
        $this->url = $url;
    }

    /**
     * Send RPC request
     * @param <string> $methodname method name
     * @param <array> $parameters parameters
     */
    public function sendRequest($methodname, $parameters) {
        for ($i = 0; $i < count($parameters); $i++) {
            if (mb_detect_encoding($parameters[$i]) === false) {
                xmlrpc_set_type(&$parameters[$i], "base64");
            }
        }
        $request = xmlrpc_encode_request($methodname, $parameters);
        $context = stream_context_create(array('http' => array(
                        'method' => "POST",
                        'header' => "Content-Type: text/xml",
                        'content' => $request
                        )));
        $file = file_get_contents($this->url, false, $context);
        $response = xmlrpc_decode($file);
        if (is_array($response) && xmlrpc_is_fault($response)) {
            throw new Exception($response['faultString'], $response['faultCode']);
        }
        return $response;
    }

}

?>

0

PHP XML-RPC Server Helper

I wrote a XMLRPCServerHelper to help me to create XML-RPC service in PHP.
It's easy to use and you just need to set the classname of service and all the methods will be extracted automatically using ReflectionClass.

The example of the server :

<?php
error_reporting(E_ERROR | E_PARSE);
require_once("autoload.php");

$server = new XMLRPCServerHelper();
$server->setClassName("TestXMLRPCService");
$answer = $server->handle();
header('Content-Type: text/xml');
print($answer);
?>


The service can be access from your normal webserver url.
To generate php client class, just simply add ?phpwrapper to the url. E.g :

 http://localhost/xmlrpc/server.php?phpwrapper


XMLRPCServerHelper.php . This file also incuded in my training materials on my previous post.

<?php

/**
 * This helper class help to create XML-RPC server
 */
class XMLRPCServerHelper {

    /**
     * Server handler holder
     * @var <Object> Server handler holder
     */
    private $serverHandler;
    /**
     * Class name holder
     * @var <string> Class name holder
     */
    private $classname;
    /**
     * External function list holder
     * @var <array>  External function list holder
     */
    private $externalFunctions;

    /**
     * Contructor
     */
    public function __construct() {
        $this->serverHandler = xmlrpc_server_create();
        $this->externalFunctions = array();
    }

    /**
     * Set object class.
     * All class methods will be extracted and registerd automatically
     * @param <Object> $class
     */
    public function setClassName($classname) {
        $this->classname = $classname;
        $reflection = new ReflectionClass($classname);
        $methods = $reflection->getMethods();
        $props = $reflection->getProperties(ReflectionProperty::IS_PUBLIC | ReflectionProperty::IS_PROTECTED);
        for ($i = 0; $i < count($methods); $i++) {
            $reflectmethod = $methods[$i];
            $methodname = $reflectmethod->name;
            $reflectparams = $reflectmethod->getParameters();
            if (count($reflectparams) > 0) {
                for ($j = 0; $j < count($reflectparams); $j++) {
                    $methodparams[] = $reflectparams[$j]->name;
                }
            } else {
                $methodparams = array();
            }
            $this->registerMethod($methodname, array(&$classname, $methodname), $methodparams);
        }
    }

    /**
     * Generate client wrapper
     */
    private function generatePHPClientWrapper() {
        $classfunctions = "";
        $reflection = new ReflectionClass($this->classname);
        $methods = $reflection->getMethods();
        $props = $reflection->getProperties(ReflectionProperty::IS_PUBLIC | ReflectionProperty::IS_PROTECTED);
        for ($i = 0; $i < count($methods); $i++) {
            $reflectmethod = $methods[$i];
            $methodname = $reflectmethod->name;
            $reflectparams = $reflectmethod->getParameters();
            $funcParams = "";
            $funcContent = "";
            if (count($reflectparams) > 0) {
                for ($j = 0; $j < count($reflectparams); $j++) {
                    //$funcContent.= "\$params[] = \$" . $reflectparams[$j]->name . ";\n";
                    if ($funcParams != "") {
                        $funcParams.=",";
                    }
                    $funcParams.='$' . $reflectparams[$j]->name;
                }
                $funcContent = "\$params = array($funcParams);\n";
            } else {
                $funcContent = "\$params = array();\n";
            }

            $classfunctions.="public function $methodname($funcParams) {\n";
            $classfunctions.=$funcContent;
            $classfunctions.="return \$this->sendRequest(\"$methodname\", \$params);\n";
            $classfunctions.="}\n\n";
        }

        $wrapper = "<pre>class " . $this->classname . "XMLRPCClient extends XMLRPCClientHelper {\n";
        $wrapper .= "$classfunctions";
        $wrapper .= "}\n</pre>";
        return $wrapper;
    }

    /**
     * Register method
     * @param <string> $externalName class name
     * @param <Object> $function class pointer
     * @param <array> $parameterNames parameters name
     */
    public function registerMethod($externalName, $function, $parameterNames) {
        if ($function == null) {
            $function = $externalName;
        }
        xmlrpc_server_register_method($this->serverHandler, $externalName, array(&$this, 'callMethod'));
        $this->externalFunctions[$externalName] = array('function' => $function, 'parameterNames' => $parameterNames);
    }

    /**
     * Invoke class method
     * @param <string> $functionName method name
     * @param <array> $parametersFromRequest parameters
     * @return <variant> function call result
     */
    public function callMethod($functionName, $parametersFromRequest) {
        if ($functionName == "generatePHPClientWrapper") {
            return $this->generatePHPClientWrapper();
        }

        $function = $this->externalFunctions[$functionName]['function'];
        $parameterNames = $this->externalFunctions[$functionName]['parameterNames'];
        return call_user_func_array($function, $parametersFromRequest);
    }

    /**
     * Handle server call
     * @return <variant>  function call result
     */
    public function handle() {
        $bWrapper = false;
        foreach ($_GET as $key => $value) {
            if ($key == "phpwrapper") {
                $bWrapper = true;
                continue;
            }
        }

        if ($bWrapper) {
            print $this->generatePHPClientWrapper();
            exit();
        }
        return xmlrpc_server_call_method($this->serverHandler, file_get_contents('php://input'), null);
    }

}

?>

XMLRPC Training (C# and PHP)

Today, I'm going to conduct a simple training on XML-RPC at my previous company.
You can access to the training materials on my googleDocs.


Presentation Slide
PHP source code
C# source code
 
Copyright © peyotest