Posted by
survivant on February 3, 2009 at 4:38 PM PST
This time I will show you how to run PHP applications on GrizzlyWebServer using 100% pure java solutions.
I used
Caucho Quercus to handle the PHP and GrizzlyWebServer as my WebServer.
The first implementation that I did was really simple. I used the demo that I did for
JSPOnGrizzly and replace the servlet
by Quercus. You can see what the code looks like :
public void launch(){
GrizzlyWebServer ws = new GrizzlyWebServer(80);
try {
ServletAdapter sa = new ServletAdapter();
sa.setContextPath("/");
Servlet servlet = (Servlet)ClassLoaderUtil.load("com.caucho.quercus.servlet.QuercusServlet");
sa.setServletInstance(servlet);
ws.addGrizzlyAdapter(sa, new String[]{});
ws.start();
} catch (Exception e){
s_logger.error("Error Launching GrizzlyWebServer",e);
}
}
I was expecting that would work within a few seconds, but I got few exceptions when I tried to run the application.
2009-02-02 17:28:03 com.sun.grizzly.http.servlet.ServletAdapter service
GRAVE: service exception:
java.lang.UnsupportedOperationException: Not supported yet.
at com.sun.grizzly.http.servlet.HttpServletRequestImpl.getRealPath(HttpServletRequestImpl.java:624)
at com.caucho.quercus.servlet.QuercusServletImpl.getPath(QuercusServletImpl.java:244)
at com.caucho.quercus.servlet.QuercusServletImpl.service(QuercusServletImpl.java:112)
at com.caucho.quercus.servlet.QuercusServlet.service(QuercusServlet.java:407)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:820)
at com.sun.grizzly.http.servlet.FilterChainImpl.doFilter(FilterChainImpl.java:174)
at com.sun.grizzly.http.servlet.FilterChainImpl.invokeFilterChain(FilterChainImpl.java:123)
at com.sun.grizzly.http.servlet.ServletAdapter.service(ServletAdapter.java:254)
at com.sun.grizzly.tcp.http11.GrizzlyAdapter.service(GrizzlyAdapter.java:165)
at com.sun.grizzly.http.DefaultProcessorTask.invokeAdapter(DefaultProcessorTask.java:653)
at com.sun.grizzly.http.DefaultProcessorTask.doProcess(DefaultProcessorTask.java:570)
at com.sun.grizzly.http.DefaultProcessorTask.process(DefaultProcessorTask.java:840)
at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:153)
at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:136)
at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:103)
at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:89)
at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:76)
at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:67)
at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:57)
at java.util.concurrent.FutureTask$Sync.innerRun(Unknown Source)
at java.util.concurrent.FutureTask.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Grizzly doesn't completely implement HttpServletRequest (yet). The easy way doesn't always work the first time.
BUT there is still a way to do PHP with GrizzlyWebServer. An alternative is to use Quercus's JSR223 implementation.
We will have to replace QuercusServlet by my Servlet that uses Quercus libraries.
Servlet servlet = (Servlet)ClassLoaderUtil.load("ca.sebastiendionne.grizzly.servlet.QuercusHttpServlet");
QuercusHttpServlet
package ca.sebastiendionne.grizzly.servlet;
import java.io.FileReader;
import java.io.IOException;
import java.io.StringWriter;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Map;
import javax.script.ScriptContext;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class QuercusHttpServlet extends HttpServlet {
private static final long serialVersionUID = -1649882114668014299L;
private static final Logger s_logger = LoggerFactory.getLogger(QuercusHttpServlet.class);
private static ScriptEngineManager scriptManager = new ScriptEngineManager();
private static ScriptEngine phpEngine = scriptManager.getEngineByExtension("php");
@SuppressWarnings("unchecked")
protected void doPut (HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
ScriptContext context = phpEngine.getContext();
try {
context.setWriter(new StringWriter());
//put the parameters and attributes into the engine
Enumeration attributes = req.getAttributeNames();
while (attributes.hasMoreElements()) {
String key = (String) attributes.nextElement();
// put the parameters and attributes into the engine
phpEngine.put(key, req.getAttribute(key));
}
Map<String, Object> params = req.getParameterMap();
for (Iterator iterator = params.keySet().iterator(); iterator.hasNext();) {
String key = (String) iterator.next();
// put the parameters and attributes into the engine
phpEngine.put(key, params.get(key));
}
// need a better way to find the requested file
String uri = req.getRequestURI();
if(uri.startsWith("/")){
uri = uri.substring(1);
}
phpEngine.eval(new FileReader(uri), context);
StringWriter writer = (StringWriter) context.getWriter();
res.getWriter().println(writer.toString());
} catch (Exception e) {
s_logger.error("Error Evaluating PHP",e);
}
}
protected void doGet (HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
doPut(req, res);
}
}
We need a php page to test our application.
phpinfo.php
<?php
// Show all information, defaults to INFO_ALL
phpinfo();
?>
The output won't be the same as the native php. Here the output from Quercus implementation.
Quercus
PHP Version => 5.2.0
System => Windows XP 5.1 x86
Build Date => 20070628T2777
Configure Command => n/a
Server API => CGI
Virtual Directory Support => disabled
Configuration File (php.ini) Path => WEB-INF/php.ini
PHP API => 20031224
PHP Extension => 20041030
Debug Build => no
Thread Safety => enabled
Registered PHP Streams => php, file, http, https
Variable => Value
....
You can download the source code for this project
here.