Copyright © 1999-2008 UCS - unique computing solutions gmbh
Table of Contents
List of Figures
List of Tables
List of Examples
Managing and operating on hierarchical data structures is an issue in many projects, alongside with security concerns, versioning and querying. Till now, neither open nor closed source projects or frameworks offer possibilities to dynamically define and manipulate the structure of hierarchical data in a scope like [fleXive]. Hence the urge to provide a solution that combines flexibility, security and performance in one customizable package.
[fleXive] is a JavaEE 5 open-source (LGPL) framework for the development of complex and evolving (web-)applications. It speeds up development as it handles numerous important application issues and keeps your application flexible over the development-cycle. It is based on the lastest industry-standards like EJB 3, JSF, etc.
The [fleXive] backend application is an optional application built on top of the framework and is licensed under the GNU General Public License (GPL). It helps you to visually manage most aspects of [fleXive] - like defining data structures, building queries, manage users and security, etc.
[fleXive] concentrates on enterprise-scale content storage and retrieval, and includes comprehensive JSF support for displaying and manipulating these contents in web applications. The runtime environment can be included in existing JavaEE applications, but you can also build new applications and package them into stand-alone JavaEE applications. Our emphasis lies on the runtime environment, so if you are looking e.g. for tool-driven JSF development, take a look at the popular JBoss Seam framework and embed the [fleXive] runtime environment in that project.
The goal of [fleXive] is to relieve you from many tendious and repetitive programming tasks when building secure, data-centric (web-)applications.
If you are new to [fleXive] please use the following tools to get started:
The [fleXive] website will provide you with top-level information about [fleXive]. Have a look at the "Explore [fleXive]" section.
This reference documentation will provide all information to use [fleXive] for the development of your application.
In the [fleXive] wiki you will find more tutorials, HowTo's, samples and developer infos
For questions, use the [fleXive] forum and mailinglists. We also provide a issue trackings system for bug reports and feature requests. In case you are interested in the development of [fleXive], have a look at the Development Section on the [fleXive] website and join the developer mailinglist.
[fleXive] is a Professional Open Source project. UCS - unique computing solutions gmbh (http://www.ucs.at) offers commercial development support and training for [fleXive].
Table of Contents
Administrator privileges on your machine
The Sun Java 6 Platform, Standard Edition Development Kit
JAVA_HOME and JDK_HOME
environment variable to your JDK root directory (e.g.
JAVA_HOME=/usr/lib/jvm/java-6-sun
on Linux,
C:\Java\jdk1.6.0_03
on Windows)
An application server ( JBoss or Glassfish) with EJB3 support
${jboss.home}
denotes your JBoss installation
directory)
${glassfish.home}
denotes your Glassfish installation directory)
A database (at the moment only MySql is supported)
Download and install MySql 5.0 or later
Currently, choosing UTF-8 as the default charset causes issues with the database setup scripts. Use the default setting (Latin1) instead.
ImageMagick version 6.3.4 or later (optional)
Apache ANT 1.7 and the ant-optional package
A [fleXive] binary distribution or the [fleXive] source code, if you want to build [fleXive] from source
If you are interested in developing [fleXive], you will need the [fleXive] source code and an IDE like Eclipse or a proprietary solution.
The following sections are good starting points for future [fleXive] developers:
We provide the current generated [fleXive] API Documentation for you on our website.
The following required libraries have to be deployed:
Copy the following file from the
extlib
directory of your [fleXive] binary distribution to
${jboss.home}/server/default/lib:
mysql-connector-java-*.jar
(Alternatively you can download the latest stable
MySQL JDBC
driver)
Create and copy the datasource config file
flexive-ds.xml
to
${jboss.home}/server/default/deploy/
and adapt to your datasource(s)
or simply copy it from the [fleXive] source tree, if available.
In the
flexive-ds.xml
configure your database connections as follows:
For the
flexive
database
<!-- transactional datasource --> <xa-datasource> <jndi-name>jdbc/flexiveDivision1</jndi-name> <xa-datasource-class>com.mysql.jdbc.jdbc2.optional.MysqlXADataSource</xa-datasource-class> <!-- Note: "&" has to be used instead of "&" for parameters --> <xa-datasource-property name="URL">jdbc:mysql://localhost:3306/flexive?useUnicode=true&characterEncoding=utf8&characterResultSets=utf8</xa-datasource-property> <user-name>root</user-name> <password>a</password> </xa-datasource> <!-- non-transactional datasource for database structure patches, Quartz, etc. --> <no-tx-datasource> <jndi-name>jdbc/flexiveDivision1NoTX</jndi-name> <driver-class>com.mysql.jdbc.Driver</driver-class> <!-- Note: "&" has to be used instead of "&" for parameters --> <connection-url>jdbc:mysql://localhost:3306/flexive?useUnicode=true&characterEncoding=utf8&characterResultSets=utf8</xa-datasource-property> <user-name>root</user-name> <password>a</password> </no-tx-datasource>
For the
flexiveConfiguration
database
<xa-datasource> <jndi-name>jdbc/flexiveConfiguration</jndi-name> <xa-datasource-class>com.mysql.jdbc.jdbc2.optional.MysqlXADataSource</xa-datasource-class> <!-- Note: "&" has to be used instead of "&" for parameters --> <xa-datasource-property name="URL">jdbc:mysql://localhost:3306/flexiveConfiguration?useUnicode=true&characterEncoding=utf8&characterResultSets=utf8</xa-datasource-property> <user-name>root</user-name> <password>a</password> </xa-datasource>
flexive-ds.xml
<!--
JBoss Datasource Configuration
See http://www.redhat.com/docs/manuals/jboss/jboss-eap-4.3/doc/Server_Configuration_Guide/html/Connectors_on_JBoss-Configuring_JDBC_DataSources.html
for detailed configuration infos
-->
<datasources>
<!--
transactional datasource, as configured in the global configuration
-->
<xa-datasource>
<jndi-name>jdbc/flexiveDivision1</jndi-name>
<xa-datasource-class>com.mysql.jdbc.jdbc2.optional.MysqlXADataSource</xa-datasource-class>
<!-- Note: "&" has to be used instead of "&" for parameters -->
<xa-datasource-property name="URL">jdbc:mysql://localhost:3306/flexive?useUnicode=true&characterEncoding=utf8&characterResultSets=utf8</xa-datasource-property>
<user-name>root</user-name>
<password>a</password>
<transaction-isolation>TRANSACTION_READ_COMMITTED</transaction-isolation>
<no-tx-separate-pools/>
<!-- This disables transaction interleaving (which BTW, most DB vendors don't support) -->
<track-connection-by-tx/>
<isSameRM-override-value>false</isSameRM-override-value>
<!--pooling parameters-->
<min-pool-size>5</min-pool-size>
<max-pool-size>20</max-pool-size>
<blocking-timeout-millis>5000</blocking-timeout-millis>
<idle-timeout-minutes>15</idle-timeout-minutes>
<!-- If you supply the usr/pw from a JAAS login module -->
<security-domain/>
<exception-sorter-class-name>
com.mysql.jdbc.integration.jboss.ExtendedMysqlExceptionSorter
</exception-sorter-class-name>
<valid-connection-checker-class-name>
com.mysql.jdbc.integration.jboss.MysqlValidConnectionChecker
</valid-connection-checker-class-name>
<metadata>
<type-mapping>mySQL</type-mapping>
</metadata>
</xa-datasource>
<!--
non-transactional datasource for database structure patches, Quartz, etc.
As per convention, non-transactional datasources have the same name like
transactional but use the suffix "NoTX"
-->
<no-tx-datasource>
<jndi-name>jdbc/flexiveDivision1NoTX</jndi-name>
<driver-class>com.mysql.jdbc.Driver</driver-class>
<!-- Note: "&" has to be used instead of "&" for parameters -->
<connection-url>jdbc:mysql://localhost:3306/flexive?useUnicode=true&characterEncoding=utf8&characterResultSets=utf8</connection-url>
<user-name>root</user-name>
<password>a</password>
<!--pooling parameters-->
<min-pool-size>5</min-pool-size>
<max-pool-size>20</max-pool-size>
<blocking-timeout-millis>5000</blocking-timeout-millis>
<idle-timeout-minutes>15</idle-timeout-minutes>
<!-- If you supply the usr/pw from a JAAS login module -->
<security-domain/>
<exception-sorter-class-name>
com.mysql.jdbc.integration.jboss.ExtendedMysqlExceptionSorter
</exception-sorter-class-name>
<valid-connection-checker-class-name>
com.mysql.jdbc.integration.jboss.MysqlValidConnectionChecker
</valid-connection-checker-class-name>
<metadata>
<type-mapping>mySQL</type-mapping>
</metadata>
</no-tx-datasource>
<xa-datasource>
<jndi-name>jdbc/flexiveConfiguration</jndi-name>
<xa-datasource-class>com.mysql.jdbc.jdbc2.optional.MysqlXADataSource</xa-datasource-class>
<!-- Note: "&" has to be used instead of "&" for parameters -->
<xa-datasource-property name="URL">jdbc:mysql://localhost:3306/flexiveConfiguration?useUnicode=true&characterEncoding=utf8&characterResultSets=utf8</xa-datasource-property>
<user-name>root</user-name>
<password>a</password>
<transaction-isolation>TRANSACTION_READ_COMMITTED</transaction-isolation>
<no-tx-separate-pools/>
<!-- This disables transaction interleaving (which BTW, most DB vendors don't support) -->
<track-connection-by-tx/>
<isSameRM-override-value>false</isSameRM-override-value>
<!--pooling parameters-->
<min-pool-size>5</min-pool-size>
<max-pool-size>20</max-pool-size>
<blocking-timeout-millis>5000</blocking-timeout-millis>
<idle-timeout-minutes>15</idle-timeout-minutes>
<!-- If you supply the usr/pw from a JAAS login module -->
<security-domain/>
<exception-sorter-class-name>
com.mysql.jdbc.integration.jboss.ExtendedMysqlExceptionSorter
</exception-sorter-class-name>
<valid-connection-checker-class-name>
com.mysql.jdbc.integration.jboss.MysqlValidConnectionChecker
</valid-connection-checker-class-name>
<metadata>
<type-mapping>mySQL</type-mapping>
</metadata>
</xa-datasource>
</datasources>
To set up the databases do the following
Adapt the
database.properties
file located in your
flexive-dist
directory of your [fleXive] distribution to your needs:
# This is the database configuration file used by the flexive setup tasks. # # Enter the settings for your database server connection to be used for development. # The server host or IP database.host=localhost # The server port database.port=3306 # The user name and password to be used for creating flexive database structures database.username=root database.password=a
Change to the
flexive-dist
directory of your [fleXive] distribution and run
ant db.create db.config.create
You will be prompted to enter a name for your division database (simply hit enter to keep
flexive).
Warning: Existing databases will be deleted.
Change to the
flexive-dist
directory of your [fleXive] distribution and run
ant ear. This will create the
flexive.ear
file inside the
flexive-dist
directory. Copy
flexive.ear
to
${jboss.home}/server/default/deploy.
Currently JBoss (4.2) uses the Java's default maximum heap size,
which means that [fleXive] will probably run out of memory during the
first startup. You have to set the maximum heap size using
-Xmx
to a larger value, at least 256m.
On Linux execute
export JAVA_OPTS="-Xms128m -Xmx512m"
On Windows execute
SET JAVA_OPTS=-Xms128m -Xmx512m
Change to the
${jboss.home}/bin
directory.
On Linux launch JBoss using
sh run.sh -c default -Djboss.bind.address=0.0.0.0
On Windows launch JBoss using
start run.bat -c default -Djboss.bind.address=0.0.0.0
To access the backend point your browser to http://localhost:8080/flexive/adm/
Alternatively you can specify your server's IP address, which is supported by default, too.
The default superuser's username and password for the Backend Administration are:
username: supervisor, password: supervisor
Extend
${jboss.home}/server/default/conf/jboss-log4j.xml
to configure logging:
<!-- Limit flexive -->
<category name="com.flexive">
<priority value="INFO"/>
</category>
<!-- Limit ajax4jsf -->
<category name="org.ajax4jsf">
<priority value="WARN"/>
</category>
Optional if you need JAAS support: Extend
${jboss.home}/server/default/conf/login-config.xml
with the following entry:
<application-policy name = "FxLogin">
<authentication>
<login-module code="com.flexive.core.security.FxDefaultLogin" flag="required"></login-module>
</authentication>
</application-policy>
Optional step: To use an external service deployer for JBoss Cache,
create the cache service file
99_JBossCacheJNDI42-service.xml
in
${jboss.home}/server/default/deploy/
or simply copy it from the [fleXive] source tree, if available:
<?xml version="1.0" encoding="UTF-8"?>
<server>
<loader-repository>com.flexive:archive=flexive.ear
</loader-repository>
<!-- ========================================================== -->
<!-- Clustered SFSB cache config for use with JBoss Cache 1.4.x -->
<!-- ========================================================== -->
<mbean code="org.jboss.cache.jmx.CacheJmxWrapper"
name="jboss.cache:service=JNDITreeCache">
<!--<depends>jboss:service=Naming</depends>-->
<!--<depends>jboss:service=TransactionManager</depends>-->
<attribute name="TransactionManagerLookupClass">org.jboss.cache.transaction.GenericTransactionManagerLookup</attribute>
<!--
Node locking scheme :
PESSIMISTIC (default)
OPTIMISTIC
-->
<attribute name="NodeLockingScheme">PESSIMISTIC</attribute>
<attribute name="ClusterName">[fleXive]-Cache-JNDI</attribute>
<!--
Node locking level : SERIALIZABLE
REPEATABLE_READ (default)
READ_COMMITTED
READ_UNCOMMITTED
NONE
-->
<attribute name="IsolationLevel">READ_COMMITTED</attribute>
<!-- Valid modes are LOCAL
REPL_ASYNC
REPL_SYNC
-->
<attribute name="CacheMode">REPL_ASYNC</attribute>
<!-- We want to activate/inactivate regions as beans are deployed -->
<attribute name="UseRegionBasedMarshalling">true</attribute>
<!-- Must match the value of "useRegionBasedMarshalling" -->
<attribute name="InactiveOnStartup">true</attribute>
<!--
JGroups protocol stack config in XML format.
If your CacheMode is set to REPL_SYNC we recommend you comment
out the FC (flow control) protocol
On Windows machines, because of the media sense feature
being broken with multicast (even after disabling media sense)
set the UDP.loopback attribute to true
-->
<attribute name="ClusterConfig">
<config>
<UDP mcast_addr="${flexive.cluster.udpGroup:229.1.2.5}"
mcast_port="${jboss.ejb3sfsbpartition.mcast_port:45557}"
tos="8"
ucast_recv_buf_size="20000000"
ucast_send_buf_size="640000"
mcast_recv_buf_size="25000000"
mcast_send_buf_size="640000"
loopback="false"
discard_incompatible_packets="true"
enable_bundling="false"
max_bundle_size="64000"
max_bundle_timeout="30"
use_incoming_packet_handler="true"
use_outgoing_packet_handler="false"
ip_ttl="${jgroups.udp.ip_ttl:2}"
down_thread="false" up_thread="false"/>
<PING timeout="2000"
down_thread="false" up_thread="false" num_initial_members="3"/>
<MERGE2 max_interval="100000"
down_thread="false" up_thread="false" min_interval="20000"/>
<FD_SOCK down_thread="false" up_thread="false"/>
<FD timeout="10000" max_tries="5" down_thread="false" up_thread="false" shun="true"/>
<VERIFY_SUSPECT timeout="1500" down_thread="false" up_thread="false"/>
<pbcast.NAKACK max_xmit_size="60000"
use_mcast_xmit="false" gc_lag="0"
retransmit_timeout="300,600,1200,2400,4800"
down_thread="false" up_thread="false"
discard_delivered_msgs="true"/>
<UNICAST timeout="300,600,1200,2400,3600"
down_thread="false" up_thread="false"/>
<pbcast.STABLE stability_delay="1000" desired_avg_gossip="50000"
down_thread="false" up_thread="false"
max_bytes="400000"/>
<pbcast.GMS print_local_addr="true" join_timeout="3000"
down_thread="false" up_thread="false"
join_retry_timeout="2000" shun="true"
view_bundling="true"
view_ack_collection_timeout="5000"/>
<FC max_credits="2000000" down_thread="false" up_thread="false"
min_threshold="0.10"/>
<FRAG2 frag_size="60000" down_thread="false" up_thread="false"/>
<pbcast.STATE_TRANSFER down_thread="false" up_thread="false" use_flush="false"/>
</config>
</attribute>
<!-- The max amount of time (in milliseconds) we wait until the
initial state (ie. the contents of the cache) are retrieved from
existing members.
-->
<attribute name="InitialStateRetrievalTimeout">17500</attribute>
<!-- Number of milliseconds to wait until all responses for a
synchronous call have been received.
-->
<attribute name="SyncReplTimeout">17500</attribute>
<!-- Max number of milliseconds to wait for a lock acquisition -->
<attribute name="LockAcquisitionTimeout">15000</attribute>
<!-- Specific eviction policy configurations. -->
<attribute name="EvictionPolicyConfig">
<config>
<attribute name="policyClass">org.jboss.cache.eviction.LRUPolicy</attribute>
<attribute name="wakeUpIntervalSeconds">5</attribute>
<name>flexiveMain</name>
<!-- So default region would never timeout -->
<region name="/_default_">
<attribute name="maxNodes">0</attribute>
<attribute name="timeToLiveSeconds">0</attribute>
</region>
<!-- cache region for contents -->
<region name="/Division1/FxContent">
<attribute name="maxNodes">1000</attribute>
<attribute name="timeToLiveSeconds">1000</attribute>
</region>
<!-- cache region for user configuration -->
<region name="/Division1/userConfig">
<attribute name="maxNodes">10000</attribute>
<attribute name="timeToLiveSeconds">1000</attribute>
</region>
</config>
</attribute>
</mbean>
</server>
If you want to use the external cache deplyoment you have to apply another modification:
Due to classloading issues ([fleXive] uses JBoss Cache 2.x, while
JBoss 4.2 uses JBoss Cache 1.x) you need to modify the deployment scanner in
${jboss.home}/server/default/conf/jboss-service.xml:
replace the entry
<attribute name="URLComparator">org.jboss.deployment.DeploymentSorter</attribute>with
<attribute name="URLComparator">org.jboss.deployment.scanner.AlphaNumericDeploymentSorter</attribute>This ensures that the cache service is started after flexive.ear is deployed and thus can use its cache implementation classes (this deployment scanner allows to influence the deployment order with a numeric prefix, otherwise it's the same as the default one).
Flexive needs several libraries to be deployed to the application server's internal
lib
directories. Execute these steps once glassfish has been setup.
We provide an ant task for you which copies all libraries needed to deploy [fleXive] on Glassfish V2 to the specified directory.
Change to the
flexive-dist
directory of your [fleXive] distribution and run
ant glassfish.libs.
You will be prompted to specify your
${glassfish.home}/domains/domain1/lib/ext
directory.
The
ant
task will copy all required libraries to this directory.
Copy the
jbosscache-core.jar
from the
extlib
directory of your [fleXive] binary distribution to
${glassfish.home}/lib
To set up the databases, follow these instructions.
Setting up Glassfish
Go to the target installation directory
java -Xmx256m -jar <<path-to-downloaded-jar>>
extracts the installation JAR to
./glassfish
cd glassfish
On Unix: chmod -R +x lib/ant/bin
Execute the
setup.xml
buildfile
Unix: lib/ant/bin/ant -f setup.xml
Windows: lib\ant\bin\ant -f setup.xml
Starting Glassfish
bin/asadmin start-domain domain1 starts the Glassfish server
http://localhost:4848/ and login using default credentials admin/adminadmin.
Additional information
To stop the Glassfish instance execute ${glassfish.home}/bin/asadmin stop-domain domain1
Admin UI Port: 4848
HTTP Port: 8080
HTTPS Port: 8181
Three connection pools, two for the division (transactional and non-transactional) and one for the configuration database, have to be set up.
Copy and paste the following data-source definitions to a file (e.g.
flexive-ds.xml)
and update your database connection settings:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE resources PUBLIC "-//Sun Microsystems Inc.//DTD Application Server 9.0 Domain//EN" "sun-resources_1_3.dtd">
<resources>
<!--
Glassfish datasource configuration
To add these datasource, start Glassfish v2, and execute
${glassfish.home}/bin/asadmin add-resources /path/to/flexive-ds.xml
-->
<!-- Configure the global configuration datasource -->
<jdbc-connection-pool
name="flexiveConfiguration"
datasource-classname="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource"
res-type="javax.sql.XADataSource">
<property name="user" value="root"/>
<property name="password" value="a"/>
<property name="url" value="jdbc:mysql://localhost:3306/flexiveConfiguration?useUnicode=true&characterEncoding=utf8&characterResultSets=utf8"/>
</jdbc-connection-pool>
<jdbc-resource pool-name="flexiveConfiguration" jndi-name="jdbc/flexiveConfiguration" enabled="true" object-type="user"/>
<!-- Configure the first flexive division -->
<jdbc-connection-pool
name="flexiveDivision1"
datasource-classname="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource"
res-type="javax.sql.XADataSource">
<property name="user" value="root"/>
<property name="password" value="a"/>
<property name="url" value="jdbc:mysql://localhost:3306/flexive?useUnicode=true&characterEncoding=utf8&characterResultSets=utf8"/>
</jdbc-connection-pool>
<jdbc-resource pool-name="flexiveDivision1" jndi-name="jdbc/flexiveDivision1" enabled="true" object-type="user"/>
<!-- Configure the first flexive division non-XA datasource -->
<jdbc-connection-pool
name="flexiveDivision1NoTX"
datasource-classname="com.mysql.jdbc.jdbc2.optional.MysqlDataSource"
res-type="javax.sql.DataSource">
<property name="user" value="root"/>
<property name="password" value="a"/>
<property name="url" value="jdbc:mysql://localhost:3306/flexive?useUnicode=true&characterEncoding=utf8&characterResultSets=utf8"/>
</jdbc-connection-pool>
<jdbc-resource pool-name="flexiveDivision1NoTX" jndi-name="jdbc/flexiveDivision1NoTX" enabled="true" object-type="user"/>
</resources>
While Glassfish is running, execute ${glassfish.home}/bin/asadmin add-resources /path/to/flexive-ds.xml to create the connection pools and JDBC resources. You have to pass the absolute path to your XML file, otherwise Glassfish looks in its own config directory.
Should you need to edit or reset your datasources, you can do so in the Glassfish administration console under →
Change to the
flexive-dist
directory of your [fleXive] distribution and run
ant ear. This will create the
flexive.ear
file inside the
flexive-dist
directory.
Using the autodeploy directory:
Copy the
flexive.ear
to
${glassfish.home}/domains/domain1/autodeploy
Using the Admin UI:
In the Admin Console, go to →
Click
Deploy...
and upload the
flexive.ear
file.
Click
OK
To access the backend point your browser to http://localhost:8080/flexive/adm/ Alternatively you can specify your server's IP address, which is supported by default, too. The default superuser's username and password for the Backend Administration are username: supervisor, password: supervisor.
This procedure is for those building [fleXive] from the source code.
build.properties.sample
file located in the root directory of the
[fleXive] source code
to
build.properties.
jboss.home=/path/to/jboss
# path to deploy the ear
deploy.ear.path=${jboss.home}/server/all/deploy
# path to deploy needed runtime libs like emma.jar
deploy.lib.path=${jboss.home}/server/all/lib
# path to the embedded jboss ejb3 container neededfor unit testing
jboss.embedded.path=${jboss.home}/jboss-embeddable/
# (...)
ant db.update
before
ant all
in the root directory of the
[fleXive] source code,
where the
build.xml
file
resides.
This will recreate all configured databases and destroy existing data.
To deploy the ear execute
ant deploy
Don't forget to set your
${jboss.home}
variable in the
build.properties
file properly!
JDK_HOME
and
JAVA_HOME
variables accordingly as explained in section
Prerequisites.
If there are multiple JBoss installations running in your local network you need
to assign a different partition UDP group to each cluster! This can be done by adding
-Djboss.partition.udpGroup=230.2.3.4
(or any other multicast address you choose thats available)
to the start script/command shown in
Starting [fleXive].
In order to run JBossCache on Linux IPv4 needs to be defined as the preferred IP stack. In the Glassfish admin console, go to → → and add the following option:
-Djava.net.preferIPv4Stack=true
If an ant-task fails, make sure you have Apache ANT 1.7 installed.
If you get the following warning:
Problem: failed to create task or type javacc when executing ant
make sure you installed the ant-optional package.
In this chapter we will get hands-on and create a few demo applications with [fleXive]. These applications are part of the binary and source distributions, but you can also download them as separate projects:
To run any of these, unzip them to a local directory. Unzip the [fleXive] distribution from the
download page in the same directory, remove the precompiled examples from
flexive-dist/applications,
and execute
ant
in the example directory. You can then deploy the
dist/[example-name].ear
file to your application server. For example (using Linux):
$ unzip flexive-dist.zip $ unzip example-helloworld.zip $ ls flexive-dist helloworld $ cd helloworld $ ant $ ls dist helloworld.ear helloworld-shared.jar helloworld.war
Before setting out on your own, you might also want to read Chapter 4, Writing [fleXive] applications , which also explains how to use Apache Maven as your build tool.
Our first [fleXive] application implements a very simple blogging system with an input mask and a view for the submitted entries. We assume you have a flexive installation up and running on your local or on a remote machine. If not, follow the instructions in Chapter 2, Installing [fleXive] . The complete source code can be found here or in the subversion repository under src/examples/helloworld.
First we create a new [fleXive] project: go to the directory where you unpacked the distribution,
and execute
ant project.create.
You will be prompted for the name of the new project. Enter
helloworld
and confirm your input. If all went well, the output should look like the following:
/tmp/flexive-dist$ ant project.create
Buildfile: build.xml
check:
project.create:
[input] Name of the project you want to create:
helloworld
[flexive]
[flexive] Please confirm your input:
[flexive] Project name: helloworld
[flexive] Base directory: ../helloworld
[flexive]
[input] Are these settings correct? ([y], n)
y
[mkdir] Created dir: /tmp/helloworld
[copy] Copying 13 files to /tmp/helloworld
[copy] Copied 29 empty directories to 6 empty directories under /tmp/helloworld
[copy] Copying 1 file to /tmp/helloworld
[copy] Copying 1 file to /tmp/helloworld
[echo] Project helloworld created successfully. The project root directory is
[echo] ../helloworld
BUILD SUCCESSFUL
The new project is created in the parent directory of the distribution, i.e. in
../helloworld,
and looks like this:
flexive-dist
|-- ...
helloworld
|-- build.xml
|-- database.properties
|-- lib
|-- resources
| |-- META-INF
| | |-- faces-config.xml
| | `-- web.xml
| |-- messages
| |-- scripts
| | |-- library
| | |-- runonce
| | `-- startup
| `-- templates
|-- src
| `-- java
| |-- ejb
| | `-- ...
| |-- shared
| | `-- ...
| `-- war
| `-- ...
`-- web
`-- index.xhtml
helloworld/src/java
contains the Java sources of the application.
helloworld/resources/scripts
contains [fleXive] scripts that will be used to setup the data structures needed by the application.
helloworld/web
contains the XHTML pages and the web configuration files.
We start with defining the data model of the application. Our blog entry consists of a
posting title and the actual text. To set up the data model when deploying the application,
we create a
run-once script
in the
resources/scripts/runonce/
directory,
hello001.groovy.
A straight-forward way of setting up [fleXive] structures is by using the
GroovyTypeBuilder
for [fleXive] types, using the Groovy scripting language.
import com.flexive.shared.scripting.groovy.* import com.flexive.shared.value.* import com.flexive.shared.structure.* new GroovyTypeBuilder().blogEntry(description: new FxString(true, "Blog Entry"), usePermissions: false) { //caption(assignment: "ROOT/CAPTION") entryTitle(multiplicity: FxMultiplicity.MULT_1_1, description: new FxString(true, "Title")) //
entryText(multiplicity: FxMultiplicity.MULT_1_1, description: new FxString(true, "Text"), multiline: true) //
}
|
The method call blogEntry(...) will create the [fleXive] type "BlogEntry" (type names are not case sensitive). For the first tutorial, we will disable [fleXive] security completely for this type by setting usePermissions to false. | |
|
Create a new property assignment for the blog entry type that is referenced with the path "/entryTitle". The multiplicity of 1..1 indicates a mandatory field, the description will be shown in the input forms. | |
|
The text property is created similar to the title, but we add a "multiline" option since we don't want to enter our blog text in a single line. |
The next step is to define a JSF bean that provides the blog postings
to be shown on the front page of our application. We create a managed bean under
src/java/war,
which will be automatically compiled and packaged into the WAR archive.
import com.flexive.faces.model.FxResultSetDataModel; import com.flexive.shared.exceptions.FxApplicationException; import com.flexive.shared.search.FxResultSet; import com.flexive.shared.search.SortDirection; import com.flexive.shared.search.query.SqlQueryBuilder; import javax.faces.model.DataModel; public class HelloWorldBean { private DataModel blogEntries; public DataModel getBlogEntries() throws FxApplicationException { if (blogEntries == null) { final FxResultSet result = new SqlQueryBuilder() .select("@pk", "entryTitle", "entryText", "created_at") //.type("blogEntry") .orderBy("created_at", SortDirection.DESCENDING) //
.getResult(); blogEntries = new FxResultSetDataModel(result); } return blogEntries; } }
|
We choose the columns to be selected for the result set:
| |
|
To display the newest postings first, we order by descending creation date
( |
For the web interface of the application we use JSF 1.2, using Facelets for creating the JSF views (i.e. we use plain XHTML templates instead of JSP). [fleXive] includes components for rendering and editing [fleXive] contents in JSF applications, although you could also use other web framework like Struts or Tapestry - you'd just miss the convenient UI components that allow a rapid creation of web applications based on [fleXive].
If you are not familiar with JSF tag libraries please refer to the Tag Library Documentation or try the JSF section of the Java EE 5 Tutorial.
The main page renders all available blog entries and shows a link to a form
for creating new entries. Facelets'
<ui:repeat/>
tag is used to iterate over the rows of the datamodel returned by the JSF bean we created in the
previous
section. A row of the datamodel provides indexed access to the columns selected in the
search query of the previous section.
In this case,
#{columns[0]}
would be the content primary key
(@pk),
#{columns[1]}
returns the entry title, and so on. The source for this file can be found under
web/index.xhtml.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:c="http://java.sun.com/jstl/core"
xmlns:fx="http://www.flexive.com/jsf/core">
<head>
<fx:includes/>
</head>
<body>
<h:outputLink value="create.xhtml">Create a new entry</h:outputLink>
<!-- Render available blog postings, as returned by helloWorldBean.blogEntries -->
<!-- The Facelets ui:repeat tag is used to iterate over arrays, lists and JSF datamodels -->
<ui:repeat value="#{helloWorldBean.blogEntries}" var="column">
<h3>
<!-- Entry title. Access the value of each column through the expressi