| Tips For Running dotCMS on Amazon's EC2 | Install Methods |
Special thanks to Will Caine for contributing the original documentation that was later reviewed and edited by the dotCMS team.
It turns out that the configuration of Tomcat you get from SVN-stable (https://svn.dotcms.org/branches/stable) provided by dotCMS was valid. It was the ant build.xml that is a problem. It bundles in way too many jars compared to what is needed to make this guy work. Many conflicting jars I found with my Tomcat 6.0.16.
Table of Contents
Jar Locations What to and Not to Include
/conf/Catalina/localhost/ROOT.xml changes
In the context.xml file
Make changes to the catalina.properties file to bring all your classes in
Make changes to the catalina.sh file to the security rules to be able to login to the admin screen
Define GLOBAL_VARIABLES_PATH in dotmarketing-config.properties
Plugins Deploy not working / Plugins not installing right
Issues / Places to Check
Run on MySQL without the lower_case_table_names=1
Extras
Make this work on a 64MB heap space
Drawbacks/Issues
To name a few that should not be bundled anywhere from the SVN checked out code since Tomcat has these already
The only jars I kept in the WEB-INF/lib folder of the war built were the ones that the checked out version of dotCMS had and they are
batik-awt-util.jar
batik-dom.jar
batik-svggen.jar
batik-util.jar
batik-xml.jar
cewolf.jar
Copy from the SVN version to the "clean" Tomcat build
[svn checkout]/conf/jaas.config --> [clean tomcat]/conf/jaas.config
[svn checkout]/common/* --> [clean tomcat]/common/* [had to make this directory]
What this will do is when the war is created by your ant script the META-INF folder will be included and when you go to deploy the war, Tomcat will install the context.xml file for you into the conf folder in the correct place.
In the first line where you see
<Context path="" docBase="../dotCMS" debug="0" reloadable="false" crossContext="true">
change to
<Context path="" debug="0" reloadable="false" crossContext="true">
The docBase is not needed anymore because we have a war file now. Tomcat will figure out the base path for us.
common.loader=${esc.d}{catalina.home}/lib,${catalina.home}/lib/*.jar,${catalina.home}/server/lib/*.jar,${catalina.home} /common/ext-ejb,${catalina.home}/common/lib/ext/*.jar,${catalina.home}/common/lib/*.jar,${catalina.home}/common /endorsed/*.jar,${catalina.home}/build/instrumented,${catalina.home}/build/classes
This will put all of the jars you copied into the common/lib/ location onto your classpath.
/bin/catalina.sh
CATALINA_OPTS="-Xms64m -Xmx64m -Djava.security.auth.login.config=$CATALINA_HOME/conf/jaas.config " echo "Using CATALINA_OPTS: $CATALINA_OPTS"
I also defined the heap size to limit myself to see how small I could make the imprint. You should use at least 512 unless you wanna get OutOfMemoryErrors once and a while
Define GLOBAL_VARIABLES_PATH in dotmarketing-config.properties because in my case, my tomcat is setup to handle mutiple roots so its inside [tomcat root]/domains/[some.com]/context and if not defined you will see in the logs...
java.io.FileNotFoundException: [some server root/>stuff]/tomcat/domains/[some.com]/context/../common/ext-ejb/...
...This is the default path that is only correct if you are using the setup that comes with the tomcat configuration when checked out of SVN. Instead you want
[some server root stuff]/tomcat/common/ext-ejb/
So define that property to your common/ext-ejb folder in the properties file and you will stop seeing FileNotFoundExceptions.
GLOBAL_VARIABLES_PATH=/[some server root stuff]/tomcat/common/ext-ejb
new PluginLoader().loadPlugins(config.getServletContext().getRealPath("."),classPath);
This tries to load all the extension jars at ../common/lib/ext This is wrong when running your app as a WAR because it creates a folder called ROOT
/Development/servers/apache-tomcat-6.0.16/webapps/ROOT/../common/lib/extwhich tries to target
/Development/servers/apache-tomcat-6.0.16/webapps/common/lib/ext
which is not a valid directory because in my case, my tomcat is setup to handle mutiple roots so its inside [tomcat root]/domains/[some.com]/context. So it does not find that directory and it fails over to
/Development/servers/apache-tomcat-6.0.16/webapps/ROOT/WEB-INF/lib
which is valid however is not where i put the jar extensions.
Because I keep my plugins in common/lib/ext and they are never found, the Plugin Deploy class never gets run and my plugins are never setup correctly
Workaround
Put the extension inside the WEB-INF/lib
Or better yet:
The logic here should be more robust to check the WEB-INF/lib using the getServletContext().getRealPath(".") as well as make use of the property GLOBAL_VARIABLES_PATH in the /common/ext-ebj/dotmarketing-config.properties file so that if can correctly discover the true ROOT and not have to use relative navigation to find the common/lib/ext. The relative navigation can be a fall back if GLOBAL_VARIABLES_PATH is not set.
I found this function in ContentletAjax.java that does the trick which I then put into InitServlet.java. Weirdly enough this function is private and used in multiple classes.
So I took this function, stuck it in InitServlet.java and got it working
public class InitServlet extends HttpServlet {
....
private String getGlobalVariablesPath() {
String globalVarsPath = Config.getStringProperty("GLOBAL_VARIABLES_PATH");
if (!UtilMethods.isSet(globalVarsPath)) {
globalVarsPath = Config.CONTEXT.getRealPath(File.separator + ".." + File.separator + "common"
+ File.separator + "ext-ejb" + File.separator + "content" + File.separator);
}
if (!globalVarsPath.endsWith(File.separator))
globalVarsPath = globalVarsPath + File.separator;
return globalVarsPath;
}
public void init(ServletConfig config) throws ServletException {
.....
//String classPath = config.getServletContext().getRealPath("../common/lib/ext");
String classPath = getGlobalVariablesPath() + "../lib/ext";
File extDir = new File(classPath);
if(!extDir.exists()){
classPath = config.getServletContext().getRealPath("WEB-INF/lib");
}
.....
}
.....
}
Name java:comp is not bound in this Context
Symptoms: dotCMS will not start because cannot get datasource
Caused by: com.dotmarketing.exception.DotRuntimeException: com.dotmarketing.exception.DotRuntimeException: javax.naming.NameNotFoundException: Name java:comp is not bound in this Context at com.dotmarketing.exception.DotRuntimeException.fillInStackTrace(DotRuntimeException.java:33) at java.lang.Throwable.Possible Solution:(Throwable.java:181) at java.lang.Exception. (Exception.java:29) at java.lang.RuntimeException. (RuntimeException.java:32) at com.dotmarketing.exception.DotRuntimeException. (DotRuntimeException.java:15) at com.dotmarketing.db.DbConnectionFactory.getConnection(DbConnectionFactory.java:92) at com.dotmarketing.db.HibernateUtil.getSession(HibernateUtil.java:498)
Make sure your context.xml file is setup correctly and it is giving you the correct access of the datasource to your app.
Make sure the naming-* files are not in the WEB-INF/lib but in the common lib folder. Has to do with classloader hierarchy
java.lang.SecurityException: Unable to locate a login configuration
Symptoms: startersite will not let me login
-Make sure the jaas.config is defined via -Djava.security.auth.login.config=$CATALINA_HOME/conf/jaas.config" on startup of Tomcat Has to do with classloader hierarchy. OR I saw a way to during runtime define it but I havn't tried it.
Symptoms: when hit url will get compile/runtime error
-make sure your JSPs compiled and were put into the dotcms_1.7a.jar(mine was about 8MB with compiled jsps, 4MB without)
Symptoms: when hit url will get compile/runtime error Make sure there are no conflicting jars inside your war like servlet-api and jsp-api that define a different spec. in this case the class was build on JSP 2.1 but Tomcat runs 2.0 Helpful URL(s):
http://java.sun.com/products/jsp/2.1/docs/jsp-2_1-pfd2/javax/servlet/jsp/JspApplicationContext.htmlIn the documentation is says that lower_case_table_names number equal 1
http://www.dotcms.org/
In the code the same table is referenced in more than one case so I wrote my own mySQL driver that wrappered the standard mysql code: ConnectionImpl, StatementImpl and PrepareStatementImpl. I then intercepted, anywhere a create statment, execute query, or prepare statment was called on these objects rewrote the SQL to make for example users_group be rewritten to Users_Groups and then passed the SQL onto the com.mysql driver code.
Sample driver code for my implementation of ConnectionImplprivate PreparedStatement wrapPrepareStatement(told the context xml to use my new driver that I named DotDriver
PreparedStatement prepareStatement) throws SQLException {
return new DotPreparedStatement(conn, getCatalog(),
(com.mysql.jdbc.PreparedStatement) prepareStatement);
}
public PreparedStatement prepareStatement(String sql, int resultSetType,
int resultSetConcurrency, int resultSetHoldability)
throws SQLException {
//rewrite the sql to fix table naming issues
sql = DotDriver.translateString(sql);
return wrapPrepareStatement(conn.prepareStatement(sql, resultSetType,
resultSetConcurrency, resultSetHoldability));
}
<Resource name="jdbc/dotCMSPool" auth="Container"to get at runtime when sql is executed
type="javax.sql.DataSource" driverClassName="com.mysql.jdbc.DotDriver"
url="jdbc:mysql://localhost/wacaine5_cainedotcms?characterEncoding=UTF-8"
username="wacaine5_dotcms" password="dotcms3146" maxActive="60" maxIdle="10" maxWait="60000"
removeAbandoned="true" removeAbandonedTimeout="60" logAbandoned="true"
validationQuery="SELECT 1" testOnBorrow="true"/>
DotDriver translated sql: insert into users_groups values (?,?) to insert into Users_Groups values (?,?) using rule:users_groups-->Users_Groups
users_groups.rule=users_groups->Users_Groups
users_groups.caseSensitive=true
users_groups.type=findReplace
users_groups.active=true
users_groups.object=any
groups_roles.rule=groups_roles->Groups_Roles
portlet.rule=portlet->Portlet
address.rule=address->Address
group.rule=group_->Group_
layout.rule=layout->Layout
user.rule=user_->User_
role.rule=role_->Role_
company.rule=company->Company
users_roles.rule=users_roles->Users_Roles
counter.rule=counter->Counter
image.rule=image->Image
portletpreferences.rule=portletpreferences->PortletPreferences
To make this work on a 64MB heap space in Tomcat 6.0.16 I had to truncate the dictionary files. They ate up a lot of heap space since they are held in memory and if I left them in there I would get an OutOfMemoryException
I was unsuccessful at getting dotCMS to deploy anywhere but the ROOT context path. I was able to change it, but there seem to be some hard coded redirections based on the root that I could not get around without modifying code (the admin page root.com/c in particular)
There are a lot of jars now on the common classpath. Observe for collisions or incompatibilities with other apps you try to deploy
| Tips For Running dotCMS on Amazon's EC2 | Install Methods |
Post a Comment