tags:

views:

513

answers:

3

We may replace php app with j2ee app, but the problem is we wanna replace the modules one by one, which means two apps would co-exist and communicate with each other.

So is it possible to share the user session between the 2 apps? Or use cookie to solve the problem?

A: 

Save your session data to a database with session_set_save_handler().

UPDATE Efficiency wise it would be very mininal, the difference from reading a text file to querying a database (presumably using an existing connection).

Some example code (simplified from what I use)

class Session {
    public function __construct() {
        session_start();       
        $this->clean();        
    }
    public function __destruct() {
        session_write_close();
    }
    public function open() {
        return TRUE;
    }    
    public function close() {
        return TRUE;
    }    
    public function read($id) {
        global $Database;
        if ($Database->select('session_data FROM sessions WHERE session_id="%s"', $id)) {
            list($data) = $Database->fetch(MYSQL_NUM);
            return $data;
        } else {
            return '';
        }
    }    
    public function write($id, $data) {
        global $Database;
        return $Database->replace('sessions SET session_id="%s", session_data="%s", session_updated=%d', array($id, $data, time()));
    }    
    public function destroy($id) {
        global $Database;
        $_SESSION = array();
        return $db->delete('sessions WHERE session_id="%s"', $id);
    }    
    public function clean($expire = 600) {
        global $Database;
        $Database->delete('FROM sessions WHERE session_updated<%d', $time - $expire);
        return TRUE;
    }
}
// Declare the functions to use:
session_set_save_handler(array('Session', 'open'), array('Session', 'close'), array('Session', 'read'), array('Session', 'write'), array('Session', 'destroy'), array('Session', 'clean'));
$Session = new Session;

The you can read/write to the session data using $_SESSION['name'] = data; in the usual technique.

bigstylee
Will this lose efficiency? What's the best way coming with good performance? Memcache?
Sean Xiong
While this is a good idea, note that you won't be able to use JEE's native session handling, you'll need to implement your own on top of this mechanic. However, many containers have proprietary pluggable session managers that you could write on top of this.
Will Hartung
+1  A: 

One option you might want to look at is Quercus which is tied into Resin, and allows you to run PHP code on a J2EE app server, and enables some communication between the 2 platforms.

jayshao
This is also great!
Sean Xiong
Yes, the main reason I wouldn't recommend something like the above is it forces you to hand-roll your own session management, a feature which both platforms (especially Java) provide. In Java's case in particular, the native session management can buy you persistance, replication, and a bunch of goodies, essentially for free that you lose by taking that approach.
jayshao
I think Quercus also offers Session integration between PHP and Java EE. The problem with this solution is that you get a complete new PHP platform and that means not all PHP extension will work or work the same in this platform.
Kdeveloper
That's true, but the compatibility is supposed to be reasonable, and if you're looking to migrate to J2EE anyway, this seems like an attractive possibility (as always, w/o being in the dev's shoes and understanding the code, and roadmap, YMMV)
jayshao
I agree Quercus looks attractive, but migrating PHP code to an other app. server, just in order to abandon it, seems a lot of hassle if you can also use an simple API to connect Java with PHP (see my other answer here).
Kdeveloper
A: 

Sharing a regular Java EE session with PHP can be done very efficient and fast with PHP-java-bridge.

This solution offer superior performance over using a database as it does not generate any disk IO. It also does not need any changes on the PHP webserver or Java EE server. Just add some code, configure and you're done.

Setting up the php-java-bridge can be confusing, but if you know how to do it, it's only a 10-minute job. As I just did a proof of concept my self I can hand you the cookbook solutions:

  1. Download PHP-java-bridge files. I downloaded JavaBridgeTemplate610.zip (for the needed jar files) and php-java-bridge_6.1.0_documentation.zip for the needed examples, php include file and sample code (session sharing!).

  2. Add the "JavaBridge.jar", "php-script.jar" and "php-servlet.jar" to you're webapp by putting it in the "/WEB-INF/lib/" of you're Java EE server.

  3. Add a "test.jsp" to you're Java EE servers "/web" directory:

    <HTML>
    <TITLE>PHP and JSP session sharing</title>
    <BODY>
    <%
    
    
    javax.servlet.http.HttpSession $session = request.getSession();
    if($session.getAttribute("counter")==null) {
      $session.setAttribute("counter", new java.lang.Integer(1));
    }
    
    
    int $counter = ((java.lang.Integer)$session.getAttribute("counter")).intValue();
    out.println ("HttpSession variable \"counter\": " + $counter + "<br>");
    java.lang.Integer $next = new java.lang.Integer($counter+1);
    session.setAttribute("counter", $next);
    %>
    <a href="http://127.0.0.1/test.php"&gt;PHP page</a>
    </BODY>
    </HTML>
    
  4. Configure the JavaBridge servlet so it can be used by PHP to communicate to the Java EE server. Just add the following lines to you're web.xml:

    <servlet>
      <servlet-name>PhpJavaServlet</servlet-name>
      <servlet-class>php.java.servlet.PhpJavaServlet</servlet-class>
    </servlet>
    <servlet-mapping>
      <servlet-name>PhpJavaServlet</servlet-name>
      <url-pattern>*.phpjavabridge</url-pattern>
    </servlet-mapping>
    
  5. Add a file named "test.php" to you're webserver root and make sure you edit the JAVA_HOSTS and JAVA_SERVLET to correctly point to the Javabridgeservlet as configured in the web.xml.

    <?php
    define ("JAVA_HOSTS", "127.0.0.1:8084");
    define ("JAVA_SERVLET", "/JavaBridge.phpjavabridge");
    
    
    require_once("java/Java.inc");
    $session = java_session();
    ?>
    
    
    <HTML>
    <TITLE>PHP and JSP session sharing</title>
    <BODY>
    <?php
    if(is_null(java_values($session->get("counter")))) {
      $session->put("counter", 1);
    }
    $counter = java_values($session->get("counter"));
    print "HttpSession variable \"counter\": $counter<br>\n";
    $session->put("counter", $counter+1);
    ?>
    <a href="http://127.0.0.1:8084/test.jsp"&gt;JSP page</a>
    </BODY>
    </HTML>
    
  6. Install the needed "java.inc" php include file. You will find the file in the downloaded "php-java-bridge_6.1.0_documentation.zip" in the src.zip. Copy the "java.inc" file in the "/java" directory (just this one php file!).

  7. Restart Application server

  8. Start the test.php script (for example goto: http://127.0.0.1/test.php)

If you click on the links to the jsp and php file back, you will notice that the counter shares the Java session between both JSP and PHP scripts!

In order to share the same JSession cookie in a JSP/Servlet and PHP they both need to run on the same domain name (also make sure that JAVA_HOSTS is the PHP file uses the same domain name!).

Kdeveloper