Skip to content

QTIWorks Engine installation guide

Dave McKain edited this page Jan 5, 2016 · 27 revisions

Before you start: important note!

FIXME: REMOVE THIS PARAGRAPH WHEN 1.0.0 COMES OUT!

QTIWorks is still under development and not yet production quality. While you can install, run and evaluate it now, I recommend not using it for real assessment as changes to the database schema and internal data storage structures made over the remaining few work iterations as we approach a 1.0 release will mean that you will need to run schema migration scripts and occasionally purge all candidate attempt data in order to keep the internal data in sync. (I will remove this notice once we are suitably near a 1.0 release with a stable schema.)

Installation instructions

0.1. Security and privacy considerations

If you are installing an instance of QTIWorks that will be used for "real" assessments, then you must think of the following privacy and security issues at all times:

  • You SHOULD make the QTIWorks webapp run over HTTPS rather than plain HTTP. If you do not do this, some LTI functionality will not be available, and sensititve information such as LTI data and system passwords will be sent over the network in unencrypted form.
  • You MUST ensure that the QTIWorks database and file store are only accessible to trusted people. This data can include the names, email addresses, progress and results of all instructor users and assessment candidates, so needs to be secured appropriately. You should ensure that any backups of this data are also secured in an appropriate fashion.

0.2. Integration Requirements

In order to use QTIWorks for "real" assessment, you will need to connect it to a (Basic) LTI 1.1 Tool Consumer. Examples of such systems include Blackboard Learn and Moodle. This usually has to be done by whomever administers or manages these systems, so you will probably need to speak to someone to arrange this for you.

0.3. Technical Requirements

To run and administer the QTIWorks Engine web application, you will need:

  • A Unix-like operating system. We have successfully installed and run the QTIWorks Engine on various flavours of Linux and Mac OS X. (I'm told it installs fine on Windows too but haven't tried myself.)
  • The Java Development Kit (JDK), version 6 or higher.
  • A Java web (servlet) container that supports the Servlet 2.5 Specification, such as Tomcat version 6 or higher, or Jetty version 6 or higher. This document will assume you know the basics about running your servlet container. You may need to ask your local IT services for support with this, but note that it's easy to download and run Tomcat without requiring it to be properly installed, which might be sufficient for initial evaluation of this software.
  • Access to a relational database. The QTIWorks Engine stores some data in a database. We have tested PostgreSQL version 8.4 and MySQL version 5.1, but other popular databases should work fine, especially those listed under SQL Dialects in the documentation for the Hibernate database abstraction library. This document will assume you know the basics about running and accessing your database. You may need to ask your local IT services for support with this.
  • Some free disk space. As well as using a relational database, the QTIWorks Engine stores uploaded content packages and assessment XML in the filesystem, as well as some internal XML files used to model candidates' progress within assessments. The amount of free space required will depend on the actual usage of QTIWorks; this is unlikely to be an issue at first.

If you want to support the MathAssess QTI extensions then you will also need to install:

  • Maxima, version 5.20.0 or higher.

We strongly recommend putting your servlet container "behind" a standard web server or web proxy server, such as Apache or Squid. As stated above, we also very strongly recommend making QTIWorks accessible over HTTPS only.

1. Obtain the QTIWorks Engine binaries

Note: We will make binaries available for download once we get nearer a final 1.0 release. In the mean time, please consult Building QTIWorks from source to build from source.

You will need the following binaries:

  • qtiworks-engine-VERSION.war: This is the QTIWorks Engine web application, which will be deployed to your servlet container.
  • qtiworks-engine-manager-VERSION.jar: This is a Java archive that lets you perform certain administrative tasks on the QTIWorks Engine from the command line. It is also used to perform the initial database bootstrap before you run the engine webapp for the first time.

If you are building from source, you will find these under qtiworks-engine/target/qtiworks-engine-VERSION.war and qtiworks-engine-manager/target/qtiworks-engine-manager-VERSION.jar respectively.

2. Download the JDBC driver for your database

You will need the JDBC driver (Java connector) for your database. Links for PostgreSQL and MySQL are below; consult your DB documentation if you are using something else.

3. Install your JDBC into your servlet container

You need to copy the JDBC driver you downloaded above into the location your servlet container provides for installing shared/additional libraries.

Hint: In the case of Tomcat, this is often a directory called lib at the top of the Tomcat file hierarchy. If you have installed a Linux Tomcat package, you may have to look elsewhere. On Red Hat Enterprise Linux 6, the current location is /usr/share/tomcat6/lib.

