Showing posts with label tomcat. Show all posts
Showing posts with label tomcat. Show all posts

Wednesday, September 26, 2012

Grails: Configure JNDI datasource for both development and production mode

Datasource.groovy hard coded JDBC connection data are ok for quick and dirty apps, but what about a scenario where:

  • you need to setup a common DBCP datasource
  • to use it when setting up BOTH development and production?

For a Tomcat and Oracle environment, here is a solution working ok for me:

Step 1: META-INF/context.xml

<Context path="/proteys" debug="5" reloadable="true"> <Resource auth="Container" name="jdbc/db" type="javax.sql.DataSource" driverClassName="oracle.jdbc.driver.OracleDriver"
url="jdbc:oracle:thin:@127.0.0.1:1521:orcl" username="XXXX"
password="YYYY" maxActive="100" maxIdle="30" maxWait="10000
</Context>





Step2: Config.groovy
alter the environment sections as follow:

environments {
    development {
        grails.logging.jul.usebridge = true
//the following is for development mode only
//not needed to alter when deploy for production
//in production just configure meta-inf/context.xml
grails.naming.entries = [
"jdbc/db": [
type: "javax.sql.DataSource", //required
auth: "Container", // optional
description: "Data source for Proteys", //optional
driverClassName: "oracle.jdbc.driver.OracleDriver",
url: "jdbc:oracle:thin:@127.0.0.1:1521:orcl",
username: "XXX",
password: "YYY",
maxActive: "8",
maxIdle: "4"
]
]
    }
    production {
        grails.logging.jul.usebridge = false
        // TODO: grails.serverURL = "http://www.changeme.com"
    }
}

Step3: Alter the default templates in order to finetune the web.xml file and include there the necessary JNDI link:

1. run grails install-templates
2. in src/templates/war edit the web.xml template - appending the JNDI link reference:
  
 <resource-ref> <description>Datasource</description> <res-ref-name>jdbc/db</res-ref-name> <res-type>javax.sql.DataSource</res-type> <res-auth>Container</res-auth> </resource-ref>



This way, in every running or creation of war, automatically the produced web.xml will contain the above xml snippet.


Step4: config Datasource.groovy
The only content needed here is:
dataSource {
jndiName = "java:comp/env/jdbc/db"
dialect= 'org.hibernate.dialect.OracleDialect'
}
Although I don't use Hibernate / GORM / Scaffolding etc, because I needed to access an existent DB through GroovySQL, the second line regarding dialect was necessary to make grails stop complaining during building / running (or perhaps should I just drop hibernate plugin...)


From this point on, (hopefully) you can develop AND generate production WAR files using JNDI setup. And not to mention that you can now alter the db connection parameters in production, without the need of a special build


Thursday, March 12, 2009

Tomcat Error: ...is quoted with " which must be escaped when used within the value

From Apache Tomcat 5.5.27 onwards, it seems that Tomcat is picky about double quoted expressions:

ERROR [http-80-Processor22] - Servlet.service() for servlet jsp threw exception
org.apache.jasper.JasperException: /forum/index.jsp(73,36) Attribute value request.getRequestURI()+"?"+request.getQueryString() is quoted with " which must be escaped when used within the value
at org.apache.jasper.compiler.DefaultErrorHandler.jspError(DefaultErrorHandler.java:40)
at org.apache.jasper.compiler.ErrorDispatcher.dispatch(ErrorDispatcher.java:407)
at org.apache.jasper.compiler.ErrorDispatcher.jspError(ErrorDispatcher.java:198)
at org.apache.jasper.compiler.Parser.parseQuoted(Parser.java:307)
at org.apache.jasper.compiler.Parser.parseAttributeValue(Parser.java:250)
at org.apache.jasper.compiler.Parser.parseAttribute(Parser.java:211)
at org.apache.jasper.compiler.Parser.parseAttributes(Parser.java:149)
at org.apache.jasper.compiler.Parser.parseParam(Parser.java:875)
at org.apache.jasper.compiler.Parser.parseBody(Parser.java:1829)
at org.apache.jasper.compiler.Parser.parseOptionalBody(Parser.java:1081)
at org.apache.jasper.compiler.Parser.parseInclude(Parser.java:909)
at org.apache.jasper.compiler.Parser.parseStandardAction(Parser.java:1232)
at org.apache.jasper.compiler.Parser.parseElements(Parser.java:1588)
at org.apache.jasper.compiler.Parser.parse(Parser.java:132)
at org.apache.jasper.compiler.ParserController.doParse(ParserController.java:212)
at org.apache.jasper.compiler.ParserController.parse(ParserController.java:101)
at org.apache.jasper.compiler.Compiler.generateJava(Compiler.java:156)
at org.apache.jasper.compiler.Compiler.compile(Compiler.java:296)
at org.apache.jasper.compiler.Compiler.compile(Compiler.java:277)
at org.apache.jasper.compiler.Compiler.compile(Compiler.java:265)
at org.apache.jasper.JspCompilationContext.compile(JspCompilationContext.java:564)
at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:302)
at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:329)
at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:265)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:269)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188)
at com.cj.trim.trimFilter.doFilter(Unknown Source)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:215)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188)
at gr.knowledge.util.SetCharacterEncodingFilter.doFilter(SetCharacterEncodingFilter.java:121)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:215)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:172)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:117)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:108)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:174)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:875)
at org.apache.coyote.http11.Http11BaseProtocol$Http11ConnectionHandler.processConnection(Http11BaseProtocol.java:665)
at org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:528)
at org.apache.tomcat.util.net.LeaderFollowerWorkerThread.runIt(LeaderFollowerWorkerThread.java:81)
at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:689)
at java.lang.Thread.run(Unknown Source)




See the relevant https://issues.apache.org/bugzilla/show_bug.cgi?id=45015

It seems that, you can either edit your jsp code to be more compliant or get rid of the error by editing catalina.properties and putting this extra line:

org.apache.jasper.compiler.Parser.STRICT_QUOTE_ESCAPING=false
This actually tells Tomcat to be more relaxed about JSP compliance regarding double quoted expressions.

See also http://tomcat.apache.org/tomcat-5.5-doc/config/systemprops.html

Tuesday, March 3, 2009

context XML file deleted when path is not readable

If your Tomcat application has a docbase which is a network place (being it a Windows share or a NFS Linux share) and temporarily the connection between the two machines is lost, chances are that the context.xml of your app as it is deployed in \conf\Catalina\localhost will be automatically removed.


In order to avoid this, edit your server.xml file and set autoDeploy="false" in the Host tag.

See https://issues.apache.org/bugzilla/show_bug.cgi?id=40050