I'm trying to implement SpringMVC + Quercus as described at http://blog.caucho.com/2009/04/14/using-php-as-a-spring-mvc-view-via-quercus/ .
So I setup Spring like this:
<servlet>
<servlet-name>Quercus Servlet</servlet-name>
<servlet-class>com.caucho.quercus.servlet.QuercusServlet</servlet-class>
<init-param>
<param-name>ini-file</param-name>
<param-value>WEB-INF/php.ini</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>Quercus Servlet</servlet-name>
<url-pattern>*.php</url-pattern>
</servlet-mapping>
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver"
p:prefix="/WEB-INF/themes/eyitope/"
p:suffix=".jsp"/>
<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="order" value="1" />
<property name="ignoreAcceptHeader" value="true" />
<property name="mediaTypes">
<map>
<entry key="php" value="application/php" />
</map>
</property>
<property name="viewResolvers">
<list>
<!-- used to handle all files with .php extension -->
<bean class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass" value="com.caucho.spring.quercus.QuercusView"/>
<property name="order" value="1"/>
<property name="prefix" value="/WEB-INF/themes/php/"/>
<property name="suffix" value=".php"/>
</bean>
</list>
</property>
<!-- If a compatible view cannot be supplied by the
ViewResolver chain, then the list of views specified through the DefaultViews property will be
consulted.
-->
<property name="defaultViews">
<list>
<bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView" />
</list>
</property>
</bean>
I have a simple controller like this:
@Controller
@RequestMapping("account/*")
public class AccountController {
public AccountController() {}
@RequestMapping("signup")
public String signupTestHandler() {
return "signup";
}
}
QuercusView looks like this:
package com.caucho.spring.quercus;
import java.io.*;
import java.util.*;
import java.util.logging.*;
import javax.servlet.*;
import javax.servlet.http.*;
import com.caucho.quercus.*;
import com.caucho.quercus.env.*;
import com.caucho.quercus.module.*;
import com.caucho.quercus.page.*;
import com.caucho.util.L10N;
import com.caucho.vfs.*;
import org.springframework.web.servlet.*;
import org.springframework.web.servlet.view.*;
public class QuercusView
extends AbstractUrlBasedView
{
private static final L10N L = new L10N(QuercusView.class);
private static final Logger log
= Logger.getLogger(QuercusView.class.getName());
protected QuercusContext _quercus;
protected ServletContext _servletContext;
public QuercusView()
{
super();
}
protected void initServletContext(ServletContext servletContext)
{
_servletContext = servletContext;
checkServletAPIVersion();
getQuercus().setPwd(new FilePath(_servletContext.getRealPath("/")));
getQuercus().init();
}
protected void checkServletAPIVersion()
{
int major = _servletContext.getMajorVersion();
int minor = _servletContext.getMinorVersion();
if (major < 2 || major == 2 && minor < 4)
throw new QuercusRuntimeException(L.l("Quercus requires Servlet API 2.4+."));
}
protected void renderMergedOutputModel(Map model,
HttpServletRequest request,
HttpServletResponse response)
throws Exception
{
Env env = null;
WriteStream ws = null;
try {
Path path = getPath(request);
QuercusPage page;
try {
page = getQuercus().parse(path);
}
catch (FileNotFoundException ex) {
// php/2001
log.log(Level.FINER, ex.toString(), ex);
response.sendError(HttpServletResponse.SC_NOT_FOUND);
return;
}
StreamImpl out;
try {
out = new VfsStream(null, response.getOutputStream());
}
catch (IllegalStateException e) {
WriterStreamImpl writer = new WriterStreamImpl();
writer.setWriter(response.getWriter());
out = writer;
}
ws = new WriteStream(out);
ws.setNewlineString("\n");
QuercusContext quercus = getQuercus();
quercus.setServletContext(_servletContext);
env = quercus.createEnv(page, ws, request, response);
// retro... thanks, Spring
for (Object entryObj : model.entrySet()) {
Map.Entry entry = (Map.Entry) entryObj;
env.setScriptGlobal((String) entry.getKey(), entry.getValue());
}
try {
env.start();
env.setScriptGlobal("request", request);
env.setScriptGlobal("response", response);
env.setScriptGlobal("servletContext", _servletContext);
StringValue prepend
= quercus.getIniValue("auto_prepend_file").toStringValue(env);
if (prepend.length() > 0) {
Path prependPath = env.lookup(prepend);
if (prependPath == null)
env.error(L.l("auto_prepend_file '{0}' not found.", prepend));
else {
QuercusPage prependPage = getQuercus().parse(prependPath);
prependPage.executeTop(env);
}
}
env.executeTop();
StringValue append
= quercus.getIniValue("auto_append_file").toStringValue(env);
if (append.length() > 0) {
Path appendPath = env.lookup(append);
if (appendPath == null)
env.error(L.l("auto_append_file '{0}' not found.", append));
else {
QuercusPage appendPage = getQuercus().parse(appendPath);
appendPage.executeTop(env);
}
}
// return;
}
catch (QuercusExitException e) {
throw e;
}
catch (QuercusErrorException e) {
throw e;
}
catch (QuercusLineRuntimeException e) {
log.log(Level.FINE, e.toString(), e);
// return;
}
catch (QuercusValueException e) {
log.log(Level.FINE, e.toString(), e);
ws.println(e.toString());
// return;
}
catch (Throwable e) {
if (response.isCommitted())
e.printStackTrace(ws.getPrintWriter());
ws = null;
throw e;
}
finally {
if (env != null)
env.close();
// don't want a flush for a thrown exception
if (ws != null)
ws.close();
}
}
catch (QuercusDieException e) {
// normal exit
log.log(Level.FINE, e.toString(), e);
}
catch (QuercusExitException e) {
// normal exit
log.log(Level.FINER, e.toString(), e);
}
catch (QuercusErrorException e) {
// error exit
log.log(Level.FINE, e.toString(), e);
}
catch (RuntimeException e) {
throw e;
}
catch (Throwable e) {
throw new ServletException(e);
}
}
Path getPath(HttpServletRequest req)
{
String scriptPath = getUrl();
String pathInfo = QuercusRequestAdapter.getPagePathInfo(req);
Path pwd = new FilePath(System.getProperty("user.dir"));
Path path = pwd.lookup(req.getRealPath(scriptPath));
if (path.isFile())
return path;
// XXX: include
String fullPath;
if (pathInfo != null)
fullPath = scriptPath + pathInfo;
else
fullPath = scriptPath;
return pwd.lookup(req.getRealPath(fullPath));
}
/**
* Returns the Quercus instance.
*/
protected QuercusContext getQuercus()
{
synchronized (this) {
if (_quercus == null)
_quercus = new QuercusContext();
}
return _quercus;
}
/**
* Gets the script manager.
*/
public void destroy()
{
_quercus.close();
}
}
Signup.php
<?php
echo 'This is php in Java with SpringMVC as the controller having a php based view resolver called QuercusView. Awesome!';
?>
When I access the resource at /account/signup , I get the following exception
exception
org.springframework.web.util.NestedServletException: Request
processing failed; nested exception is java.lang.NullPointerException
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:681)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:574)
javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
org.netbeans.modules.web.monitor.server.MonitorFilter.doFilter(MonitorFilter.java:393)
root cause
java.lang.NullPointerException
com.caucho.quercus.QuercusContext.getCurrentTime(QuercusContext.java:265)
com.caucho.quercus.env.Env.start(Env.java:1073)
com.caucho.spring.quercus.QuercusView.renderMergedOutputModel(QuercusView.java:140)
org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:250)
org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1047)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:817)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:719)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:669)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:574)
javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
org.netbeans.modules.web.monitor.server.MonitorFilter.doFilter(MonitorFilter.java:393)
I'm using Tomcat + openejb + Spring3 as EJB container.
Thanks for helping out.
Please I don't know a lot about the inner workings of SpringMVC and Quercus, but I'm hoping someone can help me with some pointers about how to resolve this.
Thanks for helping out.
Edit
The only fishy entry in server startup log is:
INFO: OpenJPA dynamically loaded a validation provider.
[LazyStopWebappClassLoader@5981f6b] warning javax.* types are not being woven because the weaver option '-Xset:weaveJavaxPackages=true' has not been specified
Dec 7, 2012 4:37:49 AM org.apache.catalina.util.LifecycleBase start
INFO: The start() method was called on component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[]] after start() had already been called. The second call will be ignored.
[LazyStopWebappClassLoader@5981f6b] error can't determine implemented interfaces of missing type javax.cache.Cache
when weaving type com.caucho.quercus.QuercusContext
when weaving classes
when weaving
[Xlint:cantFindType]
[LazyStopWebappClassLoader@5981f6b] error can't determine implemented interfaces of missing type com.google.appengine.api.users.UserService
when weaving type com.caucho.quercus.lib.gae.GaeUserService
when weaving classes
when weaving
[Xlint:cantFindType]
work copy https://github.com/PaulWeb/TestJavaPhp Stanle was right maybe old version but they forgot to add start
protected QuercusContext getQuercus()
{
synchronized (this) {
if (this._quercus == null) {
this._quercus = new QuercusContext();
this._quercus.start();
}
}
return this._quercus;
}
and if you want to pass from java to php then you have to use env.setGlobalValue