Table of Contents
This document describes how to setup an Eclipse project environment for working with Nuxeo EP. If you encounter a problem don't forget you can share your experience on the ecm mailing list .
We assume from now on that on your computer, you have the following ready-to-use environment:
Java Development Kit (JDK) 1.5.x (Nuxeo EP is known to work now with Java 6 or OpenJDK, but this is currently not supported)
Eclipse 3.4.0 (aka ganymede) for J2EE developper
A Nuxeo EP installation from the last release (download the
installation wizard). You can also download a nightly build
installer from http://www.nuxeo.org/static/snapshots/
, but keep in mind that this one may be broken, so
don't erase your working setup with a nightly build: the result is
not guaranteed.
Note: The Nuxeo EP installer also installs and sets up the right version of JBoss on your computer, so you don't need to install it by your own.
If some of these software are not already set up on your computer, please refer to the “Detailed Development Software Installation Instructions” appendix in the nuxeo book, where you will find useful help.
You should configure your Eclipse for loading the plugins listed above.
Nuxeo projects are built using the popular Maven build tool. Nuxeo packages are well described as maven artifacts. Nuxeo provides you a Maven repository that contains all you need for coding and assembling Nuxeo applications. This way, Nuxeo insures you that you're always running the correct version of software.
Maven Integration for Eclipse provides tight integration for Maven into the IDE. It especially provides wizards for creating new Maven projects and dependency management for build path based on Maven's pom file.
Here are the references for the Eclipse Update Manager:
Name: Update Site for Maven Integration URL: http://m2eclipse.sonatype.org/update
The Subversive plug-in gives you the ability to work with this CVS successor version control system from the Eclipse workbench. You can work with Subversion repositories in almost exactly the same way you can now work with CVS repositories using the CVS plug-in bundled in the standard Eclipse distribution.
Here are the references for the Eclipse Update Manager:
Name: Subversive Update Site is a part of URL: Ganymede Update Site. Look at Help > Software Updates... > Available Software > Ganymede > Collaboration Tools
Name: Subversive SVN Connectors URL: http://www.polarion.org/projects/subversive/download/eclipse/2.0/ganymede-site/
Nuxeo provides you a sample project that figures out main Nuxeo EP components uses by introducing the book document type. You will see how :
declaring the book document type;
regulating book document states;
making book documents indexable and searchable;
displaying book documents;
enabling drag and drop book creation mode;
handling book document creation events.
Run eclipse and create the project by running the “checkout maven project using SCM” wizard. The project SCM url is at org.nuxeo.project.sample. It can be quite long as it downloads all available package libraries and sources.
From the Java perspective, in the package explorer view, on the left side of the IDE, you can now see the Nuxeo project sample structure and you're able to browse all the classes without errors.
Now that you have created your project, you would want to see what your (not so tough) work produced?
You should first generate the jar artifact. From the package
explorer view, select the
nuxeo-project-sample folder and launch a
maven package build using the contextual menu : Run as
> Maven2 package. The project's target folder will
contain the generated plugin jar file
“nuxeo-project-sample-XXXX.jar”.
Then, you should copy
the jar file in the good Nuxeo directory. Create a
build.properties file on the base of the
build.properties.sample so that
jboss.dir points to your jboss path. Note that
when using the Nuxeo EP installer, the JBOSS home directory is the
same as the Nuxeo EP home directory.
Launch the dialog from Run > External
tools > External tools
configuration.... Select the “Ant
Build” tool and create a new
configuration using the contextual menu. Select the file
build.xml as buildfile and specify
copy as arguments.
You're now able to launch the copy of the generated plugin jar file using the external tools menu.
Defining a server configuration for the Nuxeo runtime enables you to start and stop Nuxeo directly from eclipse. This can be achieved by launching the new server wizard from the servers view. You should select a Jboss v4.0 server type and provide the Nuxeo EP home directory as server home. You shoud also configure a starting timeout value suitable for your computer. A typical value would be 60s in the nuxeo server properties view.
Open the internal web browser view and go to
http://localhost:8080/nuxeo/ . Log in nuxeo with Admin
signature (Administrator/Administrator), if your project was
correctly deployed, you should notice that the default font and logo
have changed.
When developing, you will find it useful not to have
to restart jboss when performing changes in xhtml
pages. Since releases 5.1.5 and 5.2-M2, you can add the line
facelets.REFRESH_PERIOD=2 to the
nuxeo.properties file in the
nuxeo.ear/config folder: pages will be
refreshed within 2 seconds.
For hot deploying web sample resources, you should use the ant
target web.
Here is the project source layout:
nuxeo-project-sample `-- src |-- main | |-- java| | `-- org | | `-- nuxeo | | `-- project | | `-- sample | `-- resources | |-- META-INF -- MANIFEST.MF
| |-- OSGI-INF
| | `-- l10n | |-- directories | |-- nuxeo.war
| | |-- icons | | |-- img | | `-- incl | | `-- tabs | |-- schemas | |-- themes | '-- workflows | `-- test
|-- java | `-- org | `-- nuxeo | `-- ecm | `-- sample `-- resources `-- META-INF `-- OSGI-INF
In the Nuxeo sample, a book is composed by the four
fields isbn,
rating, publicationDate and
literals. These fields are well defined in the book
schema. Here is the corresponding XML snipset extracted from the
books.xsd file:
... <xs:element name="isbn" type="xs:string"/> <xs:element name="rating" type="xs:int"/> <xs:element name="publicationDate" type="xs:date"/> <xs:element name="keywords" type="bk:stringArray"/> ...
Book schema and type are both declared in the
types service using extensions. Here is the
corresponding XML snipset extracted from the core-types-contrib.xml file
...
<extension target="org.nuxeo.ecm.core.schema.TypeService"
point="schema">
<schema name="book" src="schemas/book.xsd" prefix="bk">
</extension>
...
<extension target="org.nuxeo.ecm.core.schema.TypeService"
point="doctype">
<doctype name="Book" extends="Document">
...
<schema name="book" >
...
</doctype>
</extension>
...
Books are regulated by the standard life cycle
( project, approved,
obsolete, deleted states). This is
achieved by declaring to the lifecycle service an
extension that assign the default lifecycle to
book documents. Here is the corresponding XML snipset extracted from the
lifecycle-contrib.xml file
...
<extension
target="org.nuxeo.ecm.core.lifecycle.LifeCycleService" point="types">
<types>
<type name="Book">default</type>
</types>
</extension>
...
Books are figured out using a specific icon and label. This is
achieved by declaring to the types service the
associated resources. Here is the corresponding XML snipset extracted
from the ui-types-contrib.xml file
... <extension target="org.nuxeo.ecm.core.schema.TypeService" point="type"> ... <type id="Book" coretype="Book"> ... <label>Book</label> <icon>/icons/book.png</icon> ... </type> ... </extension> ...
Book documents are displayed under folders or workspaces. Theses
containment rules are declared to the types
service. Here is the XML snipset extracted from the
ui-types-contrib.xml that defines
them.
...
<extension target="org.nuxeo.ecm.platform.types.TypeService"
point="types">
...
<type id="Folder" coretype="Folder">
<subtypes>
<type>Book</type>
</subtypes>
</type>
<type id="Workspace" coretype="Workspace">
<subtypes>
<type>Book</type>
</subtypes>
</type>
...
</extension>
...
ISBN book field is displayed onto book's content tab. This is
achieved by registering into the web layout
service a new layout that includes the ISBN book number. Here is the XML
snipset extracted from the layouts-contrib.xml
:
...
<extension target="org.nuxeo.ecm.platform.forms.layout.WebLayoutManager"
point="layouts">
...
<layout name="book">
...
<widget name="isbn" type="text">
<labels>
<label mode="any">ISBN</label>
</labels>
<fields>
<field>bk:isbn</field>
</fields>
</widget>
...
</layout>
...
</extension>
...
The types service is configured for
displaying the book layout. Here is the XML snipset extracted from the
ui-types-contrib.xml :
...
<extension target="org.nuxeo.ecm.platform.types.TypeService"
point="types">
...
<type id="Book" coretype="Book">
...
<layouts mode="any">
<layout>heading</layout>
<layout>book</layout>
<layout>file</layout>
</layouts>
...
</type>
...
</extension>
...
Specific book behaviours are available onto book and workspace
documents. Each corresponding tab is declared to the
actions service. Note that tab's templates are
defined into the folder nuxeo.war/inc/tabs. Note
also that these templates get their model using the
BookManagerBean which implements book behaviours.
Here is the XML snipset extracted from the
actions-contrib.xml file :
... <extension target="org.nuxeo.ecm.platform.actions.ActionService" point="actions"> ... <action id="tab_book_view" link="/incl/tabs/book_view.xhtml" enabled="true" label="Book" icon="/icons/file.gif" order="9"> ... </action> ... <action id="tab_folder_books_list" link="/incl/tabs/folder_books_view.xhtml" enabled="true" label="Books" icon="/icons/file.gif" order="15"> ... </action> ... </extension> ...
Book documents are subject to rights management and the
corresponding tab should be displayed. ere is the XML snipset
extracted from the actions-contrib.xml file :
...
<extension target="org.nuxeo.ecm.platform.actions.ActionService" point="actions">
...
<filter id="rights" append="true">
<rule grant="true">
<type>Book</type>
</rule>
</filter>
...
</extension>
...
Book documents are made indexable by declaring an
indexableDocType extension point to the search
service in the search-contrib.xml file. Here is the
XML snipset extracted from the search-contrib.xml
file
... <extension target="org.nuxeo.ecm.core.search.service.SearchServiceImpl" point="indexableDocType"> <indexableDocType indexAllSchemas="true" name="Book" /> </extension> ...
Books are searched by keywords using
using the query model service. Here is the XML
snipset extracted from the querymodel-contrib.xml
file :
...
<extension
target="org.nuxeo.ecm.core.search.api.client.querymodel.QueryModelService"
point="model">
...
<queryModel name="BOOK">
...
<pattern>
SELECT * FROM Document WHERE ecm:primaryType = 'Book' AND
dc:subjects = ?
</pattern>
...
</queryModel>
...
</extension>
...
Query models are retrieved and invoked by the
BookResultsProvider which provide the criterias
from the session context. The BookResultsProvider
is registered into the results provider service.
Here is the XML snipset extracted from the
resultsprovider-contrib.xml file :
... <extension target="org.nuxeo.ecm.webapp.pagination.ResultsProviderService" point="model"> <resultsProvider name="BOOK" farm="bookResultsProvider" /> </extension> ...
Finally, books are searched and listed in the book's tab
using the results provider cache. Here is the XHTML snipset extracted
from the folder_books_view.xhtnml :
...
<nxu:methodResult name="provider"
value="#{resultsProvidersCache.get('BOOK')}">
<h:form>
<ui:decorate template="/pagination/pageNavigationControls.xhtml">
<ui:param name="provider" value="#{provider}" />
</ui:decorate>
</h:form>
<h:dataTable var="bookinfo" value="#{provider.currentPage}"
...
</h:dataTable>
...
Dragging an image onto a workspace will create a book document.
The BookFileManagerPlugin request the file
manager service for listening to jpeg and
gif images upload events. At it will be notified, it
creates book document models, synthetizing titles based on the uploaded
filename, normalizing them by invoking the
BookTitleService. Here is the XML snipset
extracted from the
fileManager-contrib.xml
... <extension target="org.nuxeo.ecm.platform.filemanager.service.FileManagerService" point="plugins"> ... <plugin name="book_plugin" class="org.nuxeo.project.sample.BookFileManagerPlugin"> <filter>image/gif</filter> <filter>image/jpeg</filter> </plugin> ... </extension> ...
The BookTitleService is defined as a
service. The BookTitleDescriptor defines the
configuration format suitable for this service. Here is the XML snipset
extracted from the booktitle-service-contrib.xml
file
... <implementation class="org.nuxeo.project.sample.BookTitleServiceImpl" /> <service> <provide interface="org.nuxeo.project.sample.BookTitleService" /> </service> <extension-point name="title"> <object class="org.nuxeo.project.sample.BookTitleDescriptor" /> </extension-point> ...
Empty book document models are filled by default. At the other
hand, the keywords dictionary is automatically filled using the ISBN
numbers and titles. This is achieved by registering the two event
listeners BookEventListener and
BookISBNEventListener into the
event service for receiving document events. Here
is the XML snipset extracted from the
event-contrib.xml file :
... <extension target="org.nuxeo.ecm.core.listener.CoreEventListenerService" point="listener"> <listener name="book_create" class="org.nuxeo.project.sample.BookEventListener"> <eventId>emptyDocumentModelCreated</eventId> </listener> <listener name="book_update_isbn" class="org.nuxeo.project.sample.BookISBNEventListener" order="157"> <eventId>documentCreated</eventId> <eventId>documentModified</eventId> </listene> </extension> ...
The keywords dictionary is configured in the
directories-contrib.xml file:
<extension target="org.nuxeo.ecm.directory.sql.SQLDirectoryFactory"
point="directories">
<directory name="book_keywords">
<schema>vocabulary</schema>
<idField>id</idField>
<dataSource>java:/nxsqldirectory</dataSource>
<table>book_keywords</table>
<!-- one of "never", "on_missing_columns" or "always" -->
<createTablePolicy>on_missing_columns</createTablePolicy>
<dataFile>directories/book_keywords.csv</dataFile>
</directory>
</extension>
The goal of the nuxeo-archetype-start template is to setup a Nuxeo EP plugin development environment. The template provides: a maven layout for sources, tests and dependencies, an Ant target for deployment. It also customizes the web application a litte bit.
Start the “new maven project” wizard from the menu File > New > Maven project. Enable your eclipse for using Nuxeo EP's by addind a remote archetypes catalog using the configure dialog. The URL to be used is as follow http://maven.nuxeo.org/nuxeo-release/. Select the archetype type nuxeo-archetype-start and the nuxeo's version you want your project based. Set the artifact parameters according to your organisation rules.
The Nuxeo Book is getting to be the most complete source of information around Nuxeo EP, both for beginners and advanced developer. It is a good start.
The extension point documentation is also very useful: although you may find it rough, it is the best way to evaluate the Nuxeo extensibility potential, and one should always start with a quick look around all the extension points, to "think Nuxeo" before starting a new project, and not reinventing the wheel.
The wiki: we try to reference all the documentation from the wiki welcome page, and you will find tricks, howtos, etc. If you want to have a writer account to help update the content, ask on the Nuxeo's mailing list.
IntelliJ IDEA from Jetbrains is a very lovable IDE for Java that has many fans in the Java developers community. It is unfortunately not open source.
To start using IDEA for coding on the Nuxeo project, you just need
to type mvn idea:idea from your top-level source
directory: Maven will download all the dependencies, then generate the
configuration files needed by IDEA and you will be able open
nuxeo-ecm.ipr from IDEA.
At the time of this writing, IDEA will report some (spurious) compilation failures and you won't be able to compile the whole application from IDEA. You can still use IDEA with the current configuration to write Java code ("with pleasure"), and use Ant and/or Maven to build/deploy the application.