Developer Guidelines
Contributions
The core development of the IPT is directed by GBIF, but the coding is a community effort and everyone is welcome to join. Java or HTML/jQuery developers are very welcome to contribute code patches. Patches can be submitted by creating a pull request using a branch or fork of the IPT Git repository.
Source Code Frameworks
The IPT uses the following core frameworks:
-
Freemarker templating
-
jQuery for JavaScript and AJAX
Prerequisites
The IPT uses Maven to manage dependencies and the build process. Refer to Maven’s own installation instructions for help.
Running the application in Jetty
$ cd ipt
$ mvn -DskipTests
This command starts up the IPT via the Jetty plugin on port 8080. You should be able to see the IPT running by opening http://localhost:8080 in your web browser.
Git
Please don’t check in unused files.
Code in the master branch should always compile and allow the startup of Jetty using Maven!
Guice
IptModule
contains wiring, but interfaces are annotated directly with @ImplementedBy(ConfigManagerImpl.class)
Configuration
Inside WEB-INF of a running IPT is a single file datadir.location
. It points to the currently used data directory where all configuration and data is stored. If this file is deleted the setup interceptor will ask the user to assign a new (potentially existing) data directory.
The hidden file .gbifreg
indicates whether the data directory is linked to the production or test registry. Once set, this cannot be changed from the UI!
AppConfig.java
contains all IPT wide configuration, in particular the baseURL
(referred to in the UI and documentation as the "Public URL") for the application.
Struts2
BaseAction.java
supplies the AppConfig
, implements session aware and gives access to current user, implements a simpler TextProvider
which is faster than the native Struts 2 one.
SetupAndCancelInterceptor.java
checks if the data directory is configured and an admin user exists - otherwise redirects to the respective setup page.
For each package (root
, portal
, manage
, admin
) its own interceptor stack exists.
The "input" result name is used to show the form. We can therefore use the standard validation interceptor which uses the input result when data doesn’t validate.
The "success" result name is called when the form submit succeeded. In many cases this should simply be a redirect to another, often the corresponding list, action.
The action implements preparable, request aware and the execute method.
-
execute:
FormAction
determines if aPOST
orGET
is used and calls save (POST
), delete (POST + delete=true
) or nothing (GET
).
If any other action values need to be set you can override prepare()
- but remember to call super.execute()
.
-
prepare: the
id
parameter of the request object is stored in the action.
POSTAction.java
simplifies working with forms. For modifying instance data always use POST
, never GET
. Most full actions for modifying entities should override the following methods:
-
prepare()
: load existing values based on "id" parameter and request object. -
save()
: persist data AFTER the parameters interceptor did its job. -
delete()
: this method is called when aPOST
with adelete=anything_but_null
parameter is received.
If the id
given does not exist you can set the notFound
property to true in any of the above methods. The action will then return a 404 result name.
To do validation, implement the validate()
method of an action (instead of using XML validation definitions). See SetupAction.java
as an example. Validation requires an input
result name that shows the form when the form was not valid. Using the simple theme we also need to declare where to render the validation feedback: http://struts.apache.org/docs/fielderror.html
HTML Design
Links always use ${baseURL}/my/ipt/link.do
, so please refrain from using Struts or JSP URL tags!
Forms use the forms.ftl
macros instead of Struts 2 tags, such as the internationalization @select
drop downs.
Buttons use proper buttons or input@type=submit
(forms) for add, delete, edit, create actions.
General best practice guides:
JavaScript
Only use jQuery (https://jquery.com/) for custom code.
Use jConfirmation plugin (https://github.com/hdytsgt/jConfirmAction) when asking for confirmation, e.g. deletes.
Use jQuery dataTables (https://www.datatables.net/) plugin to enhance HTML tables with pagination, searching, etc.
CSS
960 grid system is used for page layouts.
Keep number of CSS classes to a minimum and consider using page specific CSS in <head><style>
on that page.