4. Set up the file store

Choose or create the directory where the QTIWorks Engine will store its files. You will need to ensure that this directory is fully readable, accessible and writable by the process that your servlet container runs under. You may need to use some kind of combination of permissions and/or access control lists (ACLs), and this may require you asking your local IT support.

We strongly recommend that you use local disk space for this, rather than networked filesystems. You should also ensure that this data store is kept suitably secure.

5. Create the QTIWorks Engine database

You will need to create a new database (in PostgreSQL or MySQL terminology) within your database server for QTIWorks Engine. You may need to ask your local IT support or database administrator to do this for you. Regardless of whether you or someone else creates your database, you will need to know the name of the database, the username/password you connect with (or equivalent), the host and/or port the database server is accessed at (if appropriate) and any other connection parameters that may be required.

You must ensure that this database is kept suitably secure.

6. Create a qtiworks-deployment.properties configuration

The QTIWorks Engine (and QTIWorks Engine Manager) finds out how you've set things up via a configuration file called qtiworks-deployment.properties, which you will need to fill in. You will find a template for this under qtiworks-engine/default.qtiworks-deployment.properties that you should copy and adapt as appropriate. There are some instructions within the template to help you.

7. Create an admin directory for managing QTIWorks Engine

I suggest you create a directory somewhere convenient and put the qtiworks-engine-manager.jar and your qtiworks-deployment.properties in there. This will make managing the engine easier.

Note: I suggest removing the version number from the JAR name as it'll make the instructions below easy to copy and paste.

8. Bootstrap the database schema

In the admin directory you created above, type:

$ java -jar qtiworks-engine-manager.jar bootstrap

If successful, this should output a lot of logging output and complete successfully. Unfortunately, the first time you'll run this you will see some log messages recorded at error level. I therefore recommend running the above once more; there should be no errors noted the second time.

If you see errors recorded second time round, or stack traces, then you probably have a problem with your database connection parameters. Check what you have entered in qtiworks-deployment.properties against those which are required to connect to your database.

9. Configure and deploy the QTIWorks Engine webapp

This step depends heavily on what servlet container you use and how you deploy your webapps to it. The key thing you'll need to do is set a "servlet context parameter" telling QTIWorks where to load your qtiworks-deployment.properties file (or a copy of this file). This property must be called qtiWorksDeploymentPropertiesUri and should be a file URI of the form file:/path/to/qtiworks-deployment.properties. You will need to make sure your servlet container can read this file.

A suggested method for doing this with Tomcat is outlined in Appendix A below.

10. Run and test the webapp

Once deployed, you should be able to access and run QTIWorks. The bootstrap process above will have loaded in the sample items and you should be able to use the public demos. You may now want to create some user accounts, which can also be done using the qtiworks-engine-manager.jar. See QTIWorks Engine management for details.

Appendices

Appendix A: Deploying to Tomcat 6 or 7

Tomcat supports a number of ways for deploying webapps. We suggest the following method:

A1. Create a directory to house the running webapp

Create a directory that is readable to the user that the Tomcat server runs as. (It doesn't have to be writable). In here, copy your qtiworks-deployment.properties file. You might want to copy qtiworks-engine-manager.jar here too, so this directory could actually be the same as the one you created in step 7 above.

A2. Unpack the QTIWorks Engine WAR

Create a subdirectory in the one you created above, called webapp or similar. Then change into this directory and unpack the qtiworks-engine.war file using:

$ jar xvf /path/to/qtiworks-engine.war

A3. Create a Tomcat context XML configuration for the QTIWorks Engine

In this directory, create a file called qtiworks.xml as follows:

<Context path="/qtiworks" docBase="/path/to/webapp/directory/created/above">
  <Parameter name="qtiWorksDeploymentPropertiesUri" value="file:/path/to/qtiworks-deployment.properties"/>
</Context>

You can change the path attribute in the XML to deploy the webapp under a different location. (Alternatively, you can omit this completely, and give the XML file a different name, which has the same effect.)

A4. Deploy and run the webapp

Copy the XML file you created in A3 to conf/Catalina/localhost, making sure the file will be readable by the Tomcat process. (This location may be /etc/tomcat6/Catalina/localhost or similar if you have installed Tomcat as some kind of Linux package.)

If Tomcat is not already running, start it now. It should read the QTIWorks Engine XML configuration during startup and deploy the webapp. Watch out for errors, which may appear in the Tomcat logs directory. If Tomcat is running already, it may or may not deploy the new webapp automatically. You may want to restart Tomcat to make sure.

Common errors here include:

  • The webapp files, the context XML or qtiworks-deployment.properties are not readable by the Tomcat user. You may have to tweak permissions to fix this.
  • The paths specified in your context XML are wrong. Check the Tomcat logs.
  • You forgot to put the database driver JDBC in your Tomcat lib directory. This should be made clear in the logs.

Hint: The key Tomcat log file will be logs/catalina.out for "local" Tomcat installations, or somewhere like /var/log/tomcat6/catalina.out if Tomcat has been installed as a Linux package.

A5. Updating the webapp

If you need to deploy a newer version of the webapp, an unsophisticated way of doing this is to stop Tomcat, delete the contents of the webapp directory (see A2), then unpack the updated WAR file again. Then start Tomcat.

Appendix B: Customised logging

QTIWorks uses slf4j and logback to record log messages. The QTIWorks Engine webapp includes a bundled logback configuration that works fairly well. If you want more control over your logging, you can create your own logback.xml file and link to it using the logbackConfigFilePath context property. (It is a simple file path here, rather than a URI.)

If you followed the recipe outlined in Appendix A, then your qtiworks.xml would look something like:

<Context path="/qtiworks" docBase="/path/to/webapp/directory/created/above">
  <Parameter name="qtiWorksDeploymentPropertiesUri" value="file:/path/to/qtiworks-deployment.properties"/>
  <Parameter name="logbackConfigFilePath" value="/path/to/your/logback.xml"/>
</Context>

Here is an example logging configuration. This logs certain key things to separate files, which can be useful.

<configuration debug="false">

  <!-- Create basic appender sending messages to STDOUT -->
  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
      <pattern>%-5level %date %thread [%logger{0}/%line#%method\(\)] - %msg%n</pattern>
    </encoder>
  </appender>

  <!-- Main file logger -->
  <appender name="QTIWORKS"  class="ch.qos.logback.core.FileAppender">
    <file>/var/log/tomcat6/qtiworks.log</file>
    <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
      <pattern>%-5level %date %thread [%logger{0}/%line#%method\(\)] - %msg%n</pattern>
    </encoder>
  </appender>

  <!-- Appender for logging audit messages for logged in users -->
  <appender name="AUDITOR" class="ch.qos.logback.core.FileAppender">
    <file>/var/log/tomcat6/qtiworks-audit.log</file>
    <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
      <pattern>[%date] %msg%n</pattern>
    </encoder>
  </appender>

  <!-- Appender for logging audit messages for candidates -->
  <appender name="CANDIDATE_AUDITOR" class="ch.qos.logback.core.FileAppender">
    <file>/var/log/tomcat6/qtiworks-candidate-audit.log</file>
    <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
      <pattern>[%date] %msg%n</pattern>
    </encoder>
  </appender>

  <!-- Appender for logging intercepted Exceptions -->
  <appender name="EXCEPTION_LOGGER" class="ch.qos.logback.core.FileAppender">
    <file>/var/log/tomcat6/qtiworks-exceptions.log</file>
    <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
      <pattern>[%date] %msg%n%xEx{full}----------------%n</pattern>
    </encoder>
  </appender>

  <!-- Auditing log -->
  <logger name="AuditLogger" additivity="false" level="info">
    <appender-ref ref="AUDITOR"/>
  </logger>

  <!-- Candidate Auditing log -->
  <logger name="CandidateAuditLogger" additivity="false" level="info">
    <appender-ref ref="CANDIDATE_AUDITOR"/>
  </logger>

  <!-- Exception logging -->
  <logger name="uk.ac.ed.ph.qtiworks.web.LoggingHandlerExceptionResolver" additivity="false" level="info">
    <appender-ref ref="EXCEPTION_LOGGER"/>
  </logger>

  <!-- Also log certain other services at info level -->
  <logger name="uk.ac.ed.ph.qtiworks.config" level="info"/>
  <logger name="uk.ac.ed.ph.qtiworks.services.ScheduledServices" level="info"/>

  <!-- Root logger -->
  <root level="warn">
    <appender-ref ref="STDOUT"/>
    <appender-ref ref="QTIWORKS"/>
  </root>
</configuration>