<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://docs.opentaps.org/docs/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Spark</id>
	<title>Opentaps Wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://docs.opentaps.org/docs/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Spark"/>
	<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=Special:Contributions/Spark"/>
	<updated>2026-05-15T17:05:14Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.32.1</generator>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=Using_Memcache_with_opentaps&amp;diff=6961</id>
		<title>Using Memcache with opentaps</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=Using_Memcache_with_opentaps&amp;diff=6961"/>
		<updated>2010-12-21T01:04:40Z</updated>

		<summary type="html">&lt;p&gt;Spark: /* Start the Memcached Server */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;opentaps can be integrated with the [http://memcached.org/ Memcached] to use memcached in opentaps.  This short tutorial teaches you how to configure the Memcached integration.&lt;br /&gt;
&lt;br /&gt;
== Start the Memcached Server ==&lt;br /&gt;
example: memcached -d -m 256 -u root -l 127.0.0.1 -p 11211 -c 256 -P /tmp/memcached.pid&lt;br /&gt;
&lt;br /&gt;
Also you can choice your options for start memcached&lt;br /&gt;
&lt;br /&gt;
-p       TCP port number to listen on (default: 11211)&lt;br /&gt;
&lt;br /&gt;
-U       UDP port number to listen on (default: 11211, 0 is off)&lt;br /&gt;
&lt;br /&gt;
-s       UNIX socket path to listen on (disables network support)&lt;br /&gt;
&lt;br /&gt;
-a       access mask for UNIX socket, in octal (default: 0700)&lt;br /&gt;
&lt;br /&gt;
-l       interface to listen on (default: INADDR_ANY, all addresses)&lt;br /&gt;
&lt;br /&gt;
-d       run as a daemon&lt;br /&gt;
&lt;br /&gt;
-r       maximize core file limit&lt;br /&gt;
&lt;br /&gt;
-u       assume identity of  (only when run as root)&lt;br /&gt;
&lt;br /&gt;
-m       max memory to use for items in megabytes (default: 64 MB)&lt;br /&gt;
&lt;br /&gt;
-M       return error on memory exhausted (rather than removing items)&lt;br /&gt;
&lt;br /&gt;
-c       max simultaneous connections (default: 1024)&lt;br /&gt;
&lt;br /&gt;
-k       lock down all paged memory.  Note that there is a limit on how much memory you may lock.  Trying to allocate more than that would fail, so be sure you set the limit correctly for the user you started the daemon with (not for -u  user; under sh this is done with 'ulimit -S -l NUM_KB').&lt;br /&gt;
&lt;br /&gt;
-v        verbose (print errors/warnings while in event loop)&lt;br /&gt;
&lt;br /&gt;
-vv       very verbose (also print client commands/reponses)&lt;br /&gt;
&lt;br /&gt;
-vvv      extremely verbose (also print internal state transitions)&lt;br /&gt;
&lt;br /&gt;
-h        print this help and exit&lt;br /&gt;
&lt;br /&gt;
-i        print memcached and libevent license&lt;br /&gt;
&lt;br /&gt;
-P        save PID in , only used with -d option&lt;br /&gt;
&lt;br /&gt;
-f        chunk size growth factor (default: 1.25)&lt;br /&gt;
&lt;br /&gt;
-n        minimum space allocated for key+value+flags (default: 48)&lt;br /&gt;
&lt;br /&gt;
-L        Try to use large memory pages (if available). Increasing the memory page size could reduce the number of TLB misses and improve the performance. In order to get large pages from the OS, memcached will llocate the total item-cache in one large chunk.&lt;br /&gt;
&lt;br /&gt;
-D        Use  as the delimiter between key prefixes and IDs. This is used for per-prefix stats reporting. The default is &amp;quot;:&amp;quot; (colon). If this option is specified, stats collection is turned on automatically; if not, then it may be turned on by sending the &amp;quot;stats detail on&amp;quot; command to the server.&lt;br /&gt;
&lt;br /&gt;
-t        number of threads to use (default: 4)&lt;br /&gt;
&lt;br /&gt;
-R        Maximum number of requests per event, limits the number of requests process for a given connection to prevent starvation (default: 20)&lt;br /&gt;
&lt;br /&gt;
-C        Disable use of CAS&lt;br /&gt;
&lt;br /&gt;
-b        Set the backlog queue limit (default: 1024)&lt;br /&gt;
&lt;br /&gt;
-B        Binding protocol - one of ascii, binary, or auto (default)&lt;br /&gt;
&lt;br /&gt;
-I        Override the size of each slab page. Adjusts max item size (default: 1mb, min: 1k, max: 128m)&lt;br /&gt;
&lt;br /&gt;
== Configuring opentaps ==&lt;br /&gt;
&lt;br /&gt;
Edit the file &amp;lt;tt&amp;gt;framework/base/config/cache.properties&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
* Turn on memcached integration by changing &amp;lt;tt&amp;gt;default.cache.store&amp;lt;/tt&amp;gt; from CacheLineTable to Memcached&lt;br /&gt;
&lt;br /&gt;
Now you are ready.  Restart opentaps, and let's see what it does!&lt;/div&gt;</summary>
		<author><name>Spark</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=Using_Memcache_with_opentaps&amp;diff=6960</id>
		<title>Using Memcache with opentaps</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=Using_Memcache_with_opentaps&amp;diff=6960"/>
		<updated>2010-12-21T01:03:43Z</updated>

		<summary type="html">&lt;p&gt;Spark: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;opentaps can be integrated with the [http://memcached.org/ Memcached] to use memcached in opentaps.  This short tutorial teaches you how to configure the Memcached integration.&lt;br /&gt;
&lt;br /&gt;
== Start the Memcached Server ==&lt;br /&gt;
example: memcached -d -m 256 -u root -l 127.0.0.1 -p 11211 -c 256 -P /tmp/memcached.pid&lt;br /&gt;
&lt;br /&gt;
Also you can choice your options for start memcached&lt;br /&gt;
&lt;br /&gt;
-p       TCP port number to listen on (default: 11211)&lt;br /&gt;
-U       UDP port number to listen on (default: 11211, 0 is off)&lt;br /&gt;
-s       UNIX socket path to listen on (disables network support)&lt;br /&gt;
-a       access mask for UNIX socket, in octal (default: 0700)&lt;br /&gt;
-l       interface to listen on (default: INADDR_ANY, all addresses)&lt;br /&gt;
-d       run as a daemon&lt;br /&gt;
-r       maximize core file limit&lt;br /&gt;
-u       assume identity of  (only when run as root)&lt;br /&gt;
-m       max memory to use for items in megabytes (default: 64 MB)&lt;br /&gt;
-M       return error on memory exhausted (rather than removing items)&lt;br /&gt;
-c       max simultaneous connections (default: 1024)&lt;br /&gt;
-k       lock down all paged memory.  Note that there is a limit on how much memory you may lock.  Trying to allocate more than that would fail, so be sure you set the limit correctly for the user you started the daemon with (not for -u  user; under sh this is done with 'ulimit -S -l NUM_KB').&lt;br /&gt;
-v        verbose (print errors/warnings while in event loop)&lt;br /&gt;
-vv       very verbose (also print client commands/reponses)&lt;br /&gt;
-vvv      extremely verbose (also print internal state transitions)&lt;br /&gt;
-h        print this help and exit&lt;br /&gt;
-i        print memcached and libevent license&lt;br /&gt;
-P        save PID in , only used with -d option&lt;br /&gt;
-f        chunk size growth factor (default: 1.25)&lt;br /&gt;
-n        minimum space allocated for key+value+flags (default: 48)&lt;br /&gt;
-L        Try to use large memory pages (if available). Increasing the memory page size could reduce the number of TLB misses and improve the performance. In order to get large pages from the OS, memcached will llocate the total item-cache in one large chunk.&lt;br /&gt;
-D        Use  as the delimiter between key prefixes and IDs. This is used for per-prefix stats reporting. The default is &amp;quot;:&amp;quot; (colon). If this option is specified, stats collection is turned on automatically; if not, then it may be turned on by sending the &amp;quot;stats detail on&amp;quot; command to the server.&lt;br /&gt;
-t        number of threads to use (default: 4)&lt;br /&gt;
-R        Maximum number of requests per event, limits the number of requests process for a given connection to prevent starvation (default: 20)&lt;br /&gt;
-C        Disable use of CAS&lt;br /&gt;
-b        Set the backlog queue limit (default: 1024)&lt;br /&gt;
-B        Binding protocol - one of ascii, binary, or auto (default)&lt;br /&gt;
-I        Override the size of each slab page. Adjusts max item size (default: 1mb, min: 1k, max: 128m)&lt;br /&gt;
&lt;br /&gt;
== Configuring opentaps ==&lt;br /&gt;
&lt;br /&gt;
Edit the file &amp;lt;tt&amp;gt;framework/base/config/cache.properties&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
* Turn on memcached integration by changing &amp;lt;tt&amp;gt;default.cache.store&amp;lt;/tt&amp;gt; from CacheLineTable to Memcached&lt;br /&gt;
&lt;br /&gt;
Now you are ready.  Restart opentaps, and let's see what it does!&lt;/div&gt;</summary>
		<author><name>Spark</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=Using_Memcache_with_opentaps&amp;diff=6959</id>
		<title>Using Memcache with opentaps</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=Using_Memcache_with_opentaps&amp;diff=6959"/>
		<updated>2010-12-21T01:01:25Z</updated>

		<summary type="html">&lt;p&gt;Spark: /* Start the Memcached Server */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;opentaps can be integrated with the [http://memcached.org/ Memcached] to use memcached in opentaps.  This short tutorial teaches you how to configure the Memcached integration.&lt;br /&gt;
&lt;br /&gt;
== Start the Memcached Server ==&lt;br /&gt;
example: memcached -d -m 256 -u root -l 127.0.0.1 -p 11211 -c 256 -P /tmp/memcached.pid&lt;br /&gt;
&lt;br /&gt;
Also you can choice your options for start memcached&lt;br /&gt;
&lt;br /&gt;
-p       TCP port number to listen on (default: 11211)&lt;br /&gt;
-U       UDP port number to listen on (default: 11211, 0 is off)&lt;br /&gt;
-s       UNIX socket path to listen on (disables network support)&lt;br /&gt;
-a       access mask for UNIX socket, in octal (default: 0700)&lt;br /&gt;
-l       interface to listen on (default: INADDR_ANY, all addresses)&lt;br /&gt;
-d       run as a daemon&lt;br /&gt;
-r       maximize core file limit&lt;br /&gt;
-u       assume identity of  (only when run as root)&lt;br /&gt;
-m       max memory to use for items in megabytes (default: 64 MB)&lt;br /&gt;
-M       return error on memory exhausted (rather than removing items)&lt;br /&gt;
-c       max simultaneous connections (default: 1024)&lt;br /&gt;
-k       lock down all paged memory.  Note that there is a&lt;br /&gt;
          limit on how much memory you may lock.  Trying to&lt;br /&gt;
         allocate more than that would fail, so be sure you&lt;br /&gt;
         set the limit correctly for the user you started&lt;br /&gt;
         the daemon with (not for -u  user;&lt;br /&gt;
         under sh this is done with 'ulimit -S -l NUM_KB').&lt;br /&gt;
-v        verbose (print errors/warnings while in event loop)&lt;br /&gt;
-vv       very verbose (also print client commands/reponses)&lt;br /&gt;
-vvv      extremely verbose (also print internal state transitions)&lt;br /&gt;
-h        print this help and exit&lt;br /&gt;
-i        print memcached and libevent license&lt;br /&gt;
-P         save PID in , only used with -d option&lt;br /&gt;
-f        chunk size growth factor (default: 1.25)&lt;br /&gt;
-n        minimum space allocated for key+value+flags (default: 48)&lt;br /&gt;
-L            Try to use large memory pages (if available). Increasing&lt;br /&gt;
              the memory page size could reduce the number of TLB misses&lt;br /&gt;
              and improve the performance. In order to get large pages&lt;br /&gt;
              from the OS, memcached will allocate the total item-cache&lt;br /&gt;
              in one large chunk.&lt;br /&gt;
-D      Use  as the delimiter between key prefixes and IDs.&lt;br /&gt;
              This is used for per-prefix stats reporting. The default is&lt;br /&gt;
              &amp;quot;:&amp;quot; (colon). If this option is specified, stats collection&lt;br /&gt;
              is turned on automatically; if not, then it may be turned on&lt;br /&gt;
              by sending the &amp;quot;stats detail on&amp;quot; command to the server.&lt;br /&gt;
-t       number of threads to use (default: 4)&lt;br /&gt;
-R            Maximum number of requests per event, limits the number of&lt;br /&gt;
              requests process for a given connection to prevent&lt;br /&gt;
              starvation (default: 20)&lt;br /&gt;
-C            Disable use of CAS&lt;br /&gt;
-b            Set the backlog queue limit (default: 1024)&lt;br /&gt;
-B            Binding protocol - one of ascii, binary, or auto (default)&lt;br /&gt;
-I            Override the size of each slab page. Adjusts max item size (default: 1mb, min: 1k, max: 128m)&lt;br /&gt;
&lt;br /&gt;
== Configuring opentaps ==&lt;br /&gt;
&lt;br /&gt;
Edit the file &amp;lt;tt&amp;gt;framework/base/config/cache.properties&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
* Turn on memcached integration by changing &amp;lt;tt&amp;gt;default.cache.store&amp;lt;/tt&amp;gt; from CacheLineTable to Memcached&lt;br /&gt;
&lt;br /&gt;
Now you are ready.  Restart opentaps, and let's see what it does!&lt;/div&gt;</summary>
		<author><name>Spark</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=Using_Memcache_with_opentaps&amp;diff=6958</id>
		<title>Using Memcache with opentaps</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=Using_Memcache_with_opentaps&amp;diff=6958"/>
		<updated>2010-12-21T01:00:36Z</updated>

		<summary type="html">&lt;p&gt;Spark: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;opentaps can be integrated with the [http://memcached.org/ Memcached] to use memcached in opentaps.  This short tutorial teaches you how to configure the Memcached integration.&lt;br /&gt;
&lt;br /&gt;
== Start the Memcached Server ==&lt;br /&gt;
example: memcached -d -m 256 -u root -l 127.0.0.1 -p 11211 -c 256 -P /tmp/memcached.pid&lt;br /&gt;
&lt;br /&gt;
Also you can choice your options for start memcached&lt;br /&gt;
{{{&lt;br /&gt;
-p       TCP port number to listen on (default: 11211)&lt;br /&gt;
-U       UDP port number to listen on (default: 11211, 0 is off)&lt;br /&gt;
-s       UNIX socket path to listen on (disables network support)&lt;br /&gt;
-a       access mask for UNIX socket, in octal (default: 0700)&lt;br /&gt;
-l       interface to listen on (default: INADDR_ANY, all addresses)&lt;br /&gt;
-d       run as a daemon&lt;br /&gt;
-r       maximize core file limit&lt;br /&gt;
-u       assume identity of  (only when run as root)&lt;br /&gt;
-m       max memory to use for items in megabytes (default: 64 MB)&lt;br /&gt;
-M       return error on memory exhausted (rather than removing items)&lt;br /&gt;
-c       max simultaneous connections (default: 1024)&lt;br /&gt;
-k       lock down all paged memory.  Note that there is a&lt;br /&gt;
          limit on how much memory you may lock.  Trying to&lt;br /&gt;
         allocate more than that would fail, so be sure you&lt;br /&gt;
         set the limit correctly for the user you started&lt;br /&gt;
         the daemon with (not for -u  user;&lt;br /&gt;
         under sh this is done with 'ulimit -S -l NUM_KB').&lt;br /&gt;
-v        verbose (print errors/warnings while in event loop)&lt;br /&gt;
-vv       very verbose (also print client commands/reponses)&lt;br /&gt;
-vvv      extremely verbose (also print internal state transitions)&lt;br /&gt;
-h        print this help and exit&lt;br /&gt;
-i        print memcached and libevent license&lt;br /&gt;
-P         save PID in , only used with -d option&lt;br /&gt;
-f        chunk size growth factor (default: 1.25)&lt;br /&gt;
-n        minimum space allocated for key+value+flags (default: 48)&lt;br /&gt;
-L            Try to use large memory pages (if available). Increasing&lt;br /&gt;
              the memory page size could reduce the number of TLB misses&lt;br /&gt;
              and improve the performance. In order to get large pages&lt;br /&gt;
              from the OS, memcached will allocate the total item-cache&lt;br /&gt;
              in one large chunk.&lt;br /&gt;
-D      Use  as the delimiter between key prefixes and IDs.&lt;br /&gt;
              This is used for per-prefix stats reporting. The default is&lt;br /&gt;
              &amp;quot;:&amp;quot; (colon). If this option is specified, stats collection&lt;br /&gt;
              is turned on automatically; if not, then it may be turned on&lt;br /&gt;
              by sending the &amp;quot;stats detail on&amp;quot; command to the server.&lt;br /&gt;
-t       number of threads to use (default: 4)&lt;br /&gt;
-R            Maximum number of requests per event, limits the number of&lt;br /&gt;
              requests process for a given connection to prevent&lt;br /&gt;
              starvation (default: 20)&lt;br /&gt;
-C            Disable use of CAS&lt;br /&gt;
-b            Set the backlog queue limit (default: 1024)&lt;br /&gt;
-B            Binding protocol - one of ascii, binary, or auto (default)&lt;br /&gt;
-I            Override the size of each slab page. Adjusts max item size&lt;br /&gt;
              (default: 1mb, min: 1k, max: 128m)&lt;br /&gt;
&lt;br /&gt;
}}}&lt;br /&gt;
== Configuring opentaps ==&lt;br /&gt;
&lt;br /&gt;
Edit the file &amp;lt;tt&amp;gt;framework/base/config/cache.properties&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
* Turn on memcached integration by changing &amp;lt;tt&amp;gt;default.cache.store&amp;lt;/tt&amp;gt; from CacheLineTable to Memcached&lt;br /&gt;
&lt;br /&gt;
Now you are ready.  Restart opentaps, and let's see what it does!&lt;/div&gt;</summary>
		<author><name>Spark</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=Using_Memcache_with_opentaps&amp;diff=6957</id>
		<title>Using Memcache with opentaps</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=Using_Memcache_with_opentaps&amp;diff=6957"/>
		<updated>2010-12-21T00:59:51Z</updated>

		<summary type="html">&lt;p&gt;Spark: /* Start the Memcached Server */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;opentaps can be integrated with the [http://memcached.org/ Memcached] to use memcached in opentaps.  This short tutorial teaches you how to configure the Memcached integration.&lt;br /&gt;
&lt;br /&gt;
opentaps can be integrated with the [http://memcached.org/ Memcached] to use memcached in opentaps.  This short tutorial teaches you how to configure the Memcached integration.&lt;br /&gt;
&lt;br /&gt;
opentaps can be integrated with the [http://memcached.org/ Memcached] to use memcached in opentaps.  This short tutorial teaches you how to configure the Memcached integration.&lt;br /&gt;
&lt;br /&gt;
== Start the Memcached Server ==&lt;br /&gt;
example: memcached -d -m 256 -u root -l 127.0.0.1 -p 11211 -c 256 -P /tmp/memcached.pid&lt;br /&gt;
&lt;br /&gt;
Also you can choice your options for start memcached&lt;br /&gt;
{{{&lt;br /&gt;
-p       TCP port number to listen on (default: 11211)&lt;br /&gt;
-U       UDP port number to listen on (default: 11211, 0 is off)&lt;br /&gt;
-s       UNIX socket path to listen on (disables network support)&lt;br /&gt;
-a       access mask for UNIX socket, in octal (default: 0700)&lt;br /&gt;
-l       interface to listen on (default: INADDR_ANY, all addresses)&lt;br /&gt;
-d       run as a daemon&lt;br /&gt;
-r       maximize core file limit&lt;br /&gt;
-u       assume identity of  (only when run as root)&lt;br /&gt;
-m       max memory to use for items in megabytes (default: 64 MB)&lt;br /&gt;
-M       return error on memory exhausted (rather than removing items)&lt;br /&gt;
-c       max simultaneous connections (default: 1024)&lt;br /&gt;
-k       lock down all paged memory.  Note that there is a&lt;br /&gt;
          limit on how much memory you may lock.  Trying to&lt;br /&gt;
         allocate more than that would fail, so be sure you&lt;br /&gt;
         set the limit correctly for the user you started&lt;br /&gt;
         the daemon with (not for -u  user;&lt;br /&gt;
         under sh this is done with 'ulimit -S -l NUM_KB').&lt;br /&gt;
-v        verbose (print errors/warnings while in event loop)&lt;br /&gt;
-vv       very verbose (also print client commands/reponses)&lt;br /&gt;
-vvv      extremely verbose (also print internal state transitions)&lt;br /&gt;
-h        print this help and exit&lt;br /&gt;
-i        print memcached and libevent license&lt;br /&gt;
-P         save PID in , only used with -d option&lt;br /&gt;
-f        chunk size growth factor (default: 1.25)&lt;br /&gt;
-n        minimum space allocated for key+value+flags (default: 48)&lt;br /&gt;
-L            Try to use large memory pages (if available). Increasing&lt;br /&gt;
              the memory page size could reduce the number of TLB misses&lt;br /&gt;
              and improve the performance. In order to get large pages&lt;br /&gt;
              from the OS, memcached will allocate the total item-cache&lt;br /&gt;
              in one large chunk.&lt;br /&gt;
-D      Use  as the delimiter between key prefixes and IDs.&lt;br /&gt;
              This is used for per-prefix stats reporting. The default is&lt;br /&gt;
              &amp;quot;:&amp;quot; (colon). If this option is specified, stats collection&lt;br /&gt;
              is turned on automatically; if not, then it may be turned on&lt;br /&gt;
              by sending the &amp;quot;stats detail on&amp;quot; command to the server.&lt;br /&gt;
-t       number of threads to use (default: 4)&lt;br /&gt;
-R            Maximum number of requests per event, limits the number of&lt;br /&gt;
              requests process for a given connection to prevent&lt;br /&gt;
              starvation (default: 20)&lt;br /&gt;
-C            Disable use of CAS&lt;br /&gt;
-b            Set the backlog queue limit (default: 1024)&lt;br /&gt;
-B            Binding protocol - one of ascii, binary, or auto (default)&lt;br /&gt;
-I            Override the size of each slab page. Adjusts max item size&lt;br /&gt;
              (default: 1mb, min: 1k, max: 128m)&lt;br /&gt;
&lt;br /&gt;
}}}&lt;br /&gt;
== Configuring opentaps ==&lt;br /&gt;
&lt;br /&gt;
Edit the file &amp;lt;tt&amp;gt;framework/base/config/cache.properties&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
* Turn on memcached integration by changing &amp;lt;tt&amp;gt;default.cache.store&amp;lt;/tt&amp;gt; from CacheLineTable to Memcached&lt;br /&gt;
&lt;br /&gt;
Now you are ready.  Restart opentaps, and let's see what it does!&lt;br /&gt;
&lt;br /&gt;
== Configuring opentaps ==&lt;br /&gt;
&lt;br /&gt;
Edit the file &amp;lt;tt&amp;gt;framework/base/config/cache.properties&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
* Turn on memcached integration by changing &amp;lt;tt&amp;gt;default.cache.store&amp;lt;/tt&amp;gt; from CacheLineTable to Memcached&lt;br /&gt;
&lt;br /&gt;
Now you are ready.  Restart opentaps, and let's see what it does!&lt;br /&gt;
&lt;br /&gt;
== Configuring opentaps ==&lt;br /&gt;
&lt;br /&gt;
Edit the file &amp;lt;tt&amp;gt;framework/base/config/cache.properties&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
* Turn on memcached integration by changing &amp;lt;tt&amp;gt;default.cache.store&amp;lt;/tt&amp;gt; from CacheLineTable to Memcached&lt;br /&gt;
&lt;br /&gt;
Now you are ready.  Restart opentaps, and let's see what it does!&lt;/div&gt;</summary>
		<author><name>Spark</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=Using_Memcache_with_opentaps&amp;diff=6956</id>
		<title>Using Memcache with opentaps</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=Using_Memcache_with_opentaps&amp;diff=6956"/>
		<updated>2010-12-21T00:58:52Z</updated>

		<summary type="html">&lt;p&gt;Spark: /* Start the Memcached Server */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;opentaps can be integrated with the [http://memcached.org/ Memcached] to use memcached in opentaps.  This short tutorial teaches you how to configure the Memcached integration.&lt;br /&gt;
&lt;br /&gt;
opentaps can be integrated with the [http://memcached.org/ Memcached] to use memcached in opentaps.  This short tutorial teaches you how to configure the Memcached integration.&lt;br /&gt;
&lt;br /&gt;
== Start the Memcached Server ==&lt;br /&gt;
example: memcached -d -m 256 -u root -l 127.0.0.1 -p 11211 -c 256 -P /tmp/memcached.pid&lt;br /&gt;
&lt;br /&gt;
Also you can choice your options for start memcached&lt;br /&gt;
&amp;lt;nowiki&amp;gt;-p       TCP port number to listen on (default: 11211)&lt;br /&gt;
-U       UDP port number to listen on (default: 11211, 0 is off)&lt;br /&gt;
-s       UNIX socket path to listen on (disables network support)&lt;br /&gt;
-a       access mask for UNIX socket, in octal (default: 0700)&lt;br /&gt;
-l       interface to listen on (default: INADDR_ANY, all addresses)&lt;br /&gt;
-d       run as a daemon&lt;br /&gt;
-r       maximize core file limit&lt;br /&gt;
-u       assume identity of  (only when run as root)&lt;br /&gt;
-m       max memory to use for items in megabytes (default: 64 MB)&lt;br /&gt;
-M       return error on memory exhausted (rather than removing items)&lt;br /&gt;
-c       max simultaneous connections (default: 1024)&lt;br /&gt;
-k       lock down all paged memory.  Note that there is a&lt;br /&gt;
          limit on how much memory you may lock.  Trying to&lt;br /&gt;
         allocate more than that would fail, so be sure you&lt;br /&gt;
         set the limit correctly for the user you started&lt;br /&gt;
         the daemon with (not for -u  user;&lt;br /&gt;
         under sh this is done with 'ulimit -S -l NUM_KB').&lt;br /&gt;
-v        verbose (print errors/warnings while in event loop)&lt;br /&gt;
-vv       very verbose (also print client commands/reponses)&lt;br /&gt;
-vvv      extremely verbose (also print internal state transitions)&lt;br /&gt;
-h        print this help and exit&lt;br /&gt;
-i        print memcached and libevent license&lt;br /&gt;
-P         save PID in , only used with -d option&lt;br /&gt;
-f        chunk size growth factor (default: 1.25)&lt;br /&gt;
-n        minimum space allocated for key+value+flags (default: 48)&lt;br /&gt;
-L            Try to use large memory pages (if available). Increasing&lt;br /&gt;
              the memory page size could reduce the number of TLB misses&lt;br /&gt;
              and improve the performance. In order to get large pages&lt;br /&gt;
              from the OS, memcached will allocate the total item-cache&lt;br /&gt;
              in one large chunk.&lt;br /&gt;
-D      Use  as the delimiter between key prefixes and IDs.&lt;br /&gt;
              This is used for per-prefix stats reporting. The default is&lt;br /&gt;
              &amp;quot;:&amp;quot; (colon). If this option is specified, stats collection&lt;br /&gt;
              is turned on automatically; if not, then it may be turned on&lt;br /&gt;
              by sending the &amp;quot;stats detail on&amp;quot; command to the server.&lt;br /&gt;
-t       number of threads to use (default: 4)&lt;br /&gt;
-R            Maximum number of requests per event, limits the number of&lt;br /&gt;
              requests process for a given connection to prevent&lt;br /&gt;
              starvation (default: 20)&lt;br /&gt;
-C            Disable use of CAS&lt;br /&gt;
-b            Set the backlog queue limit (default: 1024)&lt;br /&gt;
-B            Binding protocol - one of ascii, binary, or auto (default)&lt;br /&gt;
-I            Override the size of each slab page. Adjusts max item size&lt;br /&gt;
              (default: 1mb, min: 1k, max: 128m)&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Configuring opentaps ==&lt;br /&gt;
&lt;br /&gt;
Edit the file &amp;lt;tt&amp;gt;framework/base/config/cache.properties&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
* Turn on memcached integration by changing &amp;lt;tt&amp;gt;default.cache.store&amp;lt;/tt&amp;gt; from CacheLineTable to Memcached&lt;br /&gt;
&lt;br /&gt;
Now you are ready.  Restart opentaps, and let's see what it does!&lt;br /&gt;
&lt;br /&gt;
== Configuring opentaps ==&lt;br /&gt;
&lt;br /&gt;
Edit the file &amp;lt;tt&amp;gt;framework/base/config/cache.properties&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
* Turn on memcached integration by changing &amp;lt;tt&amp;gt;default.cache.store&amp;lt;/tt&amp;gt; from CacheLineTable to Memcached&lt;br /&gt;
&lt;br /&gt;
Now you are ready.  Restart opentaps, and let's see what it does!&lt;/div&gt;</summary>
		<author><name>Spark</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=Using_Memcache_with_opentaps&amp;diff=6954</id>
		<title>Using Memcache with opentaps</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=Using_Memcache_with_opentaps&amp;diff=6954"/>
		<updated>2010-12-21T00:57:48Z</updated>

		<summary type="html">&lt;p&gt;Spark: New page: opentaps can be integrated with the [http://memcached.org/ Memcached] to use memcached in opentaps.  This short tutorial teaches you how to configure the Memcached integration.  == Start t...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;opentaps can be integrated with the [http://memcached.org/ Memcached] to use memcached in opentaps.  This short tutorial teaches you how to configure the Memcached integration.&lt;br /&gt;
&lt;br /&gt;
== Start the Memcached Server ==&lt;br /&gt;
example: memcached -d -m 256 -u root -l 127.0.0.1 -p 11211 -c 256 -P /tmp/memcached.pid&lt;br /&gt;
&lt;br /&gt;
Also you can choice your options for start memcached&lt;br /&gt;
-p       TCP port number to listen on (default: 11211)&lt;br /&gt;
-U       UDP port number to listen on (default: 11211, 0 is off)&lt;br /&gt;
-s       UNIX socket path to listen on (disables network support)&lt;br /&gt;
-a       access mask for UNIX socket, in octal (default: 0700)&lt;br /&gt;
-l       interface to listen on (default: INADDR_ANY, all addresses)&lt;br /&gt;
-d       run as a daemon&lt;br /&gt;
-r       maximize core file limit&lt;br /&gt;
-u       assume identity of  (only when run as root)&lt;br /&gt;
-m       max memory to use for items in megabytes (default: 64 MB)&lt;br /&gt;
-M       return error on memory exhausted (rather than removing items)&lt;br /&gt;
-c       max simultaneous connections (default: 1024)&lt;br /&gt;
-k       lock down all paged memory.  Note that there is a&lt;br /&gt;
          limit on how much memory you may lock.  Trying to&lt;br /&gt;
         allocate more than that would fail, so be sure you&lt;br /&gt;
         set the limit correctly for the user you started&lt;br /&gt;
         the daemon with (not for -u  user;&lt;br /&gt;
         under sh this is done with 'ulimit -S -l NUM_KB').&lt;br /&gt;
-v        verbose (print errors/warnings while in event loop)&lt;br /&gt;
-vv       very verbose (also print client commands/reponses)&lt;br /&gt;
-vvv      extremely verbose (also print internal state transitions)&lt;br /&gt;
-h        print this help and exit&lt;br /&gt;
-i        print memcached and libevent license&lt;br /&gt;
-P         save PID in , only used with -d option&lt;br /&gt;
-f        chunk size growth factor (default: 1.25)&lt;br /&gt;
-n        minimum space allocated for key+value+flags (default: 48)&lt;br /&gt;
-L            Try to use large memory pages (if available). Increasing&lt;br /&gt;
              the memory page size could reduce the number of TLB misses&lt;br /&gt;
              and improve the performance. In order to get large pages&lt;br /&gt;
              from the OS, memcached will allocate the total item-cache&lt;br /&gt;
              in one large chunk.&lt;br /&gt;
-D      Use  as the delimiter between key prefixes and IDs.&lt;br /&gt;
              This is used for per-prefix stats reporting. The default is&lt;br /&gt;
              &amp;quot;:&amp;quot; (colon). If this option is specified, stats collection&lt;br /&gt;
              is turned on automatically; if not, then it may be turned on&lt;br /&gt;
              by sending the &amp;quot;stats detail on&amp;quot; command to the server.&lt;br /&gt;
-t       number of threads to use (default: 4)&lt;br /&gt;
-R            Maximum number of requests per event, limits the number of&lt;br /&gt;
              requests process for a given connection to prevent&lt;br /&gt;
              starvation (default: 20)&lt;br /&gt;
-C            Disable use of CAS&lt;br /&gt;
-b            Set the backlog queue limit (default: 1024)&lt;br /&gt;
-B            Binding protocol - one of ascii, binary, or auto (default)&lt;br /&gt;
-I            Override the size of each slab page. Adjusts max item size&lt;br /&gt;
              (default: 1mb, min: 1k, max: 128m)&lt;br /&gt;
&lt;br /&gt;
== Configuring opentaps ==&lt;br /&gt;
&lt;br /&gt;
Edit the file &amp;lt;tt&amp;gt;framework/base/config/cache.properties&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
* Turn on memcached integration by changing &amp;lt;tt&amp;gt;default.cache.store&amp;lt;/tt&amp;gt; from CacheLineTable to Memcached&lt;br /&gt;
&lt;br /&gt;
Now you are ready.  Restart opentaps, and let's see what it does!&lt;/div&gt;</summary>
		<author><name>Spark</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=Using_Memcache_with_opentaps&amp;diff=6955</id>
		<title>Using Memcache with opentaps</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=Using_Memcache_with_opentaps&amp;diff=6955"/>
		<updated>2010-12-21T00:57:48Z</updated>

		<summary type="html">&lt;p&gt;Spark: Protected &amp;quot;Using Memcache with opentaps&amp;quot;: Sysop page [edit=sysop:move=sysop]&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;opentaps can be integrated with the [http://memcached.org/ Memcached] to use memcached in opentaps.  This short tutorial teaches you how to configure the Memcached integration.&lt;br /&gt;
&lt;br /&gt;
== Start the Memcached Server ==&lt;br /&gt;
example: memcached -d -m 256 -u root -l 127.0.0.1 -p 11211 -c 256 -P /tmp/memcached.pid&lt;br /&gt;
&lt;br /&gt;
Also you can choice your options for start memcached&lt;br /&gt;
-p       TCP port number to listen on (default: 11211)&lt;br /&gt;
-U       UDP port number to listen on (default: 11211, 0 is off)&lt;br /&gt;
-s       UNIX socket path to listen on (disables network support)&lt;br /&gt;
-a       access mask for UNIX socket, in octal (default: 0700)&lt;br /&gt;
-l       interface to listen on (default: INADDR_ANY, all addresses)&lt;br /&gt;
-d       run as a daemon&lt;br /&gt;
-r       maximize core file limit&lt;br /&gt;
-u       assume identity of  (only when run as root)&lt;br /&gt;
-m       max memory to use for items in megabytes (default: 64 MB)&lt;br /&gt;
-M       return error on memory exhausted (rather than removing items)&lt;br /&gt;
-c       max simultaneous connections (default: 1024)&lt;br /&gt;
-k       lock down all paged memory.  Note that there is a&lt;br /&gt;
          limit on how much memory you may lock.  Trying to&lt;br /&gt;
         allocate more than that would fail, so be sure you&lt;br /&gt;
         set the limit correctly for the user you started&lt;br /&gt;
         the daemon with (not for -u  user;&lt;br /&gt;
         under sh this is done with 'ulimit -S -l NUM_KB').&lt;br /&gt;
-v        verbose (print errors/warnings while in event loop)&lt;br /&gt;
-vv       very verbose (also print client commands/reponses)&lt;br /&gt;
-vvv      extremely verbose (also print internal state transitions)&lt;br /&gt;
-h        print this help and exit&lt;br /&gt;
-i        print memcached and libevent license&lt;br /&gt;
-P         save PID in , only used with -d option&lt;br /&gt;
-f        chunk size growth factor (default: 1.25)&lt;br /&gt;
-n        minimum space allocated for key+value+flags (default: 48)&lt;br /&gt;
-L            Try to use large memory pages (if available). Increasing&lt;br /&gt;
              the memory page size could reduce the number of TLB misses&lt;br /&gt;
              and improve the performance. In order to get large pages&lt;br /&gt;
              from the OS, memcached will allocate the total item-cache&lt;br /&gt;
              in one large chunk.&lt;br /&gt;
-D      Use  as the delimiter between key prefixes and IDs.&lt;br /&gt;
              This is used for per-prefix stats reporting. The default is&lt;br /&gt;
              &amp;quot;:&amp;quot; (colon). If this option is specified, stats collection&lt;br /&gt;
              is turned on automatically; if not, then it may be turned on&lt;br /&gt;
              by sending the &amp;quot;stats detail on&amp;quot; command to the server.&lt;br /&gt;
-t       number of threads to use (default: 4)&lt;br /&gt;
-R            Maximum number of requests per event, limits the number of&lt;br /&gt;
              requests process for a given connection to prevent&lt;br /&gt;
              starvation (default: 20)&lt;br /&gt;
-C            Disable use of CAS&lt;br /&gt;
-b            Set the backlog queue limit (default: 1024)&lt;br /&gt;
-B            Binding protocol - one of ascii, binary, or auto (default)&lt;br /&gt;
-I            Override the size of each slab page. Adjusts max item size&lt;br /&gt;
              (default: 1mb, min: 1k, max: 128m)&lt;br /&gt;
&lt;br /&gt;
== Configuring opentaps ==&lt;br /&gt;
&lt;br /&gt;
Edit the file &amp;lt;tt&amp;gt;framework/base/config/cache.properties&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
* Turn on memcached integration by changing &amp;lt;tt&amp;gt;default.cache.store&amp;lt;/tt&amp;gt; from CacheLineTable to Memcached&lt;br /&gt;
&lt;br /&gt;
Now you are ready.  Restart opentaps, and let's see what it does!&lt;/div&gt;</summary>
		<author><name>Spark</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=General_Installation_of_Opentaps&amp;diff=5775</id>
		<title>General Installation of Opentaps</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=General_Installation_of_Opentaps&amp;diff=5775"/>
		<updated>2010-04-14T08:37:28Z</updated>

		<summary type="html">&lt;p&gt;Spark: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
Installing opentaps ERP + CRM is fairly easy, and you do not need root user privileges.  These instructions will help you get started running opentaps ERP + CRM on both Unix/Linux and Windows operating systems.&lt;br /&gt;
&lt;br /&gt;
==Prerequisites==&lt;br /&gt;
&lt;br /&gt;
The first step is to make sure that you have the correct Java Virtual Machine installed.  For opentaps 0.8.x and 0.9.x, you must use Java 1.4.2.  For opentaps 1.0.x, you must use Java 5.  opentaps 1.4 works with both Java 5 or Java 6, though it is pre-compiled with Java 6.  In both cases, &amp;lt;b&amp;gt;you must use the Sun Java SDK&amp;lt;/b&amp;gt;, not GNU gcj which may have been supplied with Fedora Core or Ubuntu or the Java Runtime JRE supplied with Windows.&lt;br /&gt;
&lt;br /&gt;
To determine what version of Java you are using, type the following command:&lt;br /&gt;
&lt;br /&gt;
 $ java -version&lt;br /&gt;
&lt;br /&gt;
For opentaps 0.8.x and opentaps 0.9.x, you must see something like this:&lt;br /&gt;
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2_xxxx)&lt;br /&gt;
&lt;br /&gt;
For opentaps 1.0.x, you must see something like the following:&lt;br /&gt;
Java(TM) 2 RuntimeEnvironment, Standard Edition (build 1.5.xxxx)&lt;br /&gt;
&lt;br /&gt;
You must not see anything like&lt;br /&gt;
gij (GNU libgcj) version 4.0.1 20050727 (Red Hat 4.0.1-5)&lt;br /&gt;
&lt;br /&gt;
or anything that says &amp;quot;JRE&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;If you do not see the correct JVM, you must go download it from Sun.&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Next, you should unzip the opentaps ERP + CRM .zip file you have just downloaded and go into the directory where it is unzipped:&lt;br /&gt;
&lt;br /&gt;
 $ cd opentaps&lt;br /&gt;
&lt;br /&gt;
==Starting on Unix/Linux==&lt;br /&gt;
&lt;br /&gt;
If you are using a Unix/Linux system, you should make the startup scripts executable:&lt;br /&gt;
&lt;br /&gt;
 $ chmod u+x startofbiz.sh&lt;br /&gt;
 $ chmod u+x stopofbiz.sh&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;IMPORTANT:&amp;lt;/b&amp;gt;  If your system already has gcj and you just installed new Sun JVM, you must tell opentaps ERP + CRM to use the Sun JVM instead of the GCJ JVM in /bin/java by specifying where the JVM is:&lt;br /&gt;
&lt;br /&gt;
 $ export JAVA_HOME=/usr/java/j2sdk_xxxx/&lt;br /&gt;
&lt;br /&gt;
(or whichever directory your Sun JVM was installed.)  You can even put this directive into startofbiz.sh and stopofbiz.sh&lt;br /&gt;
&lt;br /&gt;
To start the opentaps server,&lt;br /&gt;
&lt;br /&gt;
 $ ./startofbiz.sh&lt;br /&gt;
&lt;br /&gt;
The server is started as a background process, and the logs are piped to a file called &amp;quot;console.log&amp;quot; in the logs/ sub-directory for opentaps 0.8.x and 0.9.x and runtime/logs sub-directory for opentaps 1.0.x  To see the logs,&lt;br /&gt;
&lt;br /&gt;
 $ tail -f runtime/logs/console.log&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
 $ tail -f logs/console.log&lt;br /&gt;
&lt;br /&gt;
To stop the opentaps ERP + CRM server,&lt;br /&gt;
&lt;br /&gt;
 $ ./stopofbiz.sh&lt;br /&gt;
&lt;br /&gt;
To start the Point Of Sales terminal, instead of using startofbiz.sh and stopofbiz.sh, use&lt;br /&gt;
&lt;br /&gt;
 $ java -jar ofbiz.jar -pos&lt;br /&gt;
&lt;br /&gt;
==Starting on Windows==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;IMPORTANT:&amp;lt;/b&amp;gt;  If you are using Windows, you may run into problems with having paths with directories that have spaces in the name, such as &amp;quot;C:\Documents and Settings&amp;quot;.  You can avoid these problems by unzipping in your C:\ directory.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;IMPORTANT:&amp;lt;/b&amp;gt;  opentaps ERP + CRM runs as a server on your computer and needs to access a number of ports.  If you are having start up problems, try re-configuring or temporarily disabling your firewall.&lt;br /&gt;
&lt;br /&gt;
If you are using Windows, call up a command line terminal (Windows &amp;gt; Run Program &amp;gt; &amp;quot;cmd&amp;quot;)  From the terminal, go to your opentaps ERP + CRM directory&lt;br /&gt;
&lt;br /&gt;
 C:&amp;gt; cd c:\opentaps&lt;br /&gt;
&lt;br /&gt;
You may need set a variable called JAVA_HOME first to tell Windows where Java is located:&lt;br /&gt;
&lt;br /&gt;
 C:&amp;gt; set JAVA_HOME=c:\java_x.x.x&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Or which ever directory Java was installed in.&lt;br /&gt;
&lt;br /&gt;
Now run the batch file to start the opentaps ERP + CRM server:&lt;br /&gt;
&lt;br /&gt;
 C:\opentaps&amp;gt; startofbiz.bat&lt;br /&gt;
&lt;br /&gt;
The server will run in the terminal.  Alternatively, you can create a Windows shortcut to the startofbiz.bat and place it on your desktop.&lt;br /&gt;
&lt;br /&gt;
If you want to start the Point Of Sales system, use this command instead:&lt;br /&gt;
&lt;br /&gt;
 C:\opentaps&amp;gt; java -jar ofbiz.jar -pos&lt;br /&gt;
&lt;br /&gt;
==Mac OS X Users==&lt;br /&gt;
A recent update to OS X 10.4.6 has made Java 5 the default JVM.  To use Java 1.4.2 for opentaps 0.8.x or 0.9.x, set your JAVA_HOME to the correct path:&lt;br /&gt;
&lt;br /&gt;
 $ export JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Versions/1.4.2/Home&lt;br /&gt;
&lt;br /&gt;
You can also use /Applications/Utilities/Java/J2SE 5.0/Java Preferences.app to set your preferred Java environment.&lt;br /&gt;
&lt;br /&gt;
==Accessing the Server==&lt;br /&gt;
&lt;br /&gt;
To access the opentaps ERP + CRM server, open any browser and type in the following:&lt;br /&gt;
&lt;br /&gt;
* For version 1.4: &amp;lt;tt&amp;gt;http://localhost:8080/opentaps&amp;lt;/tt&amp;gt;&lt;br /&gt;
* For version 1.0 and earlier: &amp;lt;tt&amp;gt;http://localhost:8080/&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
With opentaps 1.4, you will see a greeting page which prompts you to login.  The applications you can access are displayed as icons:&lt;br /&gt;
&lt;br /&gt;
[[Image:Opentaps home.png]]&lt;br /&gt;
&lt;br /&gt;
In earlier versions of opentaps, you will see a menu in your browser which shows you all the applications available.&lt;br /&gt;
&lt;br /&gt;
[[Image:Opentaps startup.png]]&lt;br /&gt;
&lt;br /&gt;
You can now click on the application you wish to access.  If you are using an older version of Sequoia ERP, you will need to access the applications directly using:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;http://locahost:8080/crmsfa/control/main&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
for CRMSFA or&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;http://localhost:8080/ecommerce/control/main&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
for the online store.&lt;br /&gt;
&lt;br /&gt;
==Signing In==&lt;br /&gt;
&lt;br /&gt;
For the back end web applications, use the username &amp;quot;admin&amp;quot; and the password &amp;quot;ofbiz&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
For the ecommerce online store application, use username &amp;quot;DemoCustomer&amp;quot; and password &amp;quot;ofbiz&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
For the Point Of Sales application, use username &amp;quot;1&amp;quot; and password &amp;quot;1&amp;quot; for a manager and username &amp;quot;2&amp;quot; and password &amp;quot;2&amp;quot; for a cashier.&lt;br /&gt;
&lt;br /&gt;
==Oh No!  It Didn't Work!  What Do I Do?==&lt;br /&gt;
&lt;br /&gt;
Look in your runtime/logs/console.log and runtime/logs/ofbiz.log (or simply logs/console.log or logs/ofbiz.log files for opentaps 0.8.x and 0.9.x) and see what error messages are recorded.  Check that you are using the correct version, that your database connection is successful, that there were no port conflicts, and that none of the required ports are blocked.&lt;br /&gt;
&lt;br /&gt;
Here are some specific issues and possible solutions:&lt;br /&gt;
&lt;br /&gt;
===Bad version number in .class file===&lt;br /&gt;
&lt;br /&gt;
This means that the Java virtual machine on your computer is different than the one that was used to compile opentaps. For example, your computer might have Java 5, and you may have downloaded opentaps 1.4, which was pre-compiled with Java 6.&lt;br /&gt;
&lt;br /&gt;
To fix this, either download and install the same Java virtual machine SDK as was used to compile the copy of opentaps you obtained, or try to recompile opentaps using your computer's Java virtual machine with &lt;br /&gt;
&lt;br /&gt;
 ant&lt;br /&gt;
or&lt;br /&gt;
 ./ant&lt;br /&gt;
&lt;br /&gt;
===Cannot create the Java virtual machine===&lt;br /&gt;
&lt;br /&gt;
Your computer may not have the memory available to satisfy opentaps.   Check the [[Hardware Guidelines for Opentaps]] and [[Recommended Memory Settings]].&lt;br /&gt;
&lt;br /&gt;
===PermGen Space and other Memory Errors===&lt;br /&gt;
&lt;br /&gt;
See [[Recommended Memory Settings]] for possible changes to your start scripts.&lt;br /&gt;
&lt;br /&gt;
===Build Aspect class Errors===&lt;br /&gt;
&lt;br /&gt;
If you got &amp;quot;Unable to rename old file&amp;quot; build error, you can try to use follow line to replace the weave target on hot-deploy/opentaps-common/build-aspects.xml.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    &amp;lt;!-- ================================================================== --&amp;gt;&lt;br /&gt;
    &amp;lt;!-- Weave advice into target jars                                      --&amp;gt;&lt;br /&gt;
    &amp;lt;!-- ================================================================== --&amp;gt;&lt;br /&gt;
    &amp;lt;target name=&amp;quot;weave&amp;quot; depends=&amp;quot;detect-dependencies&amp;quot; if=&amp;quot;processRequired&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;echo message=&amp;quot;[build] =========== Start Building Aspect (Weave) =============&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;java classname=&amp;quot;org.codehaus.aspectwerkz.compiler.AspectWerkzC&amp;quot; fork=&amp;quot;true&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;jvmarg value=&amp;quot;-Daspectwerkz.definition.file=${aopConfig}&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;jvmarg value=&amp;quot;-Daspectwerkz.transform.filter=no&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;!-- &amp;lt;jvmarg value=&amp;quot;-Daspectwerkz.transform.verbose=true&amp;quot;/&amp;gt; --&amp;gt;&lt;br /&gt;
        &amp;lt;!-- &amp;lt;jvmarg value=&amp;quot;-Daspectwerkz.transform.details=true&amp;quot;/&amp;gt; --&amp;gt;&lt;br /&gt;
        &amp;lt;arg value=&amp;quot;-verify&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;classpath refid=&amp;quot;local.class.path&amp;quot; /&amp;gt;&lt;br /&gt;
        &amp;lt;classpath&amp;gt;&lt;br /&gt;
          &amp;lt;pathelement path=&amp;quot;${build.dir}/classes/common&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;/classpath&amp;gt;&lt;br /&gt;
        &amp;lt;!-- below is the jars to post-process --&amp;gt;&lt;br /&gt;
        &amp;lt;arg value=&amp;quot;${ofbiz.dir}/framework/entity/build/lib/ofbiz-entity.jar&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/java&amp;gt;&lt;br /&gt;
      &amp;lt;java classname=&amp;quot;org.codehaus.aspectwerkz.compiler.AspectWerkzC&amp;quot; fork=&amp;quot;true&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;jvmarg value=&amp;quot;-Daspectwerkz.definition.file=${aopConfig}&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;jvmarg value=&amp;quot;-Daspectwerkz.transform.filter=no&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;!-- &amp;lt;jvmarg value=&amp;quot;-Daspectwerkz.transform.verbose=true&amp;quot;/&amp;gt; --&amp;gt;&lt;br /&gt;
        &amp;lt;!-- &amp;lt;jvmarg value=&amp;quot;-Daspectwerkz.transform.details=true&amp;quot;/&amp;gt; --&amp;gt;&lt;br /&gt;
        &amp;lt;arg value=&amp;quot;-verify&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;classpath refid=&amp;quot;local.class.path&amp;quot; /&amp;gt;&lt;br /&gt;
        &amp;lt;classpath&amp;gt;&lt;br /&gt;
          &amp;lt;pathelement path=&amp;quot;${build.dir}/classes/common&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;/classpath&amp;gt;&lt;br /&gt;
        &amp;lt;!-- below is the jars to post-process, if these jar not effect each other you can put them in same pos, else please seperate them into another task --&amp;gt;&lt;br /&gt;
        &amp;lt;arg value=&amp;quot;${ofbiz.dir}/framework/common/build/lib/ofbiz-common.jar&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/java&amp;gt;&lt;br /&gt;
      &amp;lt;java classname=&amp;quot;org.codehaus.aspectwerkz.compiler.AspectWerkzC&amp;quot; fork=&amp;quot;true&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;jvmarg value=&amp;quot;-Daspectwerkz.definition.file=${aopConfig}&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;jvmarg value=&amp;quot;-Daspectwerkz.transform.filter=no&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;!-- &amp;lt;jvmarg value=&amp;quot;-Daspectwerkz.transform.verbose=true&amp;quot;/&amp;gt; --&amp;gt;&lt;br /&gt;
        &amp;lt;!-- &amp;lt;jvmarg value=&amp;quot;-Daspectwerkz.transform.details=true&amp;quot;/&amp;gt; --&amp;gt;&lt;br /&gt;
        &amp;lt;arg value=&amp;quot;-verify&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;classpath refid=&amp;quot;local.class.path&amp;quot; /&amp;gt;&lt;br /&gt;
        &amp;lt;classpath&amp;gt;&lt;br /&gt;
          &amp;lt;pathelement path=&amp;quot;${build.dir}/classes/common&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;/classpath&amp;gt;&lt;br /&gt;
        &amp;lt;!-- below is the jars to post-process --&amp;gt;&lt;br /&gt;
        &amp;lt;arg value=&amp;quot;${ofbiz.dir}/applications/order/build/lib/ofbiz-order.jar&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/java&amp;gt;&lt;br /&gt;
      &amp;lt;jar jarfile=&amp;quot;${lib.dir}/${name}.jar&amp;quot; update=&amp;quot;true&amp;quot; basedir=&amp;quot;${build.dir}/classes/common&amp;quot; includes=&amp;quot;org/opentaps/aspect/secas/**&amp;quot; /&amp;gt;&lt;br /&gt;
        &amp;lt;!-- put aop.xml into target jar META-INF dir --&amp;gt;&lt;br /&gt;
         &amp;lt;mkdir dir=&amp;quot;${build.dir}/classes/META-INF&amp;quot; /&amp;gt;&lt;br /&gt;
         &amp;lt;copy file=&amp;quot;${aopConfig}&amp;quot; tofile=&amp;quot;${build.dir}/classes/META-INF/aop.xml&amp;quot; overwrite=&amp;quot;true&amp;quot;/&amp;gt;&lt;br /&gt;
       	&amp;lt;!-- create new jar with aop.xml, then copy it to orign location, using these for avoid unable rename error on windows 64bit system--&amp;gt;&lt;br /&gt;
           &amp;lt;zip destfile=&amp;quot;${lib.dir}/ofbiz-entity.jar&amp;quot;&amp;gt;&lt;br /&gt;
         	  &amp;lt;zipfileset src=&amp;quot;${ofbiz.dir}/framework/entity/build/lib/ofbiz-entity.jar&amp;quot;/&amp;gt;&lt;br /&gt;
         	  &amp;lt;fileset dir=&amp;quot;${build.dir}/classes/&amp;quot;&amp;gt;&lt;br /&gt;
         	    &amp;lt;include name=&amp;quot;META-INF/aop.xml&amp;quot;/&amp;gt;&lt;br /&gt;
         	  &amp;lt;/fileset&amp;gt;&lt;br /&gt;
           &amp;lt;/zip&amp;gt;&lt;br /&gt;
       	&amp;lt;delete file=&amp;quot;${ofbiz.dir}/framework/entity/build/lib/ofbiz-entity.jar&amp;quot; failonerror=&amp;quot;false&amp;quot;/&amp;gt;&lt;br /&gt;
           &amp;lt;move file=&amp;quot;${lib.dir}/ofbiz-entity.jar&amp;quot; tofile=&amp;quot;${ofbiz.dir}/framework/entity/build/lib/ofbiz-entity.jar&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
           &amp;lt;zip destfile=&amp;quot;${lib.dir}/ofbiz-common.jar&amp;quot;&amp;gt;&lt;br /&gt;
         	  &amp;lt;zipfileset src=&amp;quot;${ofbiz.dir}/framework/common/build/lib/ofbiz-common.jar&amp;quot;/&amp;gt;&lt;br /&gt;
         	  &amp;lt;fileset dir=&amp;quot;${build.dir}/classes/&amp;quot;&amp;gt;&lt;br /&gt;
         	    &amp;lt;include name=&amp;quot;META-INF/aop.xml&amp;quot;/&amp;gt;&lt;br /&gt;
         	  &amp;lt;/fileset&amp;gt;&lt;br /&gt;
           &amp;lt;/zip&amp;gt;&lt;br /&gt;
       	&amp;lt;delete file=&amp;quot;${ofbiz.dir}/framework/common/build/lib/ofbiz-common.jar&amp;quot; failonerror=&amp;quot;false&amp;quot;/&amp;gt;&lt;br /&gt;
           &amp;lt;move file=&amp;quot;${lib.dir}/ofbiz-common.jar&amp;quot; tofile=&amp;quot;${ofbiz.dir}/framework/common/build/lib/ofbiz-common.jar&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
       	&amp;lt;zip destfile=&amp;quot;${lib.dir}/ofbiz-order.jar&amp;quot;&amp;gt;&lt;br /&gt;
         	  &amp;lt;zipfileset src=&amp;quot;${ofbiz.dir}/applications/order/build/lib/ofbiz-order.jar&amp;quot;/&amp;gt;&lt;br /&gt;
         	  &amp;lt;fileset dir=&amp;quot;${build.dir}/classes/&amp;quot;&amp;gt;&lt;br /&gt;
         	    &amp;lt;include name=&amp;quot;META-INF/aop.xml&amp;quot;/&amp;gt;&lt;br /&gt;
         	  &amp;lt;/fileset&amp;gt;&lt;br /&gt;
           &amp;lt;/zip&amp;gt;&lt;br /&gt;
       	&amp;lt;delete file=&amp;quot;${ofbiz.dir}/applications/order/build/lib/ofbiz-order.jar&amp;quot; failonerror=&amp;quot;false&amp;quot;/&amp;gt;&lt;br /&gt;
           &amp;lt;move file=&amp;quot;${lib.dir}/ofbiz-order.jar&amp;quot; tofile=&amp;quot;${ofbiz.dir}/applications/order/build/lib/ofbiz-order.jar&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
         &amp;lt;echo message=&amp;quot;[build] =========== Done Building Aspect (Weave) ==============&amp;quot;/&amp;gt;&lt;br /&gt;
       &amp;lt;/target&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===What to do if you get an RMIDispatcher Error===&lt;br /&gt;
&lt;br /&gt;
If you see an error message like this:&lt;br /&gt;
 Exception in thread &amp;quot;main&amp;quot; java.lang.NoSuchMethodError: sun.rmi.transport.Object &lt;br /&gt;
Table.getStub(Ljava/rmi/Remote;)Ljava/rmi/server/RemoteStub; &lt;br /&gt;
at org.objectweb.carol.rmi.jrmp.server.JUnicastRemoteObject.unexportObject(JUnicastRemoteObject.java:138) &lt;br /&gt;
at org.objectweb.carol.rmi.multi.JrmpPRODelegate.unexportObject(JrmpPRODelegate.java:94) &lt;br /&gt;
at org.objectweb.carol.rmi.multi.MultiPRODelegate.unexportObject(MultiPRODelegate.java:132) &lt;br /&gt;
at javax.rmi.PortableRemoteObject.unexportObject(Unknown Source) &lt;br /&gt;
at org.objectweb.jotm.SubCoordinator.doAfterCompletion(SubCoordinator.java:1548) &lt;br /&gt;
&lt;br /&gt;
You are experiencing a problem instantiating the RMI dispatcher.  The RMI dispatcher is used to call remote services running on another instance of oopentaps.  For demo purposes, you can usually turn this off by editing the file base/config/ofbiz-containers.xml and commenting out the &amp;lt;containers&amp;gt; for rmi-dispatcher and rmi-print-server.&lt;br /&gt;
&lt;br /&gt;
===What to do if you get a BSH Error===&lt;br /&gt;
&lt;br /&gt;
If you see this error message:&lt;br /&gt;
java.lang.NoSuchMethodError: bsh.BshClassManager.createClassManager()Lbsh/BshClassManager;&lt;br /&gt;
at org.ofbiz.base.util.BshUtil.getMasterInterpreter(BshUtil.java:124)&lt;br /&gt;
at org.ofbiz.base.util.BshUtil.makeInterpreter(BshUtil.java:95)&lt;br /&gt;
at org.ofbiz.base.util.BshUtil.runBshAtLocation(BshUtil.java:144)&lt;br /&gt;
&lt;br /&gt;
The problem is that your computer has another copy of beanshell (bsh.jar) installed in the Java class path.  For example, OS X sometimes has a bsh.jar in /Library/Java/Extensions/  Simply move it out of the way and try again.&lt;br /&gt;
&lt;br /&gt;
===Keystore was tampered with, or password was incorrect on OS X===&lt;br /&gt;
&lt;br /&gt;
If you encounter this error message:&lt;br /&gt;
Keystore was tampered with, or password was incorrect&lt;br /&gt;
&lt;br /&gt;
It is actually a problem with Java 6 on OS X, and you can fix it by changing your keystore:&lt;br /&gt;
&lt;br /&gt;
sudo keytool -keystore &amp;quot;/System/Library/Frameworks/JavaVM.framework/Versions/A/Resources/Deploy.bundle/Contents/Home/lib/security/cacerts&amp;quot;&lt;br /&gt;
-storepasswd -new &amp;quot;changeit&amp;quot;&lt;br /&gt;
Enter password: &amp;lt;your sudo password&amp;gt;&lt;br /&gt;
Enter password: changeme&lt;br /&gt;
&lt;br /&gt;
The new keystore password must be exactly &amp;quot;changeme&amp;quot;.  You do not need to modify the ofbiz-containers.xml file.  Just restart opentaps after this.&lt;/div&gt;</summary>
		<author><name>Spark</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=Opentaps_Magento_Integration&amp;diff=5607</id>
		<title>Opentaps Magento Integration</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=Opentaps_Magento_Integration&amp;diff=5607"/>
		<updated>2010-02-27T03:44:45Z</updated>

		<summary type="html">&lt;p&gt;Spark: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
'''This module is now ready for beta testing by developers. If you are interested, please [http://www.opensourcestrategies.com/contact/ contact Open Source Strategies] to request access to the Subversion repository.'''&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
This integration allows you to use the [http://www.magentocommerce.com/ Magento e-commerce system] with [http://www.opentaps.org opentaps Open Source ERP + CRM].   The integration is designed to allow you to set up your products and catalogs in Magento, take orders using the Magento online store or using the Magento order entry module, and then import the products and orders to opentaps for purchasing, manufacturing fulfillment, and invoicing.&lt;br /&gt;
&lt;br /&gt;
Specific features supported are:&lt;br /&gt;
* One way push from Magento of newly added products and sales orders (Changes to products and orders are currently not handled.)&lt;br /&gt;
* All Magento orders added to one &amp;quot;Magento Customer&amp;quot; in opentaps&lt;br /&gt;
* Payments received in Magento are imported into opentaps under &amp;quot;Magento customer&amp;quot; an associated with the corresponding order&lt;br /&gt;
* Once orders are shipped in opentaps, the tracking number is sent back to Magento and associate it with the original order.&lt;br /&gt;
* Only one magento product store is supported at any time.&lt;br /&gt;
&lt;br /&gt;
This integration is compatible with the free [http://www.magentocommerce.com/product/community-edition Magento Community Edition].&lt;br /&gt;
&lt;br /&gt;
==Installation==&lt;br /&gt;
&lt;br /&gt;
The opentaps-Magento integration requires one module for Magento and two components for opentaps:&lt;br /&gt;
* IntegratingWeb module for Magento&lt;br /&gt;
* Data Access Layer (DAL) and magento-integration components for opentaps&lt;br /&gt;
&lt;br /&gt;
The Magento module retrieves product and order data from Magento and serves them up via the REST protocol.  The DAL component for opentaps receives the data from the Magento module and stores them in the opentaps database, and the magento-integration component uses the opentaps data import component to import the products and orders.&lt;br /&gt;
&lt;br /&gt;
===Installing the Source Version from Subversion===&lt;br /&gt;
&lt;br /&gt;
You can install the source code version from subversion by checking out the IntegratingWeb module for Magento and the Data Access Layer (dal) and magento integration modules for opentaps.&lt;br /&gt;
&lt;br /&gt;
====Installing the Magento Extension====&lt;br /&gt;
&lt;br /&gt;
1. Checkout the IntegratingWeb Magento module in $magentoInstallationPath/app/code/local&lt;br /&gt;
   svn co svn://svn.opentaps.org/opentaps_magento/magento_component/versions/1.0/trunk/OpentapsIntegration OpentapsIntegration &lt;br /&gt;
&lt;br /&gt;
After the download, the Magento directory structure must look like the following:&lt;br /&gt;
   $magentoInstallationPath/app/code/local/OpentapsIntegration&lt;br /&gt;
&lt;br /&gt;
2. Move $magentoInstallationPath/app/code/local/OpentapsIntegration/Restful/etc/OpentapsIntegration_Restful.xml in $magentoInstallationPath/app/etc/modules:&lt;br /&gt;
   mv $magentoInstallationPath/app/code/local/OpentapsIntegration/Restful/etc/OpentapsIntegration_Restful.xml $magentoInstallationPath/app/etc/modules&lt;br /&gt;
&lt;br /&gt;
3. Go on the Magento backend in System-&amp;gt;Configuration, then Advanced-&amp;gt;Advanced (at the bottom of the left-hand side tabs for the System-&amp;gt;Configuration screen.)&lt;br /&gt;
&lt;br /&gt;
4. Click on &amp;quot;SAVE CONFIG&amp;quot; so that the Magento configuration files will be reloaded.&lt;br /&gt;
&lt;br /&gt;
5. Now click on &amp;quot;Disable modules output&amp;quot;, make sure you see a module named OpentapsIntegration_Restful.  If that is your case, then you have succesfully installed the Magento module:&lt;br /&gt;
&lt;br /&gt;
[[Image:Magento Modules Opentaps Integration.png|600px]]&lt;br /&gt;
&lt;br /&gt;
====Installing the opentaps Modules====&lt;br /&gt;
&lt;br /&gt;
First, go to the hot-deploy/ subdirectory for opentaps:&lt;br /&gt;
opentaps $ cd hot-deploy&lt;br /&gt;
&lt;br /&gt;
Then, checkout the Data Access Layer (DAL) and magento-integration modules:&lt;br /&gt;
&lt;br /&gt;
 hot-deploy $ svn co svn://svn.opentaps.org/opentaps_magento/opentaps_component/versions/1.4/trunk/dal dal  &lt;br /&gt;
 hot-deploy $ svn co svn://svn.opentaps.org/opentaps_magento/opentaps_component/versions/1.4/trunk/magento-integration magento-integration &lt;br /&gt;
&lt;br /&gt;
After the download, the opentaps directory structure must look like the following:&lt;br /&gt;
 $opentapsInstallationPath/hot-deploy/dal&lt;br /&gt;
 $opentapsInstallationPath/hot-deploy/magento-integration&lt;br /&gt;
&lt;br /&gt;
Modify the file $opentapsInstallationPath/hot-deploy/component-load.xml uncomment the following two lines:&lt;br /&gt;
   &amp;lt;load-component component-location=&amp;quot;dal&amp;quot;/&amp;gt;&lt;br /&gt;
   &amp;lt;load-component component-location=&amp;quot;magento-integration&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Go back to the opentaps directory and rebuild everything:&lt;br /&gt;
 opentaps $ ./ant&lt;br /&gt;
&lt;br /&gt;
The opentaps modules are now installed.  Now restart opentaps, and go to http://localhost:8080/magento-integration/control/main to ensure that the modules are loaded.&lt;br /&gt;
&lt;br /&gt;
==Configuring the opentaps Magento Integration==&lt;br /&gt;
&lt;br /&gt;
First you need a user which has access to magento data. You can create this user from the Magento backend:&lt;br /&gt;
# In the Magento backend, go to System-&amp;gt; Web Service -&amp;gt; Users, and add a new user. &lt;br /&gt;
# Then go to System-&amp;gt; Web Service -&amp;gt; Roles and create a new Role with &amp;quot;Resource Access&amp;quot; set to &amp;quot;All&amp;quot;.&lt;br /&gt;
# Finally, associate the user with that role. &lt;br /&gt;
&lt;br /&gt;
Next, $opentapsInstallationPath/hot-deploy/magento-integration/config/magento-integration.properties:&lt;br /&gt;
# Set the URL and administrative access user and password for opentaps&lt;br /&gt;
# Set the base store URL and resource access user and password for magento.   Test it by trying the URL plus &amp;lt;tt&amp;gt;/ws/orders/login&amp;lt;/tt&amp;gt; For example, if your base store URL is &amp;lt;tt&amp;gt;http://www.my-magento-store.com/index.php&amp;lt;/tt&amp;gt;, then you should see a page at &amp;lt;tt&amp;gt;http://www.my-magento-store.com/index.php/ws/orders/login&amp;lt;/tt&amp;gt;  The password is also the same as your magento user's API key.&lt;br /&gt;
# Set paging size, which is the number of products retrieved in each batch from magento&lt;br /&gt;
# Set the magento store ID, which is the field store_id of the table core_store of the Magento DB.   &lt;br /&gt;
&lt;br /&gt;
'''NOTE:''' when you modify any .properties file in Opentaps, you must reboot your instance because properties are loaded statically at boot application time.&lt;br /&gt;
&lt;br /&gt;
Finally, use the opentaps Webtools &amp;gt; Entity XML Import to load the following files:&lt;br /&gt;
* hot-deploy/magento-integration/data/MagentoPrimaryStore.xml&lt;br /&gt;
* hot-deploy/magento-integration/data/MagentoPrimaryStoreCatalog.xml&lt;br /&gt;
* hot-deploy/magento-integration/data/MagentoCustomer.xml&lt;br /&gt;
&lt;br /&gt;
==Opentaps/Magento Mappings explanation==&lt;br /&gt;
&lt;br /&gt;
The magento-integration Opentaps module has a directory named &amp;quot;mappings&amp;quot; that contains a CSV file for every Magento workflow/area currently supported by the integration. These CSV files are processed by the transformations, and used when &lt;br /&gt;
storing data in Opentaps.&lt;br /&gt;
&lt;br /&gt;
'''storeMappings.csv''': handles the mapping between the Magento stores IDs and the Opentaps ProductStore/RootCategory entities.&lt;br /&gt;
&lt;br /&gt;
    MagentoStoreId,OpentapsRootCategoryId,OpentapsStoreId&lt;br /&gt;
    1,MPSCATALOG1,mag1&lt;br /&gt;
&lt;br /&gt;
The ProductCategory and ProductStore definitions can be found in magento-integration/data: by default XML files there are loaded as demo data. Informations about the Magento storeIDs can be found in the ''core_store'' table.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''shippingMappings.csv''': handles the mapping between the Magento shipping methods and the Opentaps shipping methods&lt;br /&gt;
 &lt;br /&gt;
   magentoShippingMethodId,opentapsShippingMethodId&lt;br /&gt;
   fedex_FEDEXGROUND,9015&lt;br /&gt;
   ups_GND,9001&lt;br /&gt;
   fedex_FEDEX2DAY,9002&lt;br /&gt;
&lt;br /&gt;
The Opentaps shipping method IDs are defined as seed data, and are common of every Opentaps installation. The Magento shipping methods can be found in the ''core_config_data'' table: by default Magento append the carrier code (ex.: UPS) to the shipping method (ex.: GND, states for Ground), thus resulting in a shippingMethodId of ups_GND.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''paymentsMappings.csv''': handles the mapping between Magento payment gateways and Opentaps payment methods.&lt;br /&gt;
&lt;br /&gt;
   MagentoPaymentMethodId,OpentapsPaymentMethodId&lt;br /&gt;
   authorizenet,CREDIT_CARD&lt;br /&gt;
&lt;br /&gt;
The Opentaps payment method types and be found in the ''PaymentMethodType'' entity. The Magento payment methods can be found in the ''core_config_data'' table.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''taxIdMappings.csv''': handles the mapping between Magento tax codes and Opentaps tax authorities.&lt;br /&gt;
&lt;br /&gt;
   magentoTaxCode,opentapsTaxAuthPartyId&lt;br /&gt;
   US-CA-*-Rate 1,CA_BOE&lt;br /&gt;
   US-NY-*-Rate 1,NY_DTF&lt;br /&gt;
&lt;br /&gt;
The Opentaps tax authorities can be found in the ''TaxAuthority'' entity (''taxAuthPartyId'' field). The Magento tax codes, that needs to be defined for tax calculation, can be found in the ''tax_calculation_rate'' table.&lt;br /&gt;
&lt;br /&gt;
==Testing the Integration==&lt;br /&gt;
&lt;br /&gt;
Magento orders need to be in the &amp;quot;Processing&amp;quot; state to be imported into opentaps.  This means that they must have payment received first.  You can use the [https://developer.paypal.com/ paypal developer sandbox] to set up a dummy paypal account for payment processing.  Alternatively, you can create your order with Check/Money Order and invoice the order, and then it will be &amp;quot;Processing.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==How-To Implement Paypal Payments Pro into Magento - SANDBOX==&lt;br /&gt;
 &lt;br /&gt;
You can follow the [http://www.magentocommerce.com/wiki/how-to_implement_paypal_payments_pro_into_magento_-_sandbox] to set up a developer account for payment processing.&lt;br /&gt;
&lt;br /&gt;
==Performance tuning==&lt;br /&gt;
&lt;br /&gt;
When importing a large number of products/orders (order of thousands, we made some tests with more than 10.000 products) performance issues become important.&lt;br /&gt;
&lt;br /&gt;
====Opentaps====&lt;br /&gt;
Default values of Opentaps 1.4 defined in startofbiz.sh work fine. Ensure that the Java Virtual Machine will be started with the following values&lt;br /&gt;
   -Xms512M -Xmx1536M -XX:MaxPermSize=1024M&lt;br /&gt;
&lt;br /&gt;
'''Note''': in Unix systems the maximum number of open file descriptors is sometimes configured for a non-production system, that probably will not have high loads. In Linux based systems, this value is most of the time configured to 1024: the value can be verified with the following command:&lt;br /&gt;
&lt;br /&gt;
   ulimit -n&lt;br /&gt;
&lt;br /&gt;
To increase the default value, add a line such as the following in the file /etc/security/limits.conf&lt;br /&gt;
&lt;br /&gt;
   yourUser - nofile 10000 &lt;br /&gt;
&lt;br /&gt;
Finally, reboot your machine.&lt;br /&gt;
&lt;br /&gt;
====Magento====&lt;br /&gt;
In $magentoInstallationPath/.htaccess memory used by PHP must be increased to a value of at least 512 Mb: this is a value you must tune based on the number of concurrent users that will access you production web site.&lt;br /&gt;
&lt;br /&gt;
   php_value memory_limit 512M&lt;/div&gt;</summary>
		<author><name>Spark</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=Upgrading_from_opentaps_1.0_to_opentaps_1.4&amp;diff=5606</id>
		<title>Upgrading from opentaps 1.0 to opentaps 1.4</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=Upgrading_from_opentaps_1.0_to_opentaps_1.4&amp;diff=5606"/>
		<updated>2010-02-27T00:07:17Z</updated>

		<summary type="html">&lt;p&gt;Spark: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
== Data Changes ==&lt;br /&gt;
&lt;br /&gt;
* Run the service &amp;lt;tt&amp;gt;opentaps.setSupplementalDataForAllParties&amp;lt;/tt&amp;gt; to populate primary contact data for all parties.&lt;br /&gt;
* Configuration of GL accounts for invoice writeoffs have been changed.  Instead of using &amp;lt;tt&amp;gt;GlAccountTypeDefault&amp;lt;/tt&amp;gt;, they are now configured with &amp;lt;tt&amp;gt;InvoiceAdjustmentGlAccount&amp;lt;/tt&amp;gt; with the adjustment type &amp;quot;WRITEOFF&amp;quot;&lt;br /&gt;
* If you have custom UI labels, they may be loaded by adding them to &amp;lt;tt&amp;gt;LabelConfiguration.properties&amp;lt;/tt&amp;gt; in &amp;lt;tt&amp;gt;opentaps-common/config/&amp;lt;/tt&amp;gt;&lt;br /&gt;
** If previously you were using &amp;lt;tt&amp;gt;UtilMessage.registerLabelMap()&amp;lt;/tt&amp;gt; to load custom labels, you may now remove all calls to this function as it is no longer needed.&lt;br /&gt;
* Run the upgrade SQL script in hot-deploy/opentaps-common/scripts/sql for the following:&lt;br /&gt;
** &amp;lt;tt&amp;gt;ProductAverageCost&amp;lt;/tt&amp;gt; has been re-factored to use a single productAverageCostId as its primary key.  The script will alter the table and automatically fill in its values and update &amp;lt;tt&amp;gt;SequenceValueItem&amp;lt;/tt&amp;gt; so that opentaps will generate correct future keys.&lt;br /&gt;
* Add the following to your custom component's build.xml:&lt;br /&gt;
   &amp;lt;fileset dir=&amp;quot;${ofbiz.dir}/hot-deploy/opentaps-common/lib&amp;quot; includes=&amp;quot;*.jar&amp;quot;/&amp;gt;&lt;br /&gt;
   &amp;lt;fileset dir=&amp;quot;${ofbiz.dir}/hot-deploy/opentaps-common/lib/hibernate&amp;quot; includes=&amp;quot;*.jar&amp;quot;/&amp;gt;&lt;br /&gt;
* Set &amp;lt;tt&amp;gt;SupplierProduct.supplierPrefOrderId&amp;lt;/tt&amp;gt; to '''10_MAIN_SUPPL''' where it is null.&lt;br /&gt;
* Run the following services to set summary fields:&lt;br /&gt;
** &amp;lt;tt&amp;gt;recalcAllEmptyAmountsPayments&amp;lt;/tt&amp;gt;&lt;br /&gt;
** &amp;lt;tt&amp;gt;recalcAllEmptyAmountsInvoices&amp;lt;/tt&amp;gt;&lt;br /&gt;
** &amp;lt;tt&amp;gt;updatePostedAmountAcctgTrans&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Run the following service to create hibernate search index files:&lt;br /&gt;
** &amp;lt;tt&amp;gt;opentaps.createHibernateSearchIndex&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Run the following SQL query to set Invoice.paidDate:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
update INVOICE i set PAID_DATE = (&lt;br /&gt;
 select paidDate from&lt;br /&gt;
 (&lt;br /&gt;
 select max(EFFECTIVE_DATE) paidDate, b.INVOICE_ID from PAYMENT a inner&lt;br /&gt;
 join PAYMENT_APPLICATION b on a.PAYMENT_ID=b.PAYMENT_ID group by&lt;br /&gt;
 b.INVOICE_ID&lt;br /&gt;
 ) p where p.INVOICE_ID = i.INVOICE_ID and i.STATUS_ID='INVOICE_PAID'&lt;br /&gt;
 );&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Run the ant import ext seed in command window: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 ant run-install-extseed&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== Coding Changes ==&lt;br /&gt;
&lt;br /&gt;
Changes in the ofbiz framework would require the following changes to your code:&lt;br /&gt;
&lt;br /&gt;
=== URL Parameter Security ===&lt;br /&gt;
&lt;br /&gt;
You can no longer pass parameters to a service request directly in the URL.  These requests must be part of a POST form.  To make buttons work as before, you need to change them to forms and then activate them with javascript.  For example, in earlier versions, you could have a button to delete a lead like this:&lt;br /&gt;
  &amp;lt;#assign update_options = update_options + &amp;quot;&amp;lt;a class='subMenuButtonDangerous' &lt;br /&gt;
           href='deleteLead?leadPartyId=&amp;quot; + partySummary.partyId + &amp;quot;'&amp;gt;&amp;quot; + uiLabelMap.CommonDelete + &amp;quot;&amp;lt;/a&amp;gt;&amp;quot;  /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In opentaps 1.4, you must do it this way:&lt;br /&gt;
   &amp;lt;form name=&amp;quot;deleteLeadForm&amp;quot; method=&amp;quot;post&amp;quot; action=&amp;quot;&amp;lt;@ofbizUrl&amp;gt;deleteLead&amp;lt;/@ofbizUrl&amp;gt;&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;@inputHidden name=&amp;quot;leadPartyId&amp;quot; value=&amp;quot;${partySummary.partyId}&amp;quot;/&amp;gt;&lt;br /&gt;
   &amp;lt;/form&amp;gt;&lt;br /&gt;
   &amp;lt;#assign update_options = update_options + &amp;quot;&amp;lt;a class='subMenuButtonDangerous' &lt;br /&gt;
            href='javascript:document.deleteLeadForm.submit()'&amp;gt;&amp;quot; + uiLabelMap.CommonDelete + &amp;quot;&amp;lt;/a&amp;gt;&amp;quot;  /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For your convenience, there is also a new macro to do this (see ''form'' and ''submitFormLink'' in opentapsFormMacro.ftl):&lt;br /&gt;
   &amp;lt;@form name=&amp;quot;deleteLeadForm&amp;quot; url=&amp;quot;deleteLead&amp;quot; leadPartyId=partySummary.partyId /&amp;gt;&lt;br /&gt;
   &amp;lt;#assign update_options&amp;gt;${update_options}&amp;lt;@submitFormLink form=&amp;quot;deleteLeadForm&amp;quot; text=uiLabelMap.CommonDelete class=&amp;quot;subMenuButtonDangerous&amp;quot; /&amp;gt;&amp;lt;/#assign&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The ''form'' macro makes hidden inputs for all parameters (except ''name'', ''url'' and ''method'' that are used to define the form element itself), and also accept nested elements for more complex cases.&lt;br /&gt;
&lt;br /&gt;
For the cases where a form has to be used for multiple items, for example when you have an Update form block which must include multiple remove links, instead of writing a JavaScript handler which passes the item Ids to the form before submitting, you can do:&lt;br /&gt;
&lt;br /&gt;
   &amp;lt;@form name=&amp;quot;removeReturnItemAction&amp;quot; url=&amp;quot;removeReturnItem&amp;quot; returnId=returnId returnItemSeqId=&amp;quot;&amp;quot; /&amp;gt;&lt;br /&gt;
   &amp;lt;@form name=&amp;quot;updateReturnItemsAction&amp;quot; url=&amp;quot;updateReturnItems&amp;quot; returnId=returnId&amp;gt;&lt;br /&gt;
     &amp;lt;#list returnItems as item&amp;gt;&lt;br /&gt;
       &amp;lt;!-- some editable fields for the updateReturnItems form --&amp;gt;&lt;br /&gt;
      &amp;lt;@submitFormLinkConfirm form=&amp;quot;removeReturnItemAction&amp;quot; text=uiLabelMap.CommonRemove returnItemSeqId=item.returnItemSeqId /&amp;gt;&lt;br /&gt;
     &amp;lt;/#list&amp;gt;&lt;br /&gt;
   &amp;lt;/@form&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Also the new ''selectActionForm'' and ''actionForm'' can be used with ''form'' to define a drop-down menu where when an item (''actionForm'') is selected it submits the corresponding ''form'':&lt;br /&gt;
   &amp;lt;@form name=&amp;quot;deleteLeadForm&amp;quot; url=&amp;quot;deleteLead&amp;quot; leadPartyId=partySummary.partyId /&amp;gt;&lt;br /&gt;
   &amp;lt;@form ... /&amp;gt;&lt;br /&gt;
   &amp;lt;@selectActionForm name=&amp;quot;leadActions&amp;quot; prompt=&amp;quot;${uiLabelMap.CommonSelectOne}&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;@actionForm form=&amp;quot;deleteLeadForm&amp;quot; text=&amp;quot;${uiLabelMap.CommonDelete}&amp;quot;/&amp;gt;&lt;br /&gt;
     &amp;lt;@actionForm .../&amp;gt;&lt;br /&gt;
   &amp;lt;@selectAction/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Service and HTML inputs ===&lt;br /&gt;
&lt;br /&gt;
As a security feature, the services will filter any input with HTML by default. Some services still require HTML (like emails or templates services) and to allow that there is a new ''allow-html'' parameter. For example:&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;attribute name=&amp;quot;content&amp;quot; type=&amp;quot;String&amp;quot; mode=&amp;quot;IN&amp;quot; optional=&amp;quot;false&amp;quot; allow-html=&amp;quot;safe&amp;quot;/&amp;gt;&lt;br /&gt;
     &amp;lt;override name=&amp;quot;mergeFormText&amp;quot; allow-html=&amp;quot;safe&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Form Widget Changes ===&lt;br /&gt;
&lt;br /&gt;
Form widget URL parameters should be specified with &amp;lt;tt&amp;gt;parameter&amp;lt;/tt&amp;gt; tag now, instead of in the URL:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-            &amp;lt;hyperlink description=&amp;quot;${contactListName} (${contactListId})&amp;quot; target=&amp;quot;viewContactList?contactListId=${contactListId}&amp;quot;&amp;gt;&lt;br /&gt;
+            &amp;lt;hyperlink description=&amp;quot;${contactListName} (${contactListId})&amp;quot; target=&amp;quot;viewContactList&amp;quot;&amp;gt;&lt;br /&gt;
+                &amp;lt;parameter param-name=&amp;quot;contactListId&amp;quot; from-field=&amp;quot;contactListId&amp;quot;/&amp;gt;&lt;br /&gt;
             &amp;lt;/hyperlink&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Do not have it both in the URL and as a &amp;lt;tt&amp;gt;parameter&amp;lt;/tt&amp;gt;, or the parameter will be on the form twice and be passed incorrectly.&lt;br /&gt;
&lt;br /&gt;
=== Controller redirects ===&lt;br /&gt;
&lt;br /&gt;
Redirects have been changed, now ''request-redirect'' will only copy the parameters that were in the URL string by default. To forward posted or service output parameter, use the ''redirect-parameter'' elements (one per parameter).&lt;br /&gt;
   &amp;lt;response name=&amp;quot;success&amp;quot; type=&amp;quot;request-redirect&amp;quot; value=&amp;quot;viewAccount&amp;quot;&amp;gt;&lt;br /&gt;
       &amp;lt;redirect-parameter name=&amp;quot;partyId&amp;quot;/&amp;gt;&lt;br /&gt;
   &amp;lt;/response&amp;gt;&lt;br /&gt;
Also ''request-redirect-filter-param'' is now considered deprecated.&lt;br /&gt;
&lt;br /&gt;
=== Js dateTime format ===&lt;br /&gt;
&lt;br /&gt;
Js dataTime format in ftl have been changed, now the format will return html encode string which will cause the parse exception, you should use StringUtil.wrapString to avoid this issue. For example, in earlier versions, you could have define a js dataTime format variable like this:&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;#assign dateFormat = Static[&amp;quot;org.opentaps.common.util.UtilDate&amp;quot;].getJsDateTimeFormat(Static[&amp;quot;org.opentaps.common.util.UtilDate&amp;quot;].getDateFormat(locale))/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In opentaps 1.4, you must do it this way:&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;#assign dateFormat = StringUtil.wrapString(Static[&amp;quot;org.opentaps.common.util.UtilDate&amp;quot;].getJsDateTimeFormat(Static[&amp;quot;org.opentaps.common.util.UtilDate&amp;quot;].getDateFormat(locale)))/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== BSH embedded in Forms ===&lt;br /&gt;
&lt;br /&gt;
In Forms widgets you could embed bsh code in order to have more flexibility over the formatting. Those embedded scripts need to be changed to groovy to avoid classpath issues. Fortunately this is as simple as changing the ''${bsh:'' to ''${groovy:''&lt;br /&gt;
&lt;br /&gt;
For example, in earlier versions, you could transform a party Id into the whole party name:&lt;br /&gt;
&lt;br /&gt;
   &amp;lt;field name=&amp;quot;partyId&amp;quot; title=&amp;quot;${uiLabelMap.ProductSupplier}&amp;quot;&amp;gt; &lt;br /&gt;
     &amp;lt;display description=&amp;quot;${bsh:org.ofbiz.party.party.PartyHelper.getPartyName(delegator, partyId, false)} (${partyId})&amp;quot;/&amp;gt;&lt;br /&gt;
   &amp;lt;/field&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In opentaps 1.4, you must change it to:&lt;br /&gt;
&lt;br /&gt;
   &amp;lt;field name=&amp;quot;partyId&amp;quot; title=&amp;quot;${uiLabelMap.ProductSupplier}&amp;quot;&amp;gt; &lt;br /&gt;
     &amp;lt;display description=&amp;quot;${groovy:org.ofbiz.party.party.PartyHelper.getPartyName(delegator, partyId, false)} (${partyId})&amp;quot;/&amp;gt;&lt;br /&gt;
   &amp;lt;/field&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== UEL in Minilang ===&lt;br /&gt;
&lt;br /&gt;
The ofbiz framework now supports unified express language (UEL) in the screen widgets and minilang simple methods.  (See [http://docs.ofbiz.org/display/OFBTECH/Unified+Expression+Language+%28JSR-245%29+in+OFBiz ofbiz wiki])&lt;br /&gt;
&lt;br /&gt;
One side effect is that code in simple methods, for example:&lt;br /&gt;
  someHash.${someVariableAsKey}&lt;br /&gt;
&lt;br /&gt;
In opentaps 1.4, you must change it to:&lt;br /&gt;
  someHash[someVariableAsKey]&lt;br /&gt;
&lt;br /&gt;
=== HTML escaping ===&lt;br /&gt;
&lt;br /&gt;
The ofbiz framework now automatically encodes most of the data displayed on the page. In some cases this is not wanted, and to avoid escaping in form widget use ''encode-output=&amp;quot;false&amp;quot;'' in the field element:&lt;br /&gt;
    &amp;lt;field name=&amp;quot;transactionDate&amp;quot; encode-output=&amp;quot;false&amp;quot;&amp;gt;&amp;lt;date-time/&amp;gt;&amp;lt;/field&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the FTL templates use the ''StringUtil'' class:&lt;br /&gt;
    ${StringUtil.wrapString(someData)}&lt;br /&gt;
&lt;br /&gt;
Some previous helper methods that constructed HTML code will not work anymore. For example ''PartyHelper.createViewPageLink'' has been replaced with the macro:&lt;br /&gt;
    &amp;lt;@displayPartyLink partyId=partyId /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Internationalization and Translations ==&lt;br /&gt;
&lt;br /&gt;
In ofbiz09.04, translations are now in XML format instead of .properties.   However, the old .properties translations are supported still as well.&lt;br /&gt;
&lt;br /&gt;
Furthermore, it is possible to define a component with all your translations, instead of putting them into the various existing components. As an example, &amp;lt;tt&amp;gt;hot-deploy/translations&amp;lt;/tt&amp;gt; in opentaps contains a full set of translations for opentaps to Bulgarian.&lt;br /&gt;
&lt;br /&gt;
== Other Changes ==&lt;br /&gt;
&lt;br /&gt;
In some cases the ''screenlet-title-bar'' used in some ofbiz forms and screens is not wanted, in that case simply wrap the form or screen section in a ''noTitleBar'' div.&lt;br /&gt;
&lt;br /&gt;
For example ''ViewShipmentRouteInfo.ftl'' defines such a title, to hide it we added to the screen definition:&lt;br /&gt;
&lt;br /&gt;
      &amp;lt;container style=&amp;quot;noTitleBar&amp;quot;&amp;gt;&lt;br /&gt;
          &amp;lt;platform-specific&amp;gt;&lt;br /&gt;
              &amp;lt;html&amp;gt;&amp;lt;html-template location=&amp;quot;component://product/webapp/facility/shipment/ViewShipmentRouteInfo.ftl&amp;quot;/&amp;gt;&amp;lt;/html&amp;gt;&lt;br /&gt;
          &amp;lt;/platform-specific&amp;gt;&lt;br /&gt;
      &amp;lt;/container&amp;gt;&lt;/div&gt;</summary>
		<author><name>Spark</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=Upgrading_from_opentaps_1.0_to_opentaps_1.4&amp;diff=5605</id>
		<title>Upgrading from opentaps 1.0 to opentaps 1.4</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=Upgrading_from_opentaps_1.0_to_opentaps_1.4&amp;diff=5605"/>
		<updated>2010-02-27T00:06:41Z</updated>

		<summary type="html">&lt;p&gt;Spark: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
== Data Changes ==&lt;br /&gt;
&lt;br /&gt;
* Run the service &amp;lt;tt&amp;gt;opentaps.setSupplementalDataForAllParties&amp;lt;/tt&amp;gt; to populate primary contact data for all parties.&lt;br /&gt;
* Configuration of GL accounts for invoice writeoffs have been changed.  Instead of using &amp;lt;tt&amp;gt;GlAccountTypeDefault&amp;lt;/tt&amp;gt;, they are now configured with &amp;lt;tt&amp;gt;InvoiceAdjustmentGlAccount&amp;lt;/tt&amp;gt; with the adjustment type &amp;quot;WRITEOFF&amp;quot;&lt;br /&gt;
* If you have custom UI labels, they may be loaded by adding them to &amp;lt;tt&amp;gt;LabelConfiguration.properties&amp;lt;/tt&amp;gt; in &amp;lt;tt&amp;gt;opentaps-common/config/&amp;lt;/tt&amp;gt;&lt;br /&gt;
** If previously you were using &amp;lt;tt&amp;gt;UtilMessage.registerLabelMap()&amp;lt;/tt&amp;gt; to load custom labels, you may now remove all calls to this function as it is no longer needed.&lt;br /&gt;
* Run the upgrade SQL script in hot-deploy/opentaps-common/scripts/sql for the following:&lt;br /&gt;
** &amp;lt;tt&amp;gt;ProductAverageCost&amp;lt;/tt&amp;gt; has been re-factored to use a single productAverageCostId as its primary key.  The script will alter the table and automatically fill in its values and update &amp;lt;tt&amp;gt;SequenceValueItem&amp;lt;/tt&amp;gt; so that opentaps will generate correct future keys.&lt;br /&gt;
* Add the following to your custom component's build.xml:&lt;br /&gt;
   &amp;lt;fileset dir=&amp;quot;${ofbiz.dir}/hot-deploy/opentaps-common/lib&amp;quot; includes=&amp;quot;*.jar&amp;quot;/&amp;gt;&lt;br /&gt;
   &amp;lt;fileset dir=&amp;quot;${ofbiz.dir}/hot-deploy/opentaps-common/lib/hibernate&amp;quot; includes=&amp;quot;*.jar&amp;quot;/&amp;gt;&lt;br /&gt;
* Set &amp;lt;tt&amp;gt;SupplierProduct.supplierPrefOrderId&amp;lt;/tt&amp;gt; to '''10_MAIN_SUPPL''' where it is null.&lt;br /&gt;
* Run the following services to set summary fields:&lt;br /&gt;
** &amp;lt;tt&amp;gt;recalcAllEmptyAmountsPayments&amp;lt;/tt&amp;gt;&lt;br /&gt;
** &amp;lt;tt&amp;gt;recalcAllEmptyAmountsInvoices&amp;lt;/tt&amp;gt;&lt;br /&gt;
** &amp;lt;tt&amp;gt;updatePostedAmountAcctgTrans&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Run the following services to create hibernate index files:&lt;br /&gt;
** &amp;lt;tt&amp;gt;opentaps.createHibernateSearchIndex&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Run the following SQL query to set Invoice.paidDate:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
update INVOICE i set PAID_DATE = (&lt;br /&gt;
 select paidDate from&lt;br /&gt;
 (&lt;br /&gt;
 select max(EFFECTIVE_DATE) paidDate, b.INVOICE_ID from PAYMENT a inner&lt;br /&gt;
 join PAYMENT_APPLICATION b on a.PAYMENT_ID=b.PAYMENT_ID group by&lt;br /&gt;
 b.INVOICE_ID&lt;br /&gt;
 ) p where p.INVOICE_ID = i.INVOICE_ID and i.STATUS_ID='INVOICE_PAID'&lt;br /&gt;
 );&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Run the ant import ext seed in command window: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 ant run-install-extseed&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== Coding Changes ==&lt;br /&gt;
&lt;br /&gt;
Changes in the ofbiz framework would require the following changes to your code:&lt;br /&gt;
&lt;br /&gt;
=== URL Parameter Security ===&lt;br /&gt;
&lt;br /&gt;
You can no longer pass parameters to a service request directly in the URL.  These requests must be part of a POST form.  To make buttons work as before, you need to change them to forms and then activate them with javascript.  For example, in earlier versions, you could have a button to delete a lead like this:&lt;br /&gt;
  &amp;lt;#assign update_options = update_options + &amp;quot;&amp;lt;a class='subMenuButtonDangerous' &lt;br /&gt;
           href='deleteLead?leadPartyId=&amp;quot; + partySummary.partyId + &amp;quot;'&amp;gt;&amp;quot; + uiLabelMap.CommonDelete + &amp;quot;&amp;lt;/a&amp;gt;&amp;quot;  /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In opentaps 1.4, you must do it this way:&lt;br /&gt;
   &amp;lt;form name=&amp;quot;deleteLeadForm&amp;quot; method=&amp;quot;post&amp;quot; action=&amp;quot;&amp;lt;@ofbizUrl&amp;gt;deleteLead&amp;lt;/@ofbizUrl&amp;gt;&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;@inputHidden name=&amp;quot;leadPartyId&amp;quot; value=&amp;quot;${partySummary.partyId}&amp;quot;/&amp;gt;&lt;br /&gt;
   &amp;lt;/form&amp;gt;&lt;br /&gt;
   &amp;lt;#assign update_options = update_options + &amp;quot;&amp;lt;a class='subMenuButtonDangerous' &lt;br /&gt;
            href='javascript:document.deleteLeadForm.submit()'&amp;gt;&amp;quot; + uiLabelMap.CommonDelete + &amp;quot;&amp;lt;/a&amp;gt;&amp;quot;  /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For your convenience, there is also a new macro to do this (see ''form'' and ''submitFormLink'' in opentapsFormMacro.ftl):&lt;br /&gt;
   &amp;lt;@form name=&amp;quot;deleteLeadForm&amp;quot; url=&amp;quot;deleteLead&amp;quot; leadPartyId=partySummary.partyId /&amp;gt;&lt;br /&gt;
   &amp;lt;#assign update_options&amp;gt;${update_options}&amp;lt;@submitFormLink form=&amp;quot;deleteLeadForm&amp;quot; text=uiLabelMap.CommonDelete class=&amp;quot;subMenuButtonDangerous&amp;quot; /&amp;gt;&amp;lt;/#assign&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The ''form'' macro makes hidden inputs for all parameters (except ''name'', ''url'' and ''method'' that are used to define the form element itself), and also accept nested elements for more complex cases.&lt;br /&gt;
&lt;br /&gt;
For the cases where a form has to be used for multiple items, for example when you have an Update form block which must include multiple remove links, instead of writing a JavaScript handler which passes the item Ids to the form before submitting, you can do:&lt;br /&gt;
&lt;br /&gt;
   &amp;lt;@form name=&amp;quot;removeReturnItemAction&amp;quot; url=&amp;quot;removeReturnItem&amp;quot; returnId=returnId returnItemSeqId=&amp;quot;&amp;quot; /&amp;gt;&lt;br /&gt;
   &amp;lt;@form name=&amp;quot;updateReturnItemsAction&amp;quot; url=&amp;quot;updateReturnItems&amp;quot; returnId=returnId&amp;gt;&lt;br /&gt;
     &amp;lt;#list returnItems as item&amp;gt;&lt;br /&gt;
       &amp;lt;!-- some editable fields for the updateReturnItems form --&amp;gt;&lt;br /&gt;
      &amp;lt;@submitFormLinkConfirm form=&amp;quot;removeReturnItemAction&amp;quot; text=uiLabelMap.CommonRemove returnItemSeqId=item.returnItemSeqId /&amp;gt;&lt;br /&gt;
     &amp;lt;/#list&amp;gt;&lt;br /&gt;
   &amp;lt;/@form&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Also the new ''selectActionForm'' and ''actionForm'' can be used with ''form'' to define a drop-down menu where when an item (''actionForm'') is selected it submits the corresponding ''form'':&lt;br /&gt;
   &amp;lt;@form name=&amp;quot;deleteLeadForm&amp;quot; url=&amp;quot;deleteLead&amp;quot; leadPartyId=partySummary.partyId /&amp;gt;&lt;br /&gt;
   &amp;lt;@form ... /&amp;gt;&lt;br /&gt;
   &amp;lt;@selectActionForm name=&amp;quot;leadActions&amp;quot; prompt=&amp;quot;${uiLabelMap.CommonSelectOne}&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;@actionForm form=&amp;quot;deleteLeadForm&amp;quot; text=&amp;quot;${uiLabelMap.CommonDelete}&amp;quot;/&amp;gt;&lt;br /&gt;
     &amp;lt;@actionForm .../&amp;gt;&lt;br /&gt;
   &amp;lt;@selectAction/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Service and HTML inputs ===&lt;br /&gt;
&lt;br /&gt;
As a security feature, the services will filter any input with HTML by default. Some services still require HTML (like emails or templates services) and to allow that there is a new ''allow-html'' parameter. For example:&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;attribute name=&amp;quot;content&amp;quot; type=&amp;quot;String&amp;quot; mode=&amp;quot;IN&amp;quot; optional=&amp;quot;false&amp;quot; allow-html=&amp;quot;safe&amp;quot;/&amp;gt;&lt;br /&gt;
     &amp;lt;override name=&amp;quot;mergeFormText&amp;quot; allow-html=&amp;quot;safe&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Form Widget Changes ===&lt;br /&gt;
&lt;br /&gt;
Form widget URL parameters should be specified with &amp;lt;tt&amp;gt;parameter&amp;lt;/tt&amp;gt; tag now, instead of in the URL:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-            &amp;lt;hyperlink description=&amp;quot;${contactListName} (${contactListId})&amp;quot; target=&amp;quot;viewContactList?contactListId=${contactListId}&amp;quot;&amp;gt;&lt;br /&gt;
+            &amp;lt;hyperlink description=&amp;quot;${contactListName} (${contactListId})&amp;quot; target=&amp;quot;viewContactList&amp;quot;&amp;gt;&lt;br /&gt;
+                &amp;lt;parameter param-name=&amp;quot;contactListId&amp;quot; from-field=&amp;quot;contactListId&amp;quot;/&amp;gt;&lt;br /&gt;
             &amp;lt;/hyperlink&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Do not have it both in the URL and as a &amp;lt;tt&amp;gt;parameter&amp;lt;/tt&amp;gt;, or the parameter will be on the form twice and be passed incorrectly.&lt;br /&gt;
&lt;br /&gt;
=== Controller redirects ===&lt;br /&gt;
&lt;br /&gt;
Redirects have been changed, now ''request-redirect'' will only copy the parameters that were in the URL string by default. To forward posted or service output parameter, use the ''redirect-parameter'' elements (one per parameter).&lt;br /&gt;
   &amp;lt;response name=&amp;quot;success&amp;quot; type=&amp;quot;request-redirect&amp;quot; value=&amp;quot;viewAccount&amp;quot;&amp;gt;&lt;br /&gt;
       &amp;lt;redirect-parameter name=&amp;quot;partyId&amp;quot;/&amp;gt;&lt;br /&gt;
   &amp;lt;/response&amp;gt;&lt;br /&gt;
Also ''request-redirect-filter-param'' is now considered deprecated.&lt;br /&gt;
&lt;br /&gt;
=== Js dateTime format ===&lt;br /&gt;
&lt;br /&gt;
Js dataTime format in ftl have been changed, now the format will return html encode string which will cause the parse exception, you should use StringUtil.wrapString to avoid this issue. For example, in earlier versions, you could have define a js dataTime format variable like this:&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;#assign dateFormat = Static[&amp;quot;org.opentaps.common.util.UtilDate&amp;quot;].getJsDateTimeFormat(Static[&amp;quot;org.opentaps.common.util.UtilDate&amp;quot;].getDateFormat(locale))/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In opentaps 1.4, you must do it this way:&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;#assign dateFormat = StringUtil.wrapString(Static[&amp;quot;org.opentaps.common.util.UtilDate&amp;quot;].getJsDateTimeFormat(Static[&amp;quot;org.opentaps.common.util.UtilDate&amp;quot;].getDateFormat(locale)))/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== BSH embedded in Forms ===&lt;br /&gt;
&lt;br /&gt;
In Forms widgets you could embed bsh code in order to have more flexibility over the formatting. Those embedded scripts need to be changed to groovy to avoid classpath issues. Fortunately this is as simple as changing the ''${bsh:'' to ''${groovy:''&lt;br /&gt;
&lt;br /&gt;
For example, in earlier versions, you could transform a party Id into the whole party name:&lt;br /&gt;
&lt;br /&gt;
   &amp;lt;field name=&amp;quot;partyId&amp;quot; title=&amp;quot;${uiLabelMap.ProductSupplier}&amp;quot;&amp;gt; &lt;br /&gt;
     &amp;lt;display description=&amp;quot;${bsh:org.ofbiz.party.party.PartyHelper.getPartyName(delegator, partyId, false)} (${partyId})&amp;quot;/&amp;gt;&lt;br /&gt;
   &amp;lt;/field&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In opentaps 1.4, you must change it to:&lt;br /&gt;
&lt;br /&gt;
   &amp;lt;field name=&amp;quot;partyId&amp;quot; title=&amp;quot;${uiLabelMap.ProductSupplier}&amp;quot;&amp;gt; &lt;br /&gt;
     &amp;lt;display description=&amp;quot;${groovy:org.ofbiz.party.party.PartyHelper.getPartyName(delegator, partyId, false)} (${partyId})&amp;quot;/&amp;gt;&lt;br /&gt;
   &amp;lt;/field&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== UEL in Minilang ===&lt;br /&gt;
&lt;br /&gt;
The ofbiz framework now supports unified express language (UEL) in the screen widgets and minilang simple methods.  (See [http://docs.ofbiz.org/display/OFBTECH/Unified+Expression+Language+%28JSR-245%29+in+OFBiz ofbiz wiki])&lt;br /&gt;
&lt;br /&gt;
One side effect is that code in simple methods, for example:&lt;br /&gt;
  someHash.${someVariableAsKey}&lt;br /&gt;
&lt;br /&gt;
In opentaps 1.4, you must change it to:&lt;br /&gt;
  someHash[someVariableAsKey]&lt;br /&gt;
&lt;br /&gt;
=== HTML escaping ===&lt;br /&gt;
&lt;br /&gt;
The ofbiz framework now automatically encodes most of the data displayed on the page. In some cases this is not wanted, and to avoid escaping in form widget use ''encode-output=&amp;quot;false&amp;quot;'' in the field element:&lt;br /&gt;
    &amp;lt;field name=&amp;quot;transactionDate&amp;quot; encode-output=&amp;quot;false&amp;quot;&amp;gt;&amp;lt;date-time/&amp;gt;&amp;lt;/field&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the FTL templates use the ''StringUtil'' class:&lt;br /&gt;
    ${StringUtil.wrapString(someData)}&lt;br /&gt;
&lt;br /&gt;
Some previous helper methods that constructed HTML code will not work anymore. For example ''PartyHelper.createViewPageLink'' has been replaced with the macro:&lt;br /&gt;
    &amp;lt;@displayPartyLink partyId=partyId /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Internationalization and Translations ==&lt;br /&gt;
&lt;br /&gt;
In ofbiz09.04, translations are now in XML format instead of .properties.   However, the old .properties translations are supported still as well.&lt;br /&gt;
&lt;br /&gt;
Furthermore, it is possible to define a component with all your translations, instead of putting them into the various existing components. As an example, &amp;lt;tt&amp;gt;hot-deploy/translations&amp;lt;/tt&amp;gt; in opentaps contains a full set of translations for opentaps to Bulgarian.&lt;br /&gt;
&lt;br /&gt;
== Other Changes ==&lt;br /&gt;
&lt;br /&gt;
In some cases the ''screenlet-title-bar'' used in some ofbiz forms and screens is not wanted, in that case simply wrap the form or screen section in a ''noTitleBar'' div.&lt;br /&gt;
&lt;br /&gt;
For example ''ViewShipmentRouteInfo.ftl'' defines such a title, to hide it we added to the screen definition:&lt;br /&gt;
&lt;br /&gt;
      &amp;lt;container style=&amp;quot;noTitleBar&amp;quot;&amp;gt;&lt;br /&gt;
          &amp;lt;platform-specific&amp;gt;&lt;br /&gt;
              &amp;lt;html&amp;gt;&amp;lt;html-template location=&amp;quot;component://product/webapp/facility/shipment/ViewShipmentRouteInfo.ftl&amp;quot;/&amp;gt;&amp;lt;/html&amp;gt;&lt;br /&gt;
          &amp;lt;/platform-specific&amp;gt;&lt;br /&gt;
      &amp;lt;/container&amp;gt;&lt;/div&gt;</summary>
		<author><name>Spark</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=Upgrading_from_opentaps_1.0_to_opentaps_1.4&amp;diff=5516</id>
		<title>Upgrading from opentaps 1.0 to opentaps 1.4</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=Upgrading_from_opentaps_1.0_to_opentaps_1.4&amp;diff=5516"/>
		<updated>2010-02-09T13:04:14Z</updated>

		<summary type="html">&lt;p&gt;Spark: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
== Data Changes ==&lt;br /&gt;
&lt;br /&gt;
* Run the service &amp;lt;tt&amp;gt;opentaps.setSupplementalDataForAllParties&amp;lt;/tt&amp;gt; to populate primary contact data for all parties.&lt;br /&gt;
* Configuration of GL accounts for invoice writeoffs have been changed.  Instead of using &amp;lt;tt&amp;gt;GlAccountTypeDefault&amp;lt;/tt&amp;gt;, they are now configured with &amp;lt;tt&amp;gt;InvoiceAdjustmentGlAccount&amp;lt;/tt&amp;gt; with the adjustment type &amp;quot;WRITEOFF&amp;quot;&lt;br /&gt;
* If you have custom UI labels, they may be loaded by adding them to &amp;lt;tt&amp;gt;LabelConfiguration.properties&amp;lt;/tt&amp;gt; in &amp;lt;tt&amp;gt;opentaps-common/config/&amp;lt;/tt&amp;gt;&lt;br /&gt;
** If previously you were using &amp;lt;tt&amp;gt;UtilMessage.registerLabelMap()&amp;lt;/tt&amp;gt; to load custom labels, you may now remove all calls to this function as it is no longer needed.&lt;br /&gt;
* Run the upgrade SQL script in hot-deploy/opentaps-common/scripts/sql for the following:&lt;br /&gt;
* (graciousstyle only) Run the upgrade SQL script inhot-deploy/graciousstyle/scripts/sql&lt;br /&gt;
** &amp;lt;tt&amp;gt;ProductAverageCost&amp;lt;/tt&amp;gt; has been re-factored to use a single productAverageCostId as its primary key.  The script will alter the table and automatically fill in its values and update &amp;lt;tt&amp;gt;SequenceValueItem&amp;lt;/tt&amp;gt; so that opentaps will generate correct future keys.&lt;br /&gt;
* Add the following to your custom component's build.xml:&lt;br /&gt;
   &amp;lt;fileset dir=&amp;quot;${ofbiz.dir}/hot-deploy/opentaps-common/lib&amp;quot; includes=&amp;quot;*.jar&amp;quot;/&amp;gt;&lt;br /&gt;
   &amp;lt;fileset dir=&amp;quot;${ofbiz.dir}/hot-deploy/opentaps-common/lib/hibernate&amp;quot; includes=&amp;quot;*.jar&amp;quot;/&amp;gt;&lt;br /&gt;
* Set &amp;lt;tt&amp;gt;SupplierProduct.supplierPrefOrderId&amp;lt;/tt&amp;gt; to '''10_MAIN_SUPPL''' where it is null.&lt;br /&gt;
* Run the following services to set summary fields:&lt;br /&gt;
** &amp;lt;tt&amp;gt;recalcAllEmptyAmountsPayments&amp;lt;/tt&amp;gt;&lt;br /&gt;
** &amp;lt;tt&amp;gt;recalcAllEmptyAmountsInvoices&amp;lt;/tt&amp;gt;&lt;br /&gt;
** &amp;lt;tt&amp;gt;updatePostedAmountAcctgTrans&amp;lt;/tt&amp;gt;&lt;br /&gt;
** &amp;lt;tt&amp;gt;(graciousstyle only) opentaps.convertOfbizParties&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Run the following SQL query to set Invoice.paidDate:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
update INVOICE i set PAID_DATE = (&lt;br /&gt;
 select paidDate from&lt;br /&gt;
 (&lt;br /&gt;
 select max(EFFECTIVE_DATE) paidDate, b.INVOICE_ID from PAYMENT a inner&lt;br /&gt;
 join PAYMENT_APPLICATION b on a.PAYMENT_ID=b.PAYMENT_ID group by&lt;br /&gt;
 b.INVOICE_ID&lt;br /&gt;
 ) p where p.INVOICE_ID = i.INVOICE_ID and i.STATUS_ID='INVOICE_PAID'&lt;br /&gt;
 );&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Run the ant import ext seed in command window: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 ant run-install-extseed&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== Coding Changes ==&lt;br /&gt;
&lt;br /&gt;
Changes in the ofbiz framework would require the following changes to your code:&lt;br /&gt;
&lt;br /&gt;
=== URL Parameter Security ===&lt;br /&gt;
&lt;br /&gt;
You can no longer pass parameters to a service request directly in the URL.  These requests must be part of a POST form.  To make buttons work as before, you need to change them to forms and then activate them with javascript.  For example, in earlier versions, you could have a button to delete a lead like this:&lt;br /&gt;
  &amp;lt;#assign update_options = update_options + &amp;quot;&amp;lt;a class='subMenuButtonDangerous' &lt;br /&gt;
           href='deleteLead?leadPartyId=&amp;quot; + partySummary.partyId + &amp;quot;'&amp;gt;&amp;quot; + uiLabelMap.CommonDelete + &amp;quot;&amp;lt;/a&amp;gt;&amp;quot;  /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In opentaps 1.4, you must do it this way:&lt;br /&gt;
   &amp;lt;form name=&amp;quot;deleteLeadForm&amp;quot; method=&amp;quot;post&amp;quot; action=&amp;quot;&amp;lt;@ofbizUrl&amp;gt;deleteLead&amp;lt;/@ofbizUrl&amp;gt;&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;@inputHidden name=&amp;quot;leadPartyId&amp;quot; value=&amp;quot;${partySummary.partyId}&amp;quot;/&amp;gt;&lt;br /&gt;
   &amp;lt;/form&amp;gt;&lt;br /&gt;
   &amp;lt;#assign update_options = update_options + &amp;quot;&amp;lt;a class='subMenuButtonDangerous' &lt;br /&gt;
            href='javascript:document.deleteLeadForm.submit()'&amp;gt;&amp;quot; + uiLabelMap.CommonDelete + &amp;quot;&amp;lt;/a&amp;gt;&amp;quot;  /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For your convenience, there is also a new macro to do this (see ''form'' and ''submitFormLink'' in opentapsFormMacro.ftl):&lt;br /&gt;
   &amp;lt;@form name=&amp;quot;deleteLeadForm&amp;quot; url=&amp;quot;deleteLead&amp;quot; leadPartyId=partySummary.partyId /&amp;gt;&lt;br /&gt;
   &amp;lt;#assign update_options&amp;gt;${update_options}&amp;lt;@submitFormLink form=&amp;quot;deleteLeadForm&amp;quot; text=uiLabelMap.CommonDelete class=&amp;quot;subMenuButtonDangerous&amp;quot; /&amp;gt;&amp;lt;/#assign&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The ''form'' macro makes hidden inputs for all parameters (except ''name'', ''url'' and ''method'' that are used to define the form element itself), and also accept nested elements for more complex cases.&lt;br /&gt;
&lt;br /&gt;
For the cases where a form has to be used for multiple items, for example when you have an Update form block which must include multiple remove links, instead of writing a JavaScript handler which passes the item Ids to the form before submitting, you can do:&lt;br /&gt;
&lt;br /&gt;
   &amp;lt;@form name=&amp;quot;removeReturnItemAction&amp;quot; url=&amp;quot;removeReturnItem&amp;quot; returnId=returnId returnItemSeqId=&amp;quot;&amp;quot; /&amp;gt;&lt;br /&gt;
   &amp;lt;@form name=&amp;quot;updateReturnItemsAction&amp;quot; url=&amp;quot;updateReturnItems&amp;quot; returnId=returnId&amp;gt;&lt;br /&gt;
     &amp;lt;#list returnItems as item&amp;gt;&lt;br /&gt;
       &amp;lt;!-- some editable fields for the updateReturnItems form --&amp;gt;&lt;br /&gt;
      &amp;lt;@submitFormLinkConfirm form=&amp;quot;removeReturnItemAction&amp;quot; text=uiLabelMap.CommonRemove returnItemSeqId=item.returnItemSeqId /&amp;gt;&lt;br /&gt;
     &amp;lt;/#list&amp;gt;&lt;br /&gt;
   &amp;lt;/@form&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Also the new ''selectActionForm'' and ''actionForm'' can be used with ''form'' to define a drop-down menu where when an item (''actionForm'') is selected it submits the corresponding ''form'':&lt;br /&gt;
   &amp;lt;@form name=&amp;quot;deleteLeadForm&amp;quot; url=&amp;quot;deleteLead&amp;quot; leadPartyId=partySummary.partyId /&amp;gt;&lt;br /&gt;
   &amp;lt;@form ... /&amp;gt;&lt;br /&gt;
   &amp;lt;@selectActionForm name=&amp;quot;leadActions&amp;quot; prompt=&amp;quot;${uiLabelMap.CommonSelectOne}&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;@actionForm form=&amp;quot;deleteLeadForm&amp;quot; text=&amp;quot;${uiLabelMap.CommonDelete}&amp;quot;/&amp;gt;&lt;br /&gt;
     &amp;lt;@actionForm .../&amp;gt;&lt;br /&gt;
   &amp;lt;@selectAction/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Service and HTML inputs ===&lt;br /&gt;
&lt;br /&gt;
As a security feature, the services will filter any input with HTML by default. Some services still require HTML (like emails or templates services) and to allow that there is a new ''allow-html'' parameter. For example:&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;attribute name=&amp;quot;content&amp;quot; type=&amp;quot;String&amp;quot; mode=&amp;quot;IN&amp;quot; optional=&amp;quot;false&amp;quot; allow-html=&amp;quot;safe&amp;quot;/&amp;gt;&lt;br /&gt;
     &amp;lt;override name=&amp;quot;mergeFormText&amp;quot; allow-html=&amp;quot;safe&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Form Widget Changes ===&lt;br /&gt;
&lt;br /&gt;
Form widget URL parameters should be specified with &amp;lt;tt&amp;gt;parameter&amp;lt;/tt&amp;gt; tag now, instead of in the URL:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-            &amp;lt;hyperlink description=&amp;quot;${contactListName} (${contactListId})&amp;quot; target=&amp;quot;viewContactList?contactListId=${contactListId}&amp;quot;&amp;gt;&lt;br /&gt;
+            &amp;lt;hyperlink description=&amp;quot;${contactListName} (${contactListId})&amp;quot; target=&amp;quot;viewContactList&amp;quot;&amp;gt;&lt;br /&gt;
+                &amp;lt;parameter param-name=&amp;quot;contactListId&amp;quot; from-field=&amp;quot;contactListId&amp;quot;/&amp;gt;&lt;br /&gt;
             &amp;lt;/hyperlink&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Do not have it both in the URL and as a &amp;lt;tt&amp;gt;parameter&amp;lt;/tt&amp;gt;, or the parameter will be on the form twice and be passed incorrectly.&lt;br /&gt;
&lt;br /&gt;
=== Controller redirects ===&lt;br /&gt;
&lt;br /&gt;
Redirects have been changed, now ''request-redirect'' will only copy the parameters that were in the URL string by default. To forward posted or service output parameter, use the ''redirect-parameter'' elements (one per parameter).&lt;br /&gt;
   &amp;lt;response name=&amp;quot;success&amp;quot; type=&amp;quot;request-redirect&amp;quot; value=&amp;quot;viewAccount&amp;quot;&amp;gt;&lt;br /&gt;
       &amp;lt;redirect-parameter name=&amp;quot;partyId&amp;quot;/&amp;gt;&lt;br /&gt;
   &amp;lt;/response&amp;gt;&lt;br /&gt;
Also ''request-redirect-filter-param'' is now considered deprecated.&lt;br /&gt;
&lt;br /&gt;
=== Js dateTime format ===&lt;br /&gt;
&lt;br /&gt;
Js dataTime format in ftl have been changed, now the format will return html encode string which will cause the parse exception, you should use StringUtil.wrapString to avoid this issue. For example, in earlier versions, you could have define a js dataTime format variable like this:&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;#assign dateFormat = Static[&amp;quot;org.opentaps.common.util.UtilDate&amp;quot;].getJsDateTimeFormat(Static[&amp;quot;org.opentaps.common.util.UtilDate&amp;quot;].getDateFormat(locale))/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In opentaps 1.4, you must do it this way:&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;#assign dateFormat = StringUtil.wrapString(Static[&amp;quot;org.opentaps.common.util.UtilDate&amp;quot;].getJsDateTimeFormat(Static[&amp;quot;org.opentaps.common.util.UtilDate&amp;quot;].getDateFormat(locale)))/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== BSH embedded in Forms ===&lt;br /&gt;
&lt;br /&gt;
In Forms widgets you could embed bsh code in order to have more flexibility over the formatting. Those embedded scripts need to be changed to groovy to avoid classpath issues. Fortunately this is as simple as changing the ''${bsh:'' to ''${groovy:''&lt;br /&gt;
&lt;br /&gt;
For example, in earlier versions, you could transform a party Id into the whole party name:&lt;br /&gt;
&lt;br /&gt;
   &amp;lt;field name=&amp;quot;partyId&amp;quot; title=&amp;quot;${uiLabelMap.ProductSupplier}&amp;quot;&amp;gt; &lt;br /&gt;
     &amp;lt;display description=&amp;quot;${bsh:org.ofbiz.party.party.PartyHelper.getPartyName(delegator, partyId, false)} (${partyId})&amp;quot;/&amp;gt;&lt;br /&gt;
   &amp;lt;/field&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In opentaps 1.4, you must change it to:&lt;br /&gt;
&lt;br /&gt;
   &amp;lt;field name=&amp;quot;partyId&amp;quot; title=&amp;quot;${uiLabelMap.ProductSupplier}&amp;quot;&amp;gt; &lt;br /&gt;
     &amp;lt;display description=&amp;quot;${groovy:org.ofbiz.party.party.PartyHelper.getPartyName(delegator, partyId, false)} (${partyId})&amp;quot;/&amp;gt;&lt;br /&gt;
   &amp;lt;/field&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== UEL in Minilang ===&lt;br /&gt;
&lt;br /&gt;
The ofbiz framework now supports unified express language (UEL) in the screen widgets and minilang simple methods.  (See [http://docs.ofbiz.org/display/OFBTECH/Unified+Expression+Language+%28JSR-245%29+in+OFBiz ofbiz wiki])&lt;br /&gt;
&lt;br /&gt;
One side effect is that code in simple methods, for example:&lt;br /&gt;
  someHash.${someVariableAsKey}&lt;br /&gt;
&lt;br /&gt;
In opentaps 1.4, you must change it to:&lt;br /&gt;
  someHash[someVariableAsKey]&lt;br /&gt;
&lt;br /&gt;
=== HTML escaping ===&lt;br /&gt;
&lt;br /&gt;
The ofbiz framework now automatically encodes most of the data displayed on the page. In some cases this is not wanted, and to avoid escaping in form widget use ''encode-output=&amp;quot;false&amp;quot;'' in the field element:&lt;br /&gt;
    &amp;lt;field name=&amp;quot;transactionDate&amp;quot; encode-output=&amp;quot;false&amp;quot;&amp;gt;&amp;lt;date-time/&amp;gt;&amp;lt;/field&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the FTL templates use the ''StringUtil'' class:&lt;br /&gt;
    ${StringUtil.wrapString(someData)}&lt;br /&gt;
&lt;br /&gt;
Some previous helper methods that constructed HTML code will not work anymore. For example ''PartyHelper.createViewPageLink'' has been replaced with the macro:&lt;br /&gt;
    &amp;lt;@displayPartyLink partyId=partyId /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Internationalization and Translations ==&lt;br /&gt;
&lt;br /&gt;
In ofbiz09.04, translations are now in XML format instead of .properties.   However, the old .properties translations are supported still as well.&lt;br /&gt;
&lt;br /&gt;
Furthermore, it is possible to define a component with all your translations, instead of putting them into the various existing components. As an example, &amp;lt;tt&amp;gt;hot-deploy/translations&amp;lt;/tt&amp;gt; in opentaps contains a full set of translations for opentaps to Bulgarian.&lt;br /&gt;
&lt;br /&gt;
== Other Changes ==&lt;br /&gt;
&lt;br /&gt;
In some cases the ''screenlet-title-bar'' used in some ofbiz forms and screens is not wanted, in that case simply wrap the form or screen section in a ''noTitleBar'' div.&lt;br /&gt;
&lt;br /&gt;
For example ''ViewShipmentRouteInfo.ftl'' defines such a title, to hide it we added to the screen definition:&lt;br /&gt;
&lt;br /&gt;
      &amp;lt;container style=&amp;quot;noTitleBar&amp;quot;&amp;gt;&lt;br /&gt;
          &amp;lt;platform-specific&amp;gt;&lt;br /&gt;
              &amp;lt;html&amp;gt;&amp;lt;html-template location=&amp;quot;component://product/webapp/facility/shipment/ViewShipmentRouteInfo.ftl&amp;quot;/&amp;gt;&amp;lt;/html&amp;gt;&lt;br /&gt;
          &amp;lt;/platform-specific&amp;gt;&lt;br /&gt;
      &amp;lt;/container&amp;gt;&lt;/div&gt;</summary>
		<author><name>Spark</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=Upgrading_from_opentaps_1.0_to_opentaps_1.4&amp;diff=5515</id>
		<title>Upgrading from opentaps 1.0 to opentaps 1.4</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=Upgrading_from_opentaps_1.0_to_opentaps_1.4&amp;diff=5515"/>
		<updated>2010-02-09T11:17:32Z</updated>

		<summary type="html">&lt;p&gt;Spark: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
== Data Changes ==&lt;br /&gt;
&lt;br /&gt;
* Run the service &amp;lt;tt&amp;gt;opentaps.setSupplementalDataForAllParties&amp;lt;/tt&amp;gt; to populate primary contact data for all parties.&lt;br /&gt;
* Configuration of GL accounts for invoice writeoffs have been changed.  Instead of using &amp;lt;tt&amp;gt;GlAccountTypeDefault&amp;lt;/tt&amp;gt;, they are now configured with &amp;lt;tt&amp;gt;InvoiceAdjustmentGlAccount&amp;lt;/tt&amp;gt; with the adjustment type &amp;quot;WRITEOFF&amp;quot;&lt;br /&gt;
* If you have custom UI labels, they may be loaded by adding them to &amp;lt;tt&amp;gt;LabelConfiguration.properties&amp;lt;/tt&amp;gt; in &amp;lt;tt&amp;gt;opentaps-common/config/&amp;lt;/tt&amp;gt;&lt;br /&gt;
** If previously you were using &amp;lt;tt&amp;gt;UtilMessage.registerLabelMap()&amp;lt;/tt&amp;gt; to load custom labels, you may now remove all calls to this function as it is no longer needed.&lt;br /&gt;
* Run the upgrade SQL script in hot-deploy/opentaps-common/scripts/sql for the following:&lt;br /&gt;
** &amp;lt;tt&amp;gt;ProductAverageCost&amp;lt;/tt&amp;gt; has been re-factored to use a single productAverageCostId as its primary key.  The script will alter the table and automatically fill in its values and update &amp;lt;tt&amp;gt;SequenceValueItem&amp;lt;/tt&amp;gt; so that opentaps will generate correct future keys.&lt;br /&gt;
* Add the following to your custom component's build.xml:&lt;br /&gt;
   &amp;lt;fileset dir=&amp;quot;${ofbiz.dir}/hot-deploy/opentaps-common/lib&amp;quot; includes=&amp;quot;*.jar&amp;quot;/&amp;gt;&lt;br /&gt;
   &amp;lt;fileset dir=&amp;quot;${ofbiz.dir}/hot-deploy/opentaps-common/lib/hibernate&amp;quot; includes=&amp;quot;*.jar&amp;quot;/&amp;gt;&lt;br /&gt;
* Set &amp;lt;tt&amp;gt;SupplierProduct.supplierPrefOrderId&amp;lt;/tt&amp;gt; to '''10_MAIN_SUPPL''' where it is null.&lt;br /&gt;
* Run the following services to set summary fields:&lt;br /&gt;
** &amp;lt;tt&amp;gt;recalcAllEmptyAmountsPayments&amp;lt;/tt&amp;gt;&lt;br /&gt;
** &amp;lt;tt&amp;gt;recalcAllEmptyAmountsInvoices&amp;lt;/tt&amp;gt;&lt;br /&gt;
** &amp;lt;tt&amp;gt;updatePostedAmountAcctgTrans&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Run the following SQL query to set Invoice.paidDate:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
update INVOICE i set PAID_DATE = (&lt;br /&gt;
 select paidDate from&lt;br /&gt;
 (&lt;br /&gt;
 select max(EFFECTIVE_DATE) paidDate, b.INVOICE_ID from PAYMENT a inner&lt;br /&gt;
 join PAYMENT_APPLICATION b on a.PAYMENT_ID=b.PAYMENT_ID group by&lt;br /&gt;
 b.INVOICE_ID&lt;br /&gt;
 ) p where p.INVOICE_ID = i.INVOICE_ID and i.STATUS_ID='INVOICE_PAID'&lt;br /&gt;
 );&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Run the ant import ext seed in command window: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 ant run-install-extseed&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== Coding Changes ==&lt;br /&gt;
&lt;br /&gt;
Changes in the ofbiz framework would require the following changes to your code:&lt;br /&gt;
&lt;br /&gt;
=== URL Parameter Security ===&lt;br /&gt;
&lt;br /&gt;
You can no longer pass parameters to a service request directly in the URL.  These requests must be part of a POST form.  To make buttons work as before, you need to change them to forms and then activate them with javascript.  For example, in earlier versions, you could have a button to delete a lead like this:&lt;br /&gt;
  &amp;lt;#assign update_options = update_options + &amp;quot;&amp;lt;a class='subMenuButtonDangerous' &lt;br /&gt;
           href='deleteLead?leadPartyId=&amp;quot; + partySummary.partyId + &amp;quot;'&amp;gt;&amp;quot; + uiLabelMap.CommonDelete + &amp;quot;&amp;lt;/a&amp;gt;&amp;quot;  /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In opentaps 1.4, you must do it this way:&lt;br /&gt;
   &amp;lt;form name=&amp;quot;deleteLeadForm&amp;quot; method=&amp;quot;post&amp;quot; action=&amp;quot;&amp;lt;@ofbizUrl&amp;gt;deleteLead&amp;lt;/@ofbizUrl&amp;gt;&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;@inputHidden name=&amp;quot;leadPartyId&amp;quot; value=&amp;quot;${partySummary.partyId}&amp;quot;/&amp;gt;&lt;br /&gt;
   &amp;lt;/form&amp;gt;&lt;br /&gt;
   &amp;lt;#assign update_options = update_options + &amp;quot;&amp;lt;a class='subMenuButtonDangerous' &lt;br /&gt;
            href='javascript:document.deleteLeadForm.submit()'&amp;gt;&amp;quot; + uiLabelMap.CommonDelete + &amp;quot;&amp;lt;/a&amp;gt;&amp;quot;  /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For your convenience, there is also a new macro to do this (see ''form'' and ''submitFormLink'' in opentapsFormMacro.ftl):&lt;br /&gt;
   &amp;lt;@form name=&amp;quot;deleteLeadForm&amp;quot; url=&amp;quot;deleteLead&amp;quot; leadPartyId=partySummary.partyId /&amp;gt;&lt;br /&gt;
   &amp;lt;#assign update_options&amp;gt;${update_options}&amp;lt;@submitFormLink form=&amp;quot;deleteLeadForm&amp;quot; text=uiLabelMap.CommonDelete class=&amp;quot;subMenuButtonDangerous&amp;quot; /&amp;gt;&amp;lt;/#assign&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The ''form'' macro makes hidden inputs for all parameters (except ''name'', ''url'' and ''method'' that are used to define the form element itself), and also accept nested elements for more complex cases.&lt;br /&gt;
&lt;br /&gt;
For the cases where a form has to be used for multiple items, for example when you have an Update form block which must include multiple remove links, instead of writing a JavaScript handler which passes the item Ids to the form before submitting, you can do:&lt;br /&gt;
&lt;br /&gt;
   &amp;lt;@form name=&amp;quot;removeReturnItemAction&amp;quot; url=&amp;quot;removeReturnItem&amp;quot; returnId=returnId returnItemSeqId=&amp;quot;&amp;quot; /&amp;gt;&lt;br /&gt;
   &amp;lt;@form name=&amp;quot;updateReturnItemsAction&amp;quot; url=&amp;quot;updateReturnItems&amp;quot; returnId=returnId&amp;gt;&lt;br /&gt;
     &amp;lt;#list returnItems as item&amp;gt;&lt;br /&gt;
       &amp;lt;!-- some editable fields for the updateReturnItems form --&amp;gt;&lt;br /&gt;
      &amp;lt;@submitFormLinkConfirm form=&amp;quot;removeReturnItemAction&amp;quot; text=uiLabelMap.CommonRemove returnItemSeqId=item.returnItemSeqId /&amp;gt;&lt;br /&gt;
     &amp;lt;/#list&amp;gt;&lt;br /&gt;
   &amp;lt;/@form&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Also the new ''selectActionForm'' and ''actionForm'' can be used with ''form'' to define a drop-down menu where when an item (''actionForm'') is selected it submits the corresponding ''form'':&lt;br /&gt;
   &amp;lt;@form name=&amp;quot;deleteLeadForm&amp;quot; url=&amp;quot;deleteLead&amp;quot; leadPartyId=partySummary.partyId /&amp;gt;&lt;br /&gt;
   &amp;lt;@form ... /&amp;gt;&lt;br /&gt;
   &amp;lt;@selectActionForm name=&amp;quot;leadActions&amp;quot; prompt=&amp;quot;${uiLabelMap.CommonSelectOne}&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;@actionForm form=&amp;quot;deleteLeadForm&amp;quot; text=&amp;quot;${uiLabelMap.CommonDelete}&amp;quot;/&amp;gt;&lt;br /&gt;
     &amp;lt;@actionForm .../&amp;gt;&lt;br /&gt;
   &amp;lt;@selectAction/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Service and HTML inputs ===&lt;br /&gt;
&lt;br /&gt;
As a security feature, the services will filter any input with HTML by default. Some services still require HTML (like emails or templates services) and to allow that there is a new ''allow-html'' parameter. For example:&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;attribute name=&amp;quot;content&amp;quot; type=&amp;quot;String&amp;quot; mode=&amp;quot;IN&amp;quot; optional=&amp;quot;false&amp;quot; allow-html=&amp;quot;safe&amp;quot;/&amp;gt;&lt;br /&gt;
     &amp;lt;override name=&amp;quot;mergeFormText&amp;quot; allow-html=&amp;quot;safe&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Form Widget Changes ===&lt;br /&gt;
&lt;br /&gt;
Form widget URL parameters should be specified with &amp;lt;tt&amp;gt;parameter&amp;lt;/tt&amp;gt; tag now, instead of in the URL:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-            &amp;lt;hyperlink description=&amp;quot;${contactListName} (${contactListId})&amp;quot; target=&amp;quot;viewContactList?contactListId=${contactListId}&amp;quot;&amp;gt;&lt;br /&gt;
+            &amp;lt;hyperlink description=&amp;quot;${contactListName} (${contactListId})&amp;quot; target=&amp;quot;viewContactList&amp;quot;&amp;gt;&lt;br /&gt;
+                &amp;lt;parameter param-name=&amp;quot;contactListId&amp;quot; from-field=&amp;quot;contactListId&amp;quot;/&amp;gt;&lt;br /&gt;
             &amp;lt;/hyperlink&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Do not have it both in the URL and as a &amp;lt;tt&amp;gt;parameter&amp;lt;/tt&amp;gt;, or the parameter will be on the form twice and be passed incorrectly.&lt;br /&gt;
&lt;br /&gt;
=== Controller redirects ===&lt;br /&gt;
&lt;br /&gt;
Redirects have been changed, now ''request-redirect'' will only copy the parameters that were in the URL string by default. To forward posted or service output parameter, use the ''redirect-parameter'' elements (one per parameter).&lt;br /&gt;
   &amp;lt;response name=&amp;quot;success&amp;quot; type=&amp;quot;request-redirect&amp;quot; value=&amp;quot;viewAccount&amp;quot;&amp;gt;&lt;br /&gt;
       &amp;lt;redirect-parameter name=&amp;quot;partyId&amp;quot;/&amp;gt;&lt;br /&gt;
   &amp;lt;/response&amp;gt;&lt;br /&gt;
Also ''request-redirect-filter-param'' is now considered deprecated.&lt;br /&gt;
&lt;br /&gt;
=== Js dateTime format ===&lt;br /&gt;
&lt;br /&gt;
Js dataTime format in ftl have been changed, now the format will return html encode string which will cause the parse exception, you should use StringUtil.wrapString to avoid this issue. For example, in earlier versions, you could have define a js dataTime format variable like this:&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;#assign dateFormat = Static[&amp;quot;org.opentaps.common.util.UtilDate&amp;quot;].getJsDateTimeFormat(Static[&amp;quot;org.opentaps.common.util.UtilDate&amp;quot;].getDateFormat(locale))/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In opentaps 1.4, you must do it this way:&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;#assign dateFormat = StringUtil.wrapString(Static[&amp;quot;org.opentaps.common.util.UtilDate&amp;quot;].getJsDateTimeFormat(Static[&amp;quot;org.opentaps.common.util.UtilDate&amp;quot;].getDateFormat(locale)))/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== BSH embedded in Forms ===&lt;br /&gt;
&lt;br /&gt;
In Forms widgets you could embed bsh code in order to have more flexibility over the formatting. Those embedded scripts need to be changed to groovy to avoid classpath issues. Fortunately this is as simple as changing the ''${bsh:'' to ''${groovy:''&lt;br /&gt;
&lt;br /&gt;
For example, in earlier versions, you could transform a party Id into the whole party name:&lt;br /&gt;
&lt;br /&gt;
   &amp;lt;field name=&amp;quot;partyId&amp;quot; title=&amp;quot;${uiLabelMap.ProductSupplier}&amp;quot;&amp;gt; &lt;br /&gt;
     &amp;lt;display description=&amp;quot;${bsh:org.ofbiz.party.party.PartyHelper.getPartyName(delegator, partyId, false)} (${partyId})&amp;quot;/&amp;gt;&lt;br /&gt;
   &amp;lt;/field&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In opentaps 1.4, you must change it to:&lt;br /&gt;
&lt;br /&gt;
   &amp;lt;field name=&amp;quot;partyId&amp;quot; title=&amp;quot;${uiLabelMap.ProductSupplier}&amp;quot;&amp;gt; &lt;br /&gt;
     &amp;lt;display description=&amp;quot;${groovy:org.ofbiz.party.party.PartyHelper.getPartyName(delegator, partyId, false)} (${partyId})&amp;quot;/&amp;gt;&lt;br /&gt;
   &amp;lt;/field&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== UEL in Minilang ===&lt;br /&gt;
&lt;br /&gt;
The ofbiz framework now supports unified express language (UEL) in the screen widgets and minilang simple methods.  (See [http://docs.ofbiz.org/display/OFBTECH/Unified+Expression+Language+%28JSR-245%29+in+OFBiz ofbiz wiki])&lt;br /&gt;
&lt;br /&gt;
One side effect is that code in simple methods, for example:&lt;br /&gt;
  someHash.${someVariableAsKey}&lt;br /&gt;
&lt;br /&gt;
In opentaps 1.4, you must change it to:&lt;br /&gt;
  someHash[someVariableAsKey]&lt;br /&gt;
&lt;br /&gt;
=== HTML escaping ===&lt;br /&gt;
&lt;br /&gt;
The ofbiz framework now automatically encodes most of the data displayed on the page. In some cases this is not wanted, and to avoid escaping in form widget use ''encode-output=&amp;quot;false&amp;quot;'' in the field element:&lt;br /&gt;
    &amp;lt;field name=&amp;quot;transactionDate&amp;quot; encode-output=&amp;quot;false&amp;quot;&amp;gt;&amp;lt;date-time/&amp;gt;&amp;lt;/field&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the FTL templates use the ''StringUtil'' class:&lt;br /&gt;
    ${StringUtil.wrapString(someData)}&lt;br /&gt;
&lt;br /&gt;
Some previous helper methods that constructed HTML code will not work anymore. For example ''PartyHelper.createViewPageLink'' has been replaced with the macro:&lt;br /&gt;
    &amp;lt;@displayPartyLink partyId=partyId /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Internationalization and Translations ==&lt;br /&gt;
&lt;br /&gt;
In ofbiz09.04, translations are now in XML format instead of .properties.   However, the old .properties translations are supported still as well.&lt;br /&gt;
&lt;br /&gt;
Furthermore, it is possible to define a component with all your translations, instead of putting them into the various existing components. As an example, &amp;lt;tt&amp;gt;hot-deploy/translations&amp;lt;/tt&amp;gt; in opentaps contains a full set of translations for opentaps to Bulgarian.&lt;br /&gt;
&lt;br /&gt;
== Other Changes ==&lt;br /&gt;
&lt;br /&gt;
In some cases the ''screenlet-title-bar'' used in some ofbiz forms and screens is not wanted, in that case simply wrap the form or screen section in a ''noTitleBar'' div.&lt;br /&gt;
&lt;br /&gt;
For example ''ViewShipmentRouteInfo.ftl'' defines such a title, to hide it we added to the screen definition:&lt;br /&gt;
&lt;br /&gt;
      &amp;lt;container style=&amp;quot;noTitleBar&amp;quot;&amp;gt;&lt;br /&gt;
          &amp;lt;platform-specific&amp;gt;&lt;br /&gt;
              &amp;lt;html&amp;gt;&amp;lt;html-template location=&amp;quot;component://product/webapp/facility/shipment/ViewShipmentRouteInfo.ftl&amp;quot;/&amp;gt;&amp;lt;/html&amp;gt;&lt;br /&gt;
          &amp;lt;/platform-specific&amp;gt;&lt;br /&gt;
      &amp;lt;/container&amp;gt;&lt;/div&gt;</summary>
		<author><name>Spark</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=Upgrading_from_opentaps_1.0_to_opentaps_1.4&amp;diff=5514</id>
		<title>Upgrading from opentaps 1.0 to opentaps 1.4</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=Upgrading_from_opentaps_1.0_to_opentaps_1.4&amp;diff=5514"/>
		<updated>2010-02-09T11:16:29Z</updated>

		<summary type="html">&lt;p&gt;Spark: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
== Data Changes ==&lt;br /&gt;
&lt;br /&gt;
* Run the service &amp;lt;tt&amp;gt;opentaps.setSupplementalDataForAllParties&amp;lt;/tt&amp;gt; to populate primary contact data for all parties.&lt;br /&gt;
* Configuration of GL accounts for invoice writeoffs have been changed.  Instead of using &amp;lt;tt&amp;gt;GlAccountTypeDefault&amp;lt;/tt&amp;gt;, they are now configured with &amp;lt;tt&amp;gt;InvoiceAdjustmentGlAccount&amp;lt;/tt&amp;gt; with the adjustment type &amp;quot;WRITEOFF&amp;quot;&lt;br /&gt;
* If you have custom UI labels, they may be loaded by adding them to &amp;lt;tt&amp;gt;LabelConfiguration.properties&amp;lt;/tt&amp;gt; in &amp;lt;tt&amp;gt;opentaps-common/config/&amp;lt;/tt&amp;gt;&lt;br /&gt;
** If previously you were using &amp;lt;tt&amp;gt;UtilMessage.registerLabelMap()&amp;lt;/tt&amp;gt; to load custom labels, you may now remove all calls to this function as it is no longer needed.&lt;br /&gt;
* Run the upgrade SQL script in hot-deploy/opentaps-common/scripts/sql for the following:&lt;br /&gt;
** &amp;lt;tt&amp;gt;ProductAverageCost&amp;lt;/tt&amp;gt; has been re-factored to use a single productAverageCostId as its primary key.  The script will alter the table and automatically fill in its values and update &amp;lt;tt&amp;gt;SequenceValueItem&amp;lt;/tt&amp;gt; so that opentaps will generate correct future keys.&lt;br /&gt;
* Add the following to your custom component's build.xml:&lt;br /&gt;
   &amp;lt;fileset dir=&amp;quot;${ofbiz.dir}/hot-deploy/opentaps-common/lib&amp;quot; includes=&amp;quot;*.jar&amp;quot;/&amp;gt;&lt;br /&gt;
   &amp;lt;fileset dir=&amp;quot;${ofbiz.dir}/hot-deploy/opentaps-common/lib/hibernate&amp;quot; includes=&amp;quot;*.jar&amp;quot;/&amp;gt;&lt;br /&gt;
* Set &amp;lt;tt&amp;gt;SupplierProduct.supplierPrefOrderId&amp;lt;/tt&amp;gt; to '''10_MAIN_SUPPL''' where it is null.&lt;br /&gt;
* Run the following services to set summary fields:&lt;br /&gt;
** &amp;lt;tt&amp;gt;recalcAllEmptyAmountsPayments&amp;lt;/tt&amp;gt;&lt;br /&gt;
** &amp;lt;tt&amp;gt;recalcAllEmptyAmountsInvoices&amp;lt;/tt&amp;gt;&lt;br /&gt;
** &amp;lt;tt&amp;gt;updatePostedAmountAcctgTrans&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Run the following SQL query to set Invoice.paidDate:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
update INVOICE i set PAID_DATE = (&lt;br /&gt;
 select paidDate from&lt;br /&gt;
 (&lt;br /&gt;
 select max(EFFECTIVE_DATE) paidDate, b.INVOICE_ID from PAYMENT a inner&lt;br /&gt;
 join PAYMENT_APPLICATION b on a.PAYMENT_ID=b.PAYMENT_ID group by&lt;br /&gt;
 b.INVOICE_ID&lt;br /&gt;
 ) p where p.INVOICE_ID = i.INVOICE_ID and i.STATUS_ID='INVOICE_PAID'&lt;br /&gt;
 );&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Run the ant import ext seed in command window: &lt;br /&gt;
ant run-install-extseed&lt;br /&gt;
&lt;br /&gt;
== Coding Changes ==&lt;br /&gt;
&lt;br /&gt;
Changes in the ofbiz framework would require the following changes to your code:&lt;br /&gt;
&lt;br /&gt;
=== URL Parameter Security ===&lt;br /&gt;
&lt;br /&gt;
You can no longer pass parameters to a service request directly in the URL.  These requests must be part of a POST form.  To make buttons work as before, you need to change them to forms and then activate them with javascript.  For example, in earlier versions, you could have a button to delete a lead like this:&lt;br /&gt;
  &amp;lt;#assign update_options = update_options + &amp;quot;&amp;lt;a class='subMenuButtonDangerous' &lt;br /&gt;
           href='deleteLead?leadPartyId=&amp;quot; + partySummary.partyId + &amp;quot;'&amp;gt;&amp;quot; + uiLabelMap.CommonDelete + &amp;quot;&amp;lt;/a&amp;gt;&amp;quot;  /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In opentaps 1.4, you must do it this way:&lt;br /&gt;
   &amp;lt;form name=&amp;quot;deleteLeadForm&amp;quot; method=&amp;quot;post&amp;quot; action=&amp;quot;&amp;lt;@ofbizUrl&amp;gt;deleteLead&amp;lt;/@ofbizUrl&amp;gt;&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;@inputHidden name=&amp;quot;leadPartyId&amp;quot; value=&amp;quot;${partySummary.partyId}&amp;quot;/&amp;gt;&lt;br /&gt;
   &amp;lt;/form&amp;gt;&lt;br /&gt;
   &amp;lt;#assign update_options = update_options + &amp;quot;&amp;lt;a class='subMenuButtonDangerous' &lt;br /&gt;
            href='javascript:document.deleteLeadForm.submit()'&amp;gt;&amp;quot; + uiLabelMap.CommonDelete + &amp;quot;&amp;lt;/a&amp;gt;&amp;quot;  /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For your convenience, there is also a new macro to do this (see ''form'' and ''submitFormLink'' in opentapsFormMacro.ftl):&lt;br /&gt;
   &amp;lt;@form name=&amp;quot;deleteLeadForm&amp;quot; url=&amp;quot;deleteLead&amp;quot; leadPartyId=partySummary.partyId /&amp;gt;&lt;br /&gt;
   &amp;lt;#assign update_options&amp;gt;${update_options}&amp;lt;@submitFormLink form=&amp;quot;deleteLeadForm&amp;quot; text=uiLabelMap.CommonDelete class=&amp;quot;subMenuButtonDangerous&amp;quot; /&amp;gt;&amp;lt;/#assign&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The ''form'' macro makes hidden inputs for all parameters (except ''name'', ''url'' and ''method'' that are used to define the form element itself), and also accept nested elements for more complex cases.&lt;br /&gt;
&lt;br /&gt;
For the cases where a form has to be used for multiple items, for example when you have an Update form block which must include multiple remove links, instead of writing a JavaScript handler which passes the item Ids to the form before submitting, you can do:&lt;br /&gt;
&lt;br /&gt;
   &amp;lt;@form name=&amp;quot;removeReturnItemAction&amp;quot; url=&amp;quot;removeReturnItem&amp;quot; returnId=returnId returnItemSeqId=&amp;quot;&amp;quot; /&amp;gt;&lt;br /&gt;
   &amp;lt;@form name=&amp;quot;updateReturnItemsAction&amp;quot; url=&amp;quot;updateReturnItems&amp;quot; returnId=returnId&amp;gt;&lt;br /&gt;
     &amp;lt;#list returnItems as item&amp;gt;&lt;br /&gt;
       &amp;lt;!-- some editable fields for the updateReturnItems form --&amp;gt;&lt;br /&gt;
      &amp;lt;@submitFormLinkConfirm form=&amp;quot;removeReturnItemAction&amp;quot; text=uiLabelMap.CommonRemove returnItemSeqId=item.returnItemSeqId /&amp;gt;&lt;br /&gt;
     &amp;lt;/#list&amp;gt;&lt;br /&gt;
   &amp;lt;/@form&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Also the new ''selectActionForm'' and ''actionForm'' can be used with ''form'' to define a drop-down menu where when an item (''actionForm'') is selected it submits the corresponding ''form'':&lt;br /&gt;
   &amp;lt;@form name=&amp;quot;deleteLeadForm&amp;quot; url=&amp;quot;deleteLead&amp;quot; leadPartyId=partySummary.partyId /&amp;gt;&lt;br /&gt;
   &amp;lt;@form ... /&amp;gt;&lt;br /&gt;
   &amp;lt;@selectActionForm name=&amp;quot;leadActions&amp;quot; prompt=&amp;quot;${uiLabelMap.CommonSelectOne}&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;@actionForm form=&amp;quot;deleteLeadForm&amp;quot; text=&amp;quot;${uiLabelMap.CommonDelete}&amp;quot;/&amp;gt;&lt;br /&gt;
     &amp;lt;@actionForm .../&amp;gt;&lt;br /&gt;
   &amp;lt;@selectAction/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Service and HTML inputs ===&lt;br /&gt;
&lt;br /&gt;
As a security feature, the services will filter any input with HTML by default. Some services still require HTML (like emails or templates services) and to allow that there is a new ''allow-html'' parameter. For example:&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;attribute name=&amp;quot;content&amp;quot; type=&amp;quot;String&amp;quot; mode=&amp;quot;IN&amp;quot; optional=&amp;quot;false&amp;quot; allow-html=&amp;quot;safe&amp;quot;/&amp;gt;&lt;br /&gt;
     &amp;lt;override name=&amp;quot;mergeFormText&amp;quot; allow-html=&amp;quot;safe&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Form Widget Changes ===&lt;br /&gt;
&lt;br /&gt;
Form widget URL parameters should be specified with &amp;lt;tt&amp;gt;parameter&amp;lt;/tt&amp;gt; tag now, instead of in the URL:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-            &amp;lt;hyperlink description=&amp;quot;${contactListName} (${contactListId})&amp;quot; target=&amp;quot;viewContactList?contactListId=${contactListId}&amp;quot;&amp;gt;&lt;br /&gt;
+            &amp;lt;hyperlink description=&amp;quot;${contactListName} (${contactListId})&amp;quot; target=&amp;quot;viewContactList&amp;quot;&amp;gt;&lt;br /&gt;
+                &amp;lt;parameter param-name=&amp;quot;contactListId&amp;quot; from-field=&amp;quot;contactListId&amp;quot;/&amp;gt;&lt;br /&gt;
             &amp;lt;/hyperlink&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Do not have it both in the URL and as a &amp;lt;tt&amp;gt;parameter&amp;lt;/tt&amp;gt;, or the parameter will be on the form twice and be passed incorrectly.&lt;br /&gt;
&lt;br /&gt;
=== Controller redirects ===&lt;br /&gt;
&lt;br /&gt;
Redirects have been changed, now ''request-redirect'' will only copy the parameters that were in the URL string by default. To forward posted or service output parameter, use the ''redirect-parameter'' elements (one per parameter).&lt;br /&gt;
   &amp;lt;response name=&amp;quot;success&amp;quot; type=&amp;quot;request-redirect&amp;quot; value=&amp;quot;viewAccount&amp;quot;&amp;gt;&lt;br /&gt;
       &amp;lt;redirect-parameter name=&amp;quot;partyId&amp;quot;/&amp;gt;&lt;br /&gt;
   &amp;lt;/response&amp;gt;&lt;br /&gt;
Also ''request-redirect-filter-param'' is now considered deprecated.&lt;br /&gt;
&lt;br /&gt;
=== Js dateTime format ===&lt;br /&gt;
&lt;br /&gt;
Js dataTime format in ftl have been changed, now the format will return html encode string which will cause the parse exception, you should use StringUtil.wrapString to avoid this issue. For example, in earlier versions, you could have define a js dataTime format variable like this:&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;#assign dateFormat = Static[&amp;quot;org.opentaps.common.util.UtilDate&amp;quot;].getJsDateTimeFormat(Static[&amp;quot;org.opentaps.common.util.UtilDate&amp;quot;].getDateFormat(locale))/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In opentaps 1.4, you must do it this way:&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;#assign dateFormat = StringUtil.wrapString(Static[&amp;quot;org.opentaps.common.util.UtilDate&amp;quot;].getJsDateTimeFormat(Static[&amp;quot;org.opentaps.common.util.UtilDate&amp;quot;].getDateFormat(locale)))/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== BSH embedded in Forms ===&lt;br /&gt;
&lt;br /&gt;
In Forms widgets you could embed bsh code in order to have more flexibility over the formatting. Those embedded scripts need to be changed to groovy to avoid classpath issues. Fortunately this is as simple as changing the ''${bsh:'' to ''${groovy:''&lt;br /&gt;
&lt;br /&gt;
For example, in earlier versions, you could transform a party Id into the whole party name:&lt;br /&gt;
&lt;br /&gt;
   &amp;lt;field name=&amp;quot;partyId&amp;quot; title=&amp;quot;${uiLabelMap.ProductSupplier}&amp;quot;&amp;gt; &lt;br /&gt;
     &amp;lt;display description=&amp;quot;${bsh:org.ofbiz.party.party.PartyHelper.getPartyName(delegator, partyId, false)} (${partyId})&amp;quot;/&amp;gt;&lt;br /&gt;
   &amp;lt;/field&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In opentaps 1.4, you must change it to:&lt;br /&gt;
&lt;br /&gt;
   &amp;lt;field name=&amp;quot;partyId&amp;quot; title=&amp;quot;${uiLabelMap.ProductSupplier}&amp;quot;&amp;gt; &lt;br /&gt;
     &amp;lt;display description=&amp;quot;${groovy:org.ofbiz.party.party.PartyHelper.getPartyName(delegator, partyId, false)} (${partyId})&amp;quot;/&amp;gt;&lt;br /&gt;
   &amp;lt;/field&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== UEL in Minilang ===&lt;br /&gt;
&lt;br /&gt;
The ofbiz framework now supports unified express language (UEL) in the screen widgets and minilang simple methods.  (See [http://docs.ofbiz.org/display/OFBTECH/Unified+Expression+Language+%28JSR-245%29+in+OFBiz ofbiz wiki])&lt;br /&gt;
&lt;br /&gt;
One side effect is that code in simple methods, for example:&lt;br /&gt;
  someHash.${someVariableAsKey}&lt;br /&gt;
&lt;br /&gt;
In opentaps 1.4, you must change it to:&lt;br /&gt;
  someHash[someVariableAsKey]&lt;br /&gt;
&lt;br /&gt;
=== HTML escaping ===&lt;br /&gt;
&lt;br /&gt;
The ofbiz framework now automatically encodes most of the data displayed on the page. In some cases this is not wanted, and to avoid escaping in form widget use ''encode-output=&amp;quot;false&amp;quot;'' in the field element:&lt;br /&gt;
    &amp;lt;field name=&amp;quot;transactionDate&amp;quot; encode-output=&amp;quot;false&amp;quot;&amp;gt;&amp;lt;date-time/&amp;gt;&amp;lt;/field&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the FTL templates use the ''StringUtil'' class:&lt;br /&gt;
    ${StringUtil.wrapString(someData)}&lt;br /&gt;
&lt;br /&gt;
Some previous helper methods that constructed HTML code will not work anymore. For example ''PartyHelper.createViewPageLink'' has been replaced with the macro:&lt;br /&gt;
    &amp;lt;@displayPartyLink partyId=partyId /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Internationalization and Translations ==&lt;br /&gt;
&lt;br /&gt;
In ofbiz09.04, translations are now in XML format instead of .properties.   However, the old .properties translations are supported still as well.&lt;br /&gt;
&lt;br /&gt;
Furthermore, it is possible to define a component with all your translations, instead of putting them into the various existing components. As an example, &amp;lt;tt&amp;gt;hot-deploy/translations&amp;lt;/tt&amp;gt; in opentaps contains a full set of translations for opentaps to Bulgarian.&lt;br /&gt;
&lt;br /&gt;
== Other Changes ==&lt;br /&gt;
&lt;br /&gt;
In some cases the ''screenlet-title-bar'' used in some ofbiz forms and screens is not wanted, in that case simply wrap the form or screen section in a ''noTitleBar'' div.&lt;br /&gt;
&lt;br /&gt;
For example ''ViewShipmentRouteInfo.ftl'' defines such a title, to hide it we added to the screen definition:&lt;br /&gt;
&lt;br /&gt;
      &amp;lt;container style=&amp;quot;noTitleBar&amp;quot;&amp;gt;&lt;br /&gt;
          &amp;lt;platform-specific&amp;gt;&lt;br /&gt;
              &amp;lt;html&amp;gt;&amp;lt;html-template location=&amp;quot;component://product/webapp/facility/shipment/ViewShipmentRouteInfo.ftl&amp;quot;/&amp;gt;&amp;lt;/html&amp;gt;&lt;br /&gt;
          &amp;lt;/platform-specific&amp;gt;&lt;br /&gt;
      &amp;lt;/container&amp;gt;&lt;/div&gt;</summary>
		<author><name>Spark</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=Opentaps_Funambol_Setup&amp;diff=5256</id>
		<title>Opentaps Funambol Setup</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=Opentaps_Funambol_Setup&amp;diff=5256"/>
		<updated>2009-12-29T00:56:43Z</updated>

		<summary type="html">&lt;p&gt;Spark: /* Synchronising Opentaps and Windows Mobile */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;There are currently extensive instructions available in hot-deploy/funambol/docs/man.  These documents will be moved at some point to this site.&lt;br /&gt;
&lt;br /&gt;
===Troubleshooting the Funambol Component===&lt;br /&gt;
&lt;br /&gt;
The log file for the Funambol component is in hot-deploy/funambol/logs/funambol_ds.log&lt;br /&gt;
&lt;br /&gt;
===Setting up the Funambol server in Opentaps===&lt;br /&gt;
&lt;br /&gt;
The document which explains how to set up the funambol server is hot-deploy/funambol/docs/man/otfm_admin_guide.doc&lt;br /&gt;
&lt;br /&gt;
After following this steps, you should have a complete funambol server working.&lt;br /&gt;
&lt;br /&gt;
===Synchronising Opentaps and Mozilla Thunderbird===&lt;br /&gt;
&lt;br /&gt;
Hosting: http://sourceforge.net/projects/sync4jmozilla&lt;br /&gt;
&lt;br /&gt;
Configuration to synchronise with the admin account with opentaps and&lt;br /&gt;
mozilla thunderbird on the same computer:&lt;br /&gt;
&lt;br /&gt;
Edit --&amp;gt; Preferences --&amp;gt; Funambol&lt;br /&gt;
&lt;br /&gt;
Account&lt;br /&gt;
server URL: http://127.0.0.1:8080/funambol/ds&lt;br /&gt;
Username: admin&lt;br /&gt;
Password: ofbiz&lt;br /&gt;
&lt;br /&gt;
Synchronize&lt;br /&gt;
Items --&amp;gt; Contact --&amp;gt; Details&lt;br /&gt;
&lt;br /&gt;
Select the addressbook to sync&lt;br /&gt;
Remote name: otcontact&lt;br /&gt;
&lt;br /&gt;
If you have the extension Lightning, you can also synchronise your calendar. I recommand to install the extension Provider for google calendar as well, so you can export items from Thunderbird to Google Calendar.&lt;br /&gt;
&lt;br /&gt;
Synchronize&lt;br /&gt;
Items --&amp;gt; Calendar --&amp;gt; Details&lt;br /&gt;
&lt;br /&gt;
Select the Calendar to sync&lt;br /&gt;
Remote name: otcalendar&lt;br /&gt;
&lt;br /&gt;
===Synchronising Opentaps and Outlook===&lt;br /&gt;
&lt;br /&gt;
In case you are using windows 2000, you have to use the funambol outlook plugin 3.0.15&lt;br /&gt;
But this plugin can't synchronise contacts with the funambol version 6 which is included in opentaps.&lt;br /&gt;
You'll be able to synchronise tasks and calendar only.&lt;br /&gt;
&lt;br /&gt;
To install this plugin, you have to follow the instruction in the document http://download.forge.objectweb.org/sync4j/Outlook_Plugin_UG.pdf&lt;br /&gt;
&lt;br /&gt;
Configuration to synchronise with the admin account with opentaps and&lt;br /&gt;
outlook plugin on the same computer:&lt;br /&gt;
&lt;br /&gt;
Edit --&amp;gt; Communication Settings&lt;br /&gt;
SyncServer URL: http://127.0.0.1:8080/funambol/ds&lt;br /&gt;
Username: admin&lt;br /&gt;
Password: ofbiz&lt;br /&gt;
&lt;br /&gt;
Edit --&amp;gt; Synchronisation Settings&lt;br /&gt;
Activate synchronisation with Contacts, Calendar, Tasks&lt;br /&gt;
Remote Settings:&lt;br /&gt;
Contact Name otcontact&lt;br /&gt;
Calendar Name otcalendar&lt;br /&gt;
Task Name ottask&lt;br /&gt;
&lt;br /&gt;
Hit the Synchronize button.&lt;br /&gt;
&lt;br /&gt;
===Synchronising Opentaps and Gmail===&lt;br /&gt;
&lt;br /&gt;
Hosting: https://google-connector.forge.funambol.org/&lt;br /&gt;
&lt;br /&gt;
The version tested is 1.2.0 beta1.&lt;br /&gt;
&lt;br /&gt;
Edit --&amp;gt; Communication Settings&lt;br /&gt;
Server URL: http://127.0.0.1:8080/funambol/ds&lt;br /&gt;
FunambolUsername: admin&lt;br /&gt;
FunambolPassword: ofbiz&lt;br /&gt;
Gmail Username: myuserIdongmail&lt;br /&gt;
Gmail Password: mypasswordongmail&lt;br /&gt;
&lt;br /&gt;
Edit --&amp;gt; Synchronisation Settings&lt;br /&gt;
Activate synchronisation with Contacts, Calendar&lt;br /&gt;
Remote Settings: &lt;br /&gt;
Contact Name otcontact&lt;br /&gt;
Calendar Name otcalendar&lt;br /&gt;
&lt;br /&gt;
===Synchronising Opentaps and Yahoo===&lt;br /&gt;
&lt;br /&gt;
Hosting: http://sourceforge.net/projects/funambolyahoo/&lt;br /&gt;
&lt;br /&gt;
Edit --&amp;gt; Communication Settings&lt;br /&gt;
Server URL: http://127.0.0.1:8080/funambol/ds&lt;br /&gt;
FunambolUsername: admin&lt;br /&gt;
FunambolPassword: ofbiz&lt;br /&gt;
Yahoo Username: myuserIdonyahoo&lt;br /&gt;
Yahoo Password: mypasswordonyahoo&lt;br /&gt;
&lt;br /&gt;
Edit --&amp;gt; Synchronisation Settings&lt;br /&gt;
Activate synchronisation with Contacts&lt;br /&gt;
&lt;br /&gt;
The synchronisation with Calendar doesn't work, because yahoo connector use calendar in Vcalendar format only and opentaps send the calendar in sif format. Please don't activate it.&lt;br /&gt;
&lt;br /&gt;
Remote Settings:&lt;br /&gt;
Contact Name otcontact&lt;br /&gt;
Calendar Name otcalendar&lt;br /&gt;
&lt;br /&gt;
===Synchronising Opentaps and Skype===&lt;br /&gt;
&lt;br /&gt;
Hosting: http://sourceforge.net/projects/funambolskype/&lt;br /&gt;
&lt;br /&gt;
There is currently no release either commit on svn on this project.&lt;br /&gt;
&lt;br /&gt;
===Synchronising Opentaps and Windows Mobile ===&lt;br /&gt;
&lt;br /&gt;
In case you are using windows, you have to use the funambol windows mobile sync client, you can download the version which fit your mobile at https://www.forge.funambol.org/download/.&lt;br /&gt;
&lt;br /&gt;
After install the sync client to your mobile, we can do following steps to configure it to connect with opentaps.&lt;br /&gt;
&lt;br /&gt;
Menu --&amp;gt; Accout&lt;br /&gt;
Server location: http://[yourserverip]:8080/funambol/ds&lt;br /&gt;
Username: admin&lt;br /&gt;
Password: ofbiz&lt;br /&gt;
&lt;br /&gt;
Menu --&amp;gt; Settings&lt;br /&gt;
Activate synchronisation with Contacts, Calendar, Tasks&lt;br /&gt;
&lt;br /&gt;
Menu --&amp;gt; Settings --&amp;gt; Advanced&lt;br /&gt;
Remote Name:&lt;br /&gt;
Contacts otcontact&lt;br /&gt;
Calendar otcalendar&lt;br /&gt;
Tasks ottask&lt;br /&gt;
&lt;br /&gt;
then, Hit the Sync All button.&lt;/div&gt;</summary>
		<author><name>Spark</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=Opentaps_Funambol_Setup&amp;diff=5255</id>
		<title>Opentaps Funambol Setup</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=Opentaps_Funambol_Setup&amp;diff=5255"/>
		<updated>2009-12-29T00:56:05Z</updated>

		<summary type="html">&lt;p&gt;Spark: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;There are currently extensive instructions available in hot-deploy/funambol/docs/man.  These documents will be moved at some point to this site.&lt;br /&gt;
&lt;br /&gt;
===Troubleshooting the Funambol Component===&lt;br /&gt;
&lt;br /&gt;
The log file for the Funambol component is in hot-deploy/funambol/logs/funambol_ds.log&lt;br /&gt;
&lt;br /&gt;
===Setting up the Funambol server in Opentaps===&lt;br /&gt;
&lt;br /&gt;
The document which explains how to set up the funambol server is hot-deploy/funambol/docs/man/otfm_admin_guide.doc&lt;br /&gt;
&lt;br /&gt;
After following this steps, you should have a complete funambol server working.&lt;br /&gt;
&lt;br /&gt;
===Synchronising Opentaps and Mozilla Thunderbird===&lt;br /&gt;
&lt;br /&gt;
Hosting: http://sourceforge.net/projects/sync4jmozilla&lt;br /&gt;
&lt;br /&gt;
Configuration to synchronise with the admin account with opentaps and&lt;br /&gt;
mozilla thunderbird on the same computer:&lt;br /&gt;
&lt;br /&gt;
Edit --&amp;gt; Preferences --&amp;gt; Funambol&lt;br /&gt;
&lt;br /&gt;
Account&lt;br /&gt;
server URL: http://127.0.0.1:8080/funambol/ds&lt;br /&gt;
Username: admin&lt;br /&gt;
Password: ofbiz&lt;br /&gt;
&lt;br /&gt;
Synchronize&lt;br /&gt;
Items --&amp;gt; Contact --&amp;gt; Details&lt;br /&gt;
&lt;br /&gt;
Select the addressbook to sync&lt;br /&gt;
Remote name: otcontact&lt;br /&gt;
&lt;br /&gt;
If you have the extension Lightning, you can also synchronise your calendar. I recommand to install the extension Provider for google calendar as well, so you can export items from Thunderbird to Google Calendar.&lt;br /&gt;
&lt;br /&gt;
Synchronize&lt;br /&gt;
Items --&amp;gt; Calendar --&amp;gt; Details&lt;br /&gt;
&lt;br /&gt;
Select the Calendar to sync&lt;br /&gt;
Remote name: otcalendar&lt;br /&gt;
&lt;br /&gt;
===Synchronising Opentaps and Outlook===&lt;br /&gt;
&lt;br /&gt;
In case you are using windows 2000, you have to use the funambol outlook plugin 3.0.15&lt;br /&gt;
But this plugin can't synchronise contacts with the funambol version 6 which is included in opentaps.&lt;br /&gt;
You'll be able to synchronise tasks and calendar only.&lt;br /&gt;
&lt;br /&gt;
To install this plugin, you have to follow the instruction in the document http://download.forge.objectweb.org/sync4j/Outlook_Plugin_UG.pdf&lt;br /&gt;
&lt;br /&gt;
Configuration to synchronise with the admin account with opentaps and&lt;br /&gt;
outlook plugin on the same computer:&lt;br /&gt;
&lt;br /&gt;
Edit --&amp;gt; Communication Settings&lt;br /&gt;
SyncServer URL: http://127.0.0.1:8080/funambol/ds&lt;br /&gt;
Username: admin&lt;br /&gt;
Password: ofbiz&lt;br /&gt;
&lt;br /&gt;
Edit --&amp;gt; Synchronisation Settings&lt;br /&gt;
Activate synchronisation with Contacts, Calendar, Tasks&lt;br /&gt;
Remote Settings:&lt;br /&gt;
Contact Name otcontact&lt;br /&gt;
Calendar Name otcalendar&lt;br /&gt;
Task Name ottask&lt;br /&gt;
&lt;br /&gt;
Hit the Synchronize button.&lt;br /&gt;
&lt;br /&gt;
===Synchronising Opentaps and Gmail===&lt;br /&gt;
&lt;br /&gt;
Hosting: https://google-connector.forge.funambol.org/&lt;br /&gt;
&lt;br /&gt;
The version tested is 1.2.0 beta1.&lt;br /&gt;
&lt;br /&gt;
Edit --&amp;gt; Communication Settings&lt;br /&gt;
Server URL: http://127.0.0.1:8080/funambol/ds&lt;br /&gt;
FunambolUsername: admin&lt;br /&gt;
FunambolPassword: ofbiz&lt;br /&gt;
Gmail Username: myuserIdongmail&lt;br /&gt;
Gmail Password: mypasswordongmail&lt;br /&gt;
&lt;br /&gt;
Edit --&amp;gt; Synchronisation Settings&lt;br /&gt;
Activate synchronisation with Contacts, Calendar&lt;br /&gt;
Remote Settings: &lt;br /&gt;
Contact Name otcontact&lt;br /&gt;
Calendar Name otcalendar&lt;br /&gt;
&lt;br /&gt;
===Synchronising Opentaps and Yahoo===&lt;br /&gt;
&lt;br /&gt;
Hosting: http://sourceforge.net/projects/funambolyahoo/&lt;br /&gt;
&lt;br /&gt;
Edit --&amp;gt; Communication Settings&lt;br /&gt;
Server URL: http://127.0.0.1:8080/funambol/ds&lt;br /&gt;
FunambolUsername: admin&lt;br /&gt;
FunambolPassword: ofbiz&lt;br /&gt;
Yahoo Username: myuserIdonyahoo&lt;br /&gt;
Yahoo Password: mypasswordonyahoo&lt;br /&gt;
&lt;br /&gt;
Edit --&amp;gt; Synchronisation Settings&lt;br /&gt;
Activate synchronisation with Contacts&lt;br /&gt;
&lt;br /&gt;
The synchronisation with Calendar doesn't work, because yahoo connector use calendar in Vcalendar format only and opentaps send the calendar in sif format. Please don't activate it.&lt;br /&gt;
&lt;br /&gt;
Remote Settings:&lt;br /&gt;
Contact Name otcontact&lt;br /&gt;
Calendar Name otcalendar&lt;br /&gt;
&lt;br /&gt;
===Synchronising Opentaps and Skype===&lt;br /&gt;
&lt;br /&gt;
Hosting: http://sourceforge.net/projects/funambolskype/&lt;br /&gt;
&lt;br /&gt;
There is currently no release either commit on svn on this project.&lt;br /&gt;
&lt;br /&gt;
===Synchronising Opentaps and Windows Mobile ===&lt;br /&gt;
&lt;br /&gt;
In case you are using windows, you have to use the funambol windows mobile sync client, you can download the version which fit your mobile at https://www.forge.funambol.org/download/.&lt;br /&gt;
&lt;br /&gt;
After install the sync client to your mobile, we can do following steps to configure it to connect with opentaps.&lt;br /&gt;
&lt;br /&gt;
Menu --&amp;gt; Accout&lt;br /&gt;
Server location: http://127.0.0.1:8080/funambol/ds&lt;br /&gt;
Username: admin&lt;br /&gt;
Password: ofbiz&lt;br /&gt;
&lt;br /&gt;
Menu --&amp;gt; Settings&lt;br /&gt;
Activate synchronisation with Contacts, Calendar, Tasks&lt;br /&gt;
&lt;br /&gt;
Menu --&amp;gt; Settings --&amp;gt; Advanced&lt;br /&gt;
Remote Name:&lt;br /&gt;
Contacts otcontact&lt;br /&gt;
Calendar otcalendar&lt;br /&gt;
Tasks ottask&lt;br /&gt;
&lt;br /&gt;
then, Hit the Sync All button.&lt;/div&gt;</summary>
		<author><name>Spark</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=Opentaps_Funambol_Setup&amp;diff=5254</id>
		<title>Opentaps Funambol Setup</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=Opentaps_Funambol_Setup&amp;diff=5254"/>
		<updated>2009-12-26T04:28:14Z</updated>

		<summary type="html">&lt;p&gt;Spark: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;There are currently extensive instructions available in hot-deploy/funambol/docs/man.  These documents will be moved at some point to this site.&lt;br /&gt;
&lt;br /&gt;
===Troubleshooting the Funambol Component===&lt;br /&gt;
&lt;br /&gt;
The log file for the Funambol component is in hot-deploy/funambol/logs/funambol_ds.log&lt;br /&gt;
&lt;br /&gt;
===Setting up the Funambol server in Opentaps===&lt;br /&gt;
&lt;br /&gt;
The document which explains how to set up the funambol server is hot-deploy/funambol/docs/man/otfm_admin_guide.doc&lt;br /&gt;
&lt;br /&gt;
After following this steps, you should have a complete funambol server working.&lt;br /&gt;
&lt;br /&gt;
===Synchronising Opentaps and Mozilla Thunderbird===&lt;br /&gt;
&lt;br /&gt;
Hosting: http://sourceforge.net/projects/sync4jmozilla&lt;br /&gt;
&lt;br /&gt;
Configuration to synchronise with the admin account with opentaps and&lt;br /&gt;
mozilla thunderbird on the same computer:&lt;br /&gt;
&lt;br /&gt;
Edit --&amp;gt; Preferences --&amp;gt; Funambol&lt;br /&gt;
&lt;br /&gt;
Account&lt;br /&gt;
server URL: http://127.0.0.1:8080/funambol/ds&lt;br /&gt;
Username: admin&lt;br /&gt;
Password: ofbiz&lt;br /&gt;
&lt;br /&gt;
Synchronize&lt;br /&gt;
Items --&amp;gt; Contact --&amp;gt; Details&lt;br /&gt;
&lt;br /&gt;
Select the addressbook to sync&lt;br /&gt;
Remote name: otcontact&lt;br /&gt;
&lt;br /&gt;
If you have the extension Lightning, you can also synchronise your calendar. I recommand to install the extension Provider for google calendar as well, so you can export items from Thunderbird to Google Calendar.&lt;br /&gt;
&lt;br /&gt;
Synchronize&lt;br /&gt;
Items --&amp;gt; Calendar --&amp;gt; Details&lt;br /&gt;
&lt;br /&gt;
Select the Calendar to sync&lt;br /&gt;
Remote name: otcalendar&lt;br /&gt;
&lt;br /&gt;
===Synchronising Opentaps and Outlook===&lt;br /&gt;
&lt;br /&gt;
In case you are using windows 2000, you have to use the funambol outlook plugin 3.0.15&lt;br /&gt;
But this plugin can't synchronise contacts with the funambol version 6 which is included in opentaps.&lt;br /&gt;
You'll be able to synchronise tasks and calendar only.&lt;br /&gt;
&lt;br /&gt;
To install this plugin, you have to follow the instruction in the document http://download.forge.objectweb.org/sync4j/Outlook_Plugin_UG.pdf&lt;br /&gt;
&lt;br /&gt;
Configuration to synchronise with the admin account with opentaps and&lt;br /&gt;
outlook plugin on the same computer:&lt;br /&gt;
&lt;br /&gt;
Edit --&amp;gt; Communication Settings&lt;br /&gt;
SyncServer URL: http://127.0.0.1:8080/funambol/ds&lt;br /&gt;
Username: admin&lt;br /&gt;
Password: ofbiz&lt;br /&gt;
&lt;br /&gt;
Edit --&amp;gt; Synchronisation Settings&lt;br /&gt;
Activate synchronisation with Contacts, Calendar, Tasks&lt;br /&gt;
Remote Settings:&lt;br /&gt;
Contact Name otcontact&lt;br /&gt;
Calendar Name otcalendar&lt;br /&gt;
Task Name ottask&lt;br /&gt;
&lt;br /&gt;
Hit the Synchronize button.&lt;br /&gt;
&lt;br /&gt;
===Synchronising Opentaps and Gmail===&lt;br /&gt;
&lt;br /&gt;
Hosting: https://google-connector.forge.funambol.org/&lt;br /&gt;
&lt;br /&gt;
The version tested is 1.2.0 beta1.&lt;br /&gt;
&lt;br /&gt;
Edit --&amp;gt; Communication Settings&lt;br /&gt;
Server URL: http://127.0.0.1:8080/funambol/ds&lt;br /&gt;
FunambolUsername: admin&lt;br /&gt;
FunambolPassword: ofbiz&lt;br /&gt;
Gmail Username: myuserIdongmail&lt;br /&gt;
Gmail Password: mypasswordongmail&lt;br /&gt;
&lt;br /&gt;
Edit --&amp;gt; Synchronisation Settings&lt;br /&gt;
Activate synchronisation with Contacts, Calendar&lt;br /&gt;
Remote Settings: &lt;br /&gt;
Contact Name otcontact&lt;br /&gt;
Calendar Name otcalendar&lt;br /&gt;
&lt;br /&gt;
===Synchronising Opentaps and Yahoo===&lt;br /&gt;
&lt;br /&gt;
Hosting: http://sourceforge.net/projects/funambolyahoo/&lt;br /&gt;
&lt;br /&gt;
Edit --&amp;gt; Communication Settings&lt;br /&gt;
Server URL: http://127.0.0.1:8080/funambol/ds&lt;br /&gt;
FunambolUsername: admin&lt;br /&gt;
FunambolPassword: ofbiz&lt;br /&gt;
Yahoo Username: myuserIdonyahoo&lt;br /&gt;
Yahoo Password: mypasswordonyahoo&lt;br /&gt;
&lt;br /&gt;
Edit --&amp;gt; Synchronisation Settings&lt;br /&gt;
Activate synchronisation with Contacts&lt;br /&gt;
&lt;br /&gt;
The synchronisation with Calendar doesn't work, because yahoo connector use calendar in Vcalendar format only and opentaps send the calendar in sif format. Please don't activate it.&lt;br /&gt;
&lt;br /&gt;
Remote Settings:&lt;br /&gt;
Contact Name otcontact&lt;br /&gt;
Calendar Name otcalendar&lt;br /&gt;
&lt;br /&gt;
===Synchronising Opentaps and Skype===&lt;br /&gt;
&lt;br /&gt;
Hosting: http://sourceforge.net/projects/funambolskype/&lt;br /&gt;
&lt;br /&gt;
There is currently no release either commit on svn on this project.&lt;/div&gt;</summary>
		<author><name>Spark</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=Opentaps_Hibernate_Integration&amp;diff=5057</id>
		<title>Opentaps Hibernate Integration</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=Opentaps_Hibernate_Integration&amp;diff=5057"/>
		<updated>2009-11-26T11:27:09Z</updated>

		<summary type="html">&lt;p&gt;Spark: /* Caching */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Beginning with opentaps version 1.4, [http://www.hibernate.org Hibernate] will be available as a persistence tool alongside with the original ofbiz entity engine.  Hibernate is a more object oriented persistence framework and better suited for the new [[Domain Driven Architecture]], while the ofbiz entity engine will continue to be supported for legacy features from both ofbiz and opentaps.  In this document, we will review how the hibernate integration in opentaps works.&lt;br /&gt;
&lt;br /&gt;
== Working with Hibernate in opentaps ==&lt;br /&gt;
&lt;br /&gt;
=== Generating Hibernate Configuration Files ===&lt;br /&gt;
&lt;br /&gt;
After changing or defining new entities in your &amp;lt;tt&amp;gt;entitymodel.xml&amp;lt;/tt&amp;gt; files, you need to generate new Java classes for your entities with&lt;br /&gt;
 $ ant make-base-entities&lt;br /&gt;
&lt;br /&gt;
This command updates the Java classes defined in &amp;lt;tt&amp;gt;org.opentaps.domain.base.entities&amp;lt;/tt&amp;gt;, including their hibernate annotations, and the &amp;lt;tt&amp;gt;hibernate.cfg.xml&amp;lt;/tt&amp;gt; for integrating with hibernate.  (If you use a repository management system, you must commit both and you Java classes and the updated &amp;lt;tt&amp;gt;hibernate.cfg.xml&amp;lt;/tt&amp;gt; files.)&lt;br /&gt;
&lt;br /&gt;
{{note|Important|Be sure to reference the JARs from &amp;lt;tt&amp;gt;/hot-deploy/opentaps-common/lib/hibernate&amp;lt;/tt&amp;gt; in your Ant build file, or else during build it will not be able to locate the appropriate Hibernate files.}}&lt;br /&gt;
&lt;br /&gt;
=== Accessing Entities with Hibernate ===&lt;br /&gt;
&lt;br /&gt;
{{tip|Tip|If you are developing in Eclipse, when using Hibernate make sure to run the ant task &amp;lt;tt&amp;gt;make-base-entities&amp;lt;/tt&amp;gt; immediately after you are done defining new entities. Also make sure you refresh the Eclipse project so that it picks up the new Hibernate POJOs for code-assist.}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To use hibernate to access your entities, you will need an &amp;lt;tt&amp;gt;org.opentaps.foundation.entity.hibernate.Session&amp;lt;/tt&amp;gt;, which is an extension of the &amp;lt;tt&amp;gt;org.hibernate.Session&amp;lt;/tt&amp;gt; class.  You can obtain it from the Infrastructure class like this:&lt;br /&gt;
        session = infrastructure.getSession();&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;Infrastructure&amp;lt;/tt&amp;gt; must be created from &amp;lt;tt&amp;gt;dispatcher&amp;lt;/tt&amp;gt; in order to obtain the hibernate session.&lt;br /&gt;
&lt;br /&gt;
In situations where you are passing through the service engine the &amp;lt;tt&amp;gt;dispatcher&amp;lt;/tt&amp;gt; is obtained from the &amp;lt;tt&amp;gt;DispatchContext&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
        public static Map myNewService(DispatchContext dctx, Map context) {&lt;br /&gt;
            LocalDispatcher dispatcher = dctx.getDispatcher();&lt;br /&gt;
    &lt;br /&gt;
            try {&lt;br /&gt;
                Infrastructure infrastructure = new Infrastructure(dispatcher);&lt;br /&gt;
                Session session = infrastructure.getSession();&lt;br /&gt;
            } catch (InfrastructureException e) {&lt;br /&gt;
                // TODO Auto-generated catch block&lt;br /&gt;
                e.printStackTrace();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
In situations where you are bypassing the service engine and accessing the Java method directly the &amp;lt;tt&amp;gt;dispatcher&amp;lt;/tt&amp;gt; is obtained from &amp;lt;tt&amp;gt;HttpServletRequest&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
    public static Map myNewService(HttpServletRequest request, HttpServletResponse response) {&lt;br /&gt;
        LocalDispatcher dispatcher = (LocalDispatcher) request.getAttribute(&amp;quot;dispatcher&amp;quot;);&lt;br /&gt;
    &lt;br /&gt;
        try {&lt;br /&gt;
            Infrastructure infrastructure = new Infrastructure(dispatcher);&lt;br /&gt;
            Session session = infrastructure.getSession();&lt;br /&gt;
        } catch (InfrastructureException e) {&lt;br /&gt;
            // TODO Auto-generated catch block&lt;br /&gt;
            e.printStackTrace();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
Then, you can work with it as if it were a Hibernate &amp;lt;tt&amp;gt;Session&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
        Transaction tx = session.beginTransaction();&lt;br /&gt;
        TestEntity newTestEntity = new TestEntity();&lt;br /&gt;
        newTestEntity.setTestStringField(&amp;quot;testInsertTestEntity string field&amp;quot;);&lt;br /&gt;
        newTestEntity.setCreatedStamp(UtilDateTime.nowTimestamp());&lt;br /&gt;
        session.save(newTestEntity);&lt;br /&gt;
        tx.commit();&lt;br /&gt;
        session.flush();&lt;br /&gt;
        // ...&lt;br /&gt;
        TestEntity loadEntity = (TestEntity) session.load(TestEntity.class, newTestEntity.getTestId());&lt;br /&gt;
        // ...&lt;br /&gt;
        String hql = &amp;quot;from TestEntity eo where eo.testId='&amp;quot; + testEntityId2 + &amp;quot;'&amp;quot;;&lt;br /&gt;
        Query query = session.createQuery(hql);&lt;br /&gt;
        List&amp;lt;TestEntity&amp;gt; list = query.list()&lt;br /&gt;
 &lt;br /&gt;
You do not need to close your JDBC connection manually with the opentaps Session, however.  When you call&lt;br /&gt;
            session.close();&lt;br /&gt;
It will do it for you automatically.&lt;br /&gt;
&lt;br /&gt;
=== Traversing Related Entities ===&lt;br /&gt;
&lt;br /&gt;
opentaps will automatically create the relationship annotations, such as @OneToMany, @ManyToMany, and @Join, for your Java classes.&lt;br /&gt;
&lt;br /&gt;
To get related entities, use the hibernate query language (HQL):&lt;br /&gt;
    String hql = &amp;quot;from TestEntityItem eo where eo.testEntity.testId='&amp;quot; + testEntity.getTestId() + &amp;quot;'&amp;quot;&lt;br /&gt;
               + &amp;quot; and eo.testEntityItemSeqId in (&amp;quot; + testEntityItemSeqIds + &amp;quot;)&amp;quot;;&lt;br /&gt;
    Query query = session.createQuery(hql);&lt;br /&gt;
    List&amp;lt;TestEntityItem&amp;gt; list = query.list();&lt;br /&gt;
&lt;br /&gt;
Or use the getter methods in the base entities:&lt;br /&gt;
    List&amp;lt;TestEntityItem&amp;gt; list = testEntity.getTestEntityItems();&lt;br /&gt;
&lt;br /&gt;
Note that hibernate will automatically load related entities for you, so the getRelated  methods from Repository which were designed for the ofbiz entity engine are no longer needed when you work with hibernate.&lt;br /&gt;
&lt;br /&gt;
=== Working with View Entities ===&lt;br /&gt;
&lt;br /&gt;
Once a view entity has been defined in &amp;lt;tt&amp;gt;entitymodel.xml&amp;lt;/tt&amp;gt;, you can access it as any other Java object from hibernate, for example:&lt;br /&gt;
        Query query = session.createQuery(&amp;quot;from TestEntityAndItem eo where eo.testId='&amp;quot; &lt;br /&gt;
                    + testEntityId + &amp;quot;' order by eo.testEntityItemSeqId&amp;quot;);&lt;br /&gt;
        List&amp;lt;TestEntityAndItem&amp;gt; list = query.list();&lt;br /&gt;
        &lt;br /&gt;
The opentaps  Session, which extends the hibernate Session, will automatically create the SQL for accessing the view entity.&lt;br /&gt;
&lt;br /&gt;
=== Using Transactions ===&lt;br /&gt;
&lt;br /&gt;
You should use the transaction manager configured in the ofbiz entity engine through the &amp;lt;tt&amp;gt;[http://java.sun.com/j2ee/sdk_1.3/techdocs/api/javax/transaction/UserTransaction.html UserTransaction]&amp;lt;/tt&amp;gt;  class.  In the entity engine, the transaction manager is configured as:&lt;br /&gt;
  &amp;lt;transaction-factory class=&amp;quot;org.ofbiz.geronimo.GeronimoTransactionFactory&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is obtained from the ofbiz &amp;lt;tt&amp;gt;TransactionFactory&amp;lt;/tt&amp;gt; by our &amp;lt;tt&amp;gt;Session&amp;lt;/tt&amp;gt; and used the same way as a hibernate transaction:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     UserTransaction tx = session.beginUserTransaction();&lt;br /&gt;
     // do something useful&lt;br /&gt;
     tx.commit();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Auto Generating ID Values ===&lt;br /&gt;
&lt;br /&gt;
ofbiz keeps track of auto generated sequence IDs in an entity called &amp;lt;tt&amp;gt;SequenceValueItem&amp;lt;/tt&amp;gt;  To make sure that the auto generated sequence IDs from hibernate and the ofbiz entity engine work well together, we have created an &amp;lt;tt&amp;gt;OpentapsIdentifierGenerator&amp;lt;/tt&amp;gt; which also uses the same &amp;lt;tt&amp;gt;SequenceValueItem&amp;lt;/tt&amp;gt; to obtain the next sequential ID.  This ID generator is wired to the base entity POJO Java objects with hibernate annotations, like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 @org.hibernate.annotations.GenericGenerator(name=&amp;quot;Party_GEN&amp;quot;,  strategy=&amp;quot;org.opentaps.foundation.entity.hibernate.OpentapsIdentifierGenerator&amp;quot;)&lt;br /&gt;
 @GeneratedValue(generator=&amp;quot;Party_GEN&amp;quot;)   &lt;br /&gt;
 @Id&lt;br /&gt;
    &lt;br /&gt;
 @Column(name=&amp;quot;PARTY_ID&amp;quot;)&lt;br /&gt;
    &lt;br /&gt;
 private String partyId;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So that a &amp;lt;tt&amp;gt;partyId&amp;lt;/tt&amp;gt; field is automatically set for you.&lt;br /&gt;
&lt;br /&gt;
You can also ask the &amp;lt;tt&amp;gt;Session&amp;lt;/tt&amp;gt; to generate a particular sequence ID for you:&lt;br /&gt;
 String testEntityItemSeqId = session.getNextSeqId(&amp;quot;TestEntityItemSeqId&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
This can be helpful when you have complex keys with several fields, and you want the secondary key fields to be auto sequenced as well.&lt;br /&gt;
&lt;br /&gt;
=== Support for OFBIZ EECA's ===&lt;br /&gt;
&lt;br /&gt;
ofbiz EECA's are supported with custom event listeners which are registered with hibernate when &amp;lt;tt&amp;gt;Infrastructure.getSessionFactory(String delegatorName)&amp;lt;/tt&amp;gt; is called, usually during the initial startup.  These event listeners will run ofbiz services defined in &amp;lt;tt&amp;gt;eeca.xml&amp;lt;/tt&amp;gt;'s  when hibernate is used to update the same entities.&lt;br /&gt;
&lt;br /&gt;
=== Caching ===&lt;br /&gt;
&lt;br /&gt;
After opentaps 1.4 preview 2, opentaps added support for hibernate caching using [http://ehcache.org/ EhCache] by default.  opentaps supports mutual cache clearing between the ofbiz entity engine and hibernate.  This means that opentaps will synchronize hibernate cache when you update your values with ofbiz entity engine, and vice versa. The hibernate cache configuration is locate in HibernateCfg.ftl (it also in hibernate.cfg.xml) as following:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  &amp;lt;property name=&amp;quot;hibernate.cache.provider_class&amp;quot;&amp;gt;org.hibernate.cache.EhCacheProvider&amp;lt;/property&amp;gt;&lt;br /&gt;
  &amp;lt;property name=&amp;quot;net.sf.ehcache.configurationResourceName&amp;quot;&amp;gt;ehcache.xml&amp;lt;/property&amp;gt; &lt;br /&gt;
  &amp;lt;property name=&amp;quot;hibernate.search.worker.execution&amp;quot;&amp;gt;async&amp;lt;/property&amp;gt;&lt;br /&gt;
  &amp;lt;property name=&amp;quot;hibernate.cache.use_query_cache&amp;quot;&amp;gt;true&amp;lt;/property&amp;gt;&lt;br /&gt;
  &amp;lt;property name=&amp;quot;hibernate.cache.use_second_level_cache&amp;quot;&amp;gt;true&amp;lt;/property&amp;gt;&lt;br /&gt;
  &amp;lt;property name=&amp;quot;hibernate.search.worker.buffer_queue.max&amp;quot;&amp;gt;5&amp;lt;/property&amp;gt;&lt;br /&gt;
  &amp;lt;property name=&amp;quot;hibernate.search.worker.thread_pool.size&amp;quot;&amp;gt;5&amp;lt;/property&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can disable the caching feature by removing or commenting out these lines (both HibernateCfg.ftl and hibernate.cfg.xml).&lt;br /&gt;
&lt;br /&gt;
{{note|Important|The entities of current open hibernate session will not update when they are changed by ofbiz entity engine after session has already been opened, so you must open a new session to get a refreshed version of the object. In contrast, if you update a value with hibernate, it will be refreshed in the ofbiz entity engine's cache.  This is due to the different way the ofbiz entity engine works versus hibernate -- the ofbiz delegator is a static object, whereas each hibernate session is a different object.}}&lt;br /&gt;
&lt;br /&gt;
=== Using Hibernate without the OFBIZ Entity Engine ===&lt;br /&gt;
&lt;br /&gt;
You can also use hibernate without the ofbiz entity engine by adding your Java objects to the template opentaps uses to generate the hibernate configuration files, &amp;lt;tt&amp;gt;hot-deploy/opentaps-common/templates/HibernateCfg.ftl&amp;lt;/tt&amp;gt;.  Simply put your Java objects after the &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  &amp;lt;#list&amp;gt;&lt;br /&gt;
    ...&lt;br /&gt;
  &amp;lt;/#list&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
directives in the file, like in the following example:    &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;!DOCTYPE hibernate-configuration PUBLIC &amp;quot;-//Hibernate/Hibernate Configuration DTD 3.0//EN&amp;quot; &amp;quot;http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;hibernate-configuration&amp;gt;&lt;br /&gt;
  &amp;lt;session-factory&amp;gt;&lt;br /&gt;
  &amp;lt;property name=&amp;quot;hibernate.connection.provider_class&amp;quot;&amp;gt;org.opentaps.foundation.entity.hibernate.OpentapsConnectionProvider&amp;lt;/property&amp;gt;  &lt;br /&gt;
  &amp;lt;property name=&amp;quot;hibernate.transaction.factory_class&amp;quot;&amp;gt;org.opentaps.foundation.entity.hibernate.OpentapsTransactionFactory&amp;lt;/property&amp;gt;&lt;br /&gt;
  &amp;lt;property name=&amp;quot;hibernate.transaction.manager_lookup_class&amp;quot;&amp;gt;org.opentaps.foundation.entity.hibernate.OpentapsTransactionManagerLookup&amp;lt;/property&amp;gt;  &lt;br /&gt;
  &amp;lt;property name=&amp;quot;hibernate.search.default.directory_provider&amp;quot;&amp;gt;org.hibernate.search.store.FSDirectoryProvider&amp;lt;/property&amp;gt;&lt;br /&gt;
&amp;lt;#list entities as entity&amp;gt;&lt;br /&gt;
  &amp;lt;mapping class=&amp;quot;org.opentaps.domain.base.entities.${entity}&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/#list&amp;gt;&lt;br /&gt;
  &amp;lt;mapping class=&amp;quot;org.opentaps.domain.base.entities.MyPojo1&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;mapping class=&amp;quot;org.opentaps.domain.base.entities.MyPojo2&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;/session-factory&amp;gt;&lt;br /&gt;
&amp;lt;/hibernate-configuration&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
opentaps will then create the hibernate configuration file for each database and include your Java objects in it.  However, you would not be able to access these Java objects as generic values from the ofbiz entity engine.&lt;br /&gt;
&lt;br /&gt;
== Under the Hood: How It Works ==&lt;br /&gt;
&lt;br /&gt;
=== Base Class Annotations ===&lt;br /&gt;
&lt;br /&gt;
In opentaps version 1.4, the entity model XML from the ofbiz entity engine is still used as the base definition for all entities.  The opentaps POJO generator is used to create [[Base Entity Classes|base Java objects]] automatically from these entity definitions.  This POJO generator will also create the annotations which hibernate can then use to map those base objects to the database persistence layer.  The definitions of the annotations can be found in &amp;lt;tt&amp;gt;BaseEntity.ftl&amp;lt;/tt&amp;gt; file used by the POJO generator.&lt;br /&gt;
&lt;br /&gt;
=== How Hibernate Configuration Files are Generated ===&lt;br /&gt;
&lt;br /&gt;
The POJO Generator will use &amp;lt;tt&amp;gt;hot-deploy/opentaps-common/templates/HibernateCfg.ftl&amp;lt;/tt&amp;gt; to generate a base hibernate configuration file in &amp;lt;tt&amp;gt;hot-deploy/opentaps-common/config/hibernate.cfg.xml&amp;lt;/tt&amp;gt;  When opentaps is started, the following new container in &amp;lt;tt&amp;gt;framework/base/config/ofbiz-containers.xml&amp;lt;/tt&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    &amp;lt;container name=&amp;quot;hibernate-container&amp;quot; class=&amp;quot;org.opentaps.common.container.HibernateContainer&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;property name=&amp;quot;delegator-name&amp;quot; value=&amp;quot;default&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;/container&amp;gt;    &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will generate all the hibernate configuration XML files in the &amp;lt;tt&amp;gt;hot-deploy/opentaps/config/&amp;lt;/tt&amp;gt; directory for each data source in your entity engine XML file.  For example, it will generate a &amp;lt;tt&amp;gt;localmysql.cfg.xml&amp;lt;/tt&amp;gt;, a &amp;lt;tt&amp;gt;localpostgres.cfg.xml&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How We Get the Hibernate Session ===&lt;br /&gt;
&lt;br /&gt;
The opentaps &amp;lt;tt&amp;gt;Infrastructure&amp;lt;/tt&amp;gt; Class maintains a Map of delegatorName and hibernate SessionFactory objects.  Each SessionFactory is created for its corresponding delegatorName the first time it is requested from the &amp;lt;tt&amp;gt;Infrastructure.getSessionFactory(delegatorName)&amp;lt;/tt&amp;gt; method.  This SessionFactory is created from ofbiz entity engine configurations:&lt;br /&gt;
* The &amp;lt;tt&amp;gt;HibernateContainer&amp;lt;/tt&amp;gt; in &amp;lt;tt&amp;gt;ofbiz-containers.xml&amp;lt;/tt&amp;gt; has a property called &amp;lt;tt&amp;gt;delegator-name&amp;lt;/tt&amp;gt;&lt;br /&gt;
* From this delegator, we get the data source defined in &amp;lt;tt&amp;gt;entityengine.xml&amp;lt;/tt&amp;gt; for the default group helper name.  This is set to &amp;lt;tt&amp;gt;org.ofbiz&amp;lt;/tt&amp;gt; by default in the &amp;lt;tt&amp;gt;Infrastructure&amp;lt;/tt&amp;gt; class and is the &amp;lt;tt&amp;gt;group&amp;lt;/tt&amp;gt; attribute of the &amp;lt;tt&amp;gt;entitygroup.xml&amp;lt;/tt&amp;gt; definitions in ofbiz:&lt;br /&gt;
  &amp;lt;entity-group group=&amp;quot;org.ofbiz&amp;quot; entity=&amp;quot;AcctgTagEnumType&amp;quot;/&amp;gt;&lt;br /&gt;
In &amp;lt;tt&amp;gt;entityengine.xml&amp;lt;/tt&amp;gt;, you map a data source to each group:&lt;br /&gt;
    &amp;lt;delegator name=&amp;quot;default&amp;quot; entity-model-reader=&amp;quot;main&amp;quot; entity-group-reader=&amp;quot;main&amp;quot; entity-eca-reader=&amp;quot;main&amp;quot; distributed-cache-clear-enabled=&amp;quot;false&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;group-map group-name=&amp;quot;org.ofbiz&amp;quot; datasource-name=&amp;quot;localmysql&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;/delegator&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So, we are basically following the entity engine from the delegator to the data source via the group.&lt;br /&gt;
* Once we have the data source, we can create the SessionFactory from the hibernate.cfg.xml for that data source.  For example, if your data source is &amp;quot;localmysql&amp;quot;, we will create the SessionFactory from the &amp;lt;tt&amp;gt;localmysql.cfg.xml&amp;lt;/tt&amp;gt;   created by the &amp;lt;tt&amp;gt;HibernateContainer&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;HibernateContainer&amp;lt;/tt&amp;gt;, which loads on startup, will cause a SessionFactory to be loaded for the delegator in the &amp;lt;tt&amp;gt;delegator-name&amp;lt;/tt&amp;gt; attribute.  Once this SessionFactory is loaded, it will be available for future use.  Additional session factories can be obtained later by calling the &amp;lt;tt&amp;gt;getSessionFactory&amp;lt;/tt&amp;gt; directly.&lt;br /&gt;
&lt;br /&gt;
When the &amp;lt;tt&amp;gt;Infrastructure.getSession()&amp;lt;/tt&amp;gt; method is called,  it will use the delegator already in the Infrastructure object to open a JDBC connection first, and then use that JDBC connection and the SessionFactory for the delegator to return a Session.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;Infrastructure.getSession()&amp;lt;/tt&amp;gt; will return an &amp;lt;tt&amp;gt;org.opentaps.foundation.entity.hibernate.Session&amp;lt;/tt&amp;gt;, which extends the hibernate Session with the following differences:&lt;br /&gt;
* when the session is closed, the JDBC connection is also automatically closed&lt;br /&gt;
* when a Query is created, this Session will check if the query is on an entity engine view entity and construct the Query from native SQL first&lt;br /&gt;
&lt;br /&gt;
=== View Entities ===&lt;br /&gt;
&lt;br /&gt;
View entities are supported with @NamedNativeQuery annotations in the base entity Java classes, which are automatically generated by the opentaps POJO Generator.&lt;br /&gt;
&lt;br /&gt;
=== Encryption ===&lt;br /&gt;
&lt;br /&gt;
The ofbiz delegator allows you to set a field to be encrypted in the database with the &amp;lt;tt&amp;gt;encrypt=&amp;quot;true&amp;quot;&amp;lt;/tt&amp;gt; attribute in the &amp;lt;tt&amp;gt;field&amp;lt;/tt&amp;gt; tag of an entity definition.  The opentaps hibernate will support the same encryption/decryption algorithm, so that encrypted values can be stored with the delegator and decrypted when it's retrieved with hibernate or vice versa.  This is done by:&lt;br /&gt;
# When an object is being stored, the &amp;lt;tt&amp;gt;EcaCommEvent.beforeSave&amp;lt;/tt&amp;gt; Method will come for the object to an ofbiz GenericValue and then use the ofbiz delegator to encrypt it.&lt;br /&gt;
# When an object is retrieved from the database, the &amp;lt;tt&amp;gt;Session.load&amp;lt;/tt&amp;gt; will call the &amp;lt;tt&amp;gt;HibernateUtil.decryptField&amp;lt;/tt&amp;gt; to decrypt it.&lt;br /&gt;
&lt;br /&gt;
=== Transaction Management ===&lt;br /&gt;
&lt;br /&gt;
To maintain compatibility with the ofbiz entity engine's transaction manager and connection pool providers, we have defined transaction manager look up, transaction factory, and connection provider classes which use the ofbiz transaction manager and transaction factory to begin transactions.  These are defined in the &amp;lt;tt&amp;gt;hibernate.cfg.xml&amp;lt;/tt&amp;gt; configuration file.  They allow you to mix delegator and hibernate transaction codes as in this following example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        UserTransaction tx = session.beginUserTransaction();&lt;br /&gt;
        TestEntity useIdentifierTestEntity = new TestEntity();&lt;br /&gt;
        useIdentifierTestEntity.setTestStringField(&amp;quot;Use IdentifierGenerator string field&amp;quot;);&lt;br /&gt;
        session.save(useIdentifierTestEntity);&lt;br /&gt;
        String getNextSeqIdTestEntityId = delegator.getNextSeqId(&amp;quot;TestEntity&amp;quot;);&lt;br /&gt;
        GenericValue useGetNextSeqIdTestEntity = delegator.create(&amp;quot;TestEntity&amp;quot;,&lt;br /&gt;
                UtilMisc.toMap(&amp;quot;testId&amp;quot;, getNextSeqIdTestEntityId,  &amp;quot;testStringField&amp;quot;, &amp;quot;Use getNextSeqId string field&amp;quot;));&lt;br /&gt;
        session.flush();&lt;br /&gt;
        tx.commit();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Support for BLOBs ===&lt;br /&gt;
&lt;br /&gt;
To make the &amp;quot;BLOB&amp;quot; type work with postgresql, we made the following changes:&lt;br /&gt;
# change blob field mapping to Java byte[] &lt;br /&gt;
# avoid using the &amp;lt;tt&amp;gt;@Lob&amp;lt;/tt&amp;gt; annotation&lt;br /&gt;
# add this element in hibernate.cfg.xml&lt;br /&gt;
 &amp;lt;property name=&amp;quot;hibernate.jdbc.use_streams_for_binary&amp;quot;&amp;gt;true&amp;lt;/property&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Unit Tests ===&lt;br /&gt;
&lt;br /&gt;
Unit tests for hibernate are found in &amp;lt;tt&amp;gt;org.opentaps.tests.entity.HibernateTests&amp;lt;/tt&amp;gt; in the opentaps-tests component.&lt;br /&gt;
&lt;br /&gt;
== Learning More ==&lt;br /&gt;
&lt;br /&gt;
The best way to learn more about how to use hibernate with opentaps is to look through the unit tests in &amp;lt;tt&amp;gt;org.opentaps.tests.entity.HibernateTests&amp;lt;/tt&amp;gt; as an example.&lt;/div&gt;</summary>
		<author><name>Spark</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=Opentaps_Hibernate_Integration&amp;diff=5041</id>
		<title>Opentaps Hibernate Integration</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=Opentaps_Hibernate_Integration&amp;diff=5041"/>
		<updated>2009-11-21T04:09:09Z</updated>

		<summary type="html">&lt;p&gt;Spark: /* Caching */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Beginning with opentaps version 1.4, [http://www.hibernate.org Hibernate] will be available as a persistence tool alongside with the original ofbiz entity engine.  Hibernate is a more object oriented persistence framework and better suited for the new [[Domain Driven Architecture]], while the ofbiz entity engine will continue to be supported for legacy features from both ofbiz and opentaps.  In this document, we will review how the hibernate integration in opentaps works.&lt;br /&gt;
&lt;br /&gt;
== Working with Hibernate in opentaps ==&lt;br /&gt;
&lt;br /&gt;
=== Generating Hibernate Configuration Files ===&lt;br /&gt;
&lt;br /&gt;
After changing or defining new entities in your &amp;lt;tt&amp;gt;entitymodel.xml&amp;lt;/tt&amp;gt; files, you need to generate new Java classes for your entities with&lt;br /&gt;
 $ ant make-base-entities&lt;br /&gt;
&lt;br /&gt;
This command updates the Java classes defined in &amp;lt;tt&amp;gt;org.opentaps.domain.base.entities&amp;lt;/tt&amp;gt;, including their hibernate annotations, and the &amp;lt;tt&amp;gt;hibernate.cfg.xml&amp;lt;/tt&amp;gt; for integrating with hibernate.  (If you use a repository management system, you must commit both and you Java classes and the updated &amp;lt;tt&amp;gt;hibernate.cfg.xml&amp;lt;/tt&amp;gt; files.)&lt;br /&gt;
&lt;br /&gt;
{{note|Important|Be sure to reference the JARs from &amp;lt;tt&amp;gt;/hot-deploy/opentaps-common/lib/hibernate&amp;lt;/tt&amp;gt; in your Ant build file, or else during build it will not be able to locate the appropriate Hibernate files.}}&lt;br /&gt;
&lt;br /&gt;
=== Accessing Entities with Hibernate ===&lt;br /&gt;
&lt;br /&gt;
{{tip|Tip|If you are developing in Eclipse, when using Hibernate make sure to run the ant task &amp;lt;tt&amp;gt;make-base-entities&amp;lt;/tt&amp;gt; immediately after you are done defining new entities. Also make sure you refresh the Eclipse project so that it picks up the new Hibernate POJOs for code-assist.}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To use hibernate to access your entities, you will need an &amp;lt;tt&amp;gt;org.opentaps.foundation.entity.hibernate.Session&amp;lt;/tt&amp;gt;, which is an extension of the &amp;lt;tt&amp;gt;org.hibernate.Session&amp;lt;/tt&amp;gt; class.  You can obtain it from the Infrastructure class like this:&lt;br /&gt;
        session = infrastructure.getSession();&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;Infrastructure&amp;lt;/tt&amp;gt; must be created from &amp;lt;tt&amp;gt;dispatcher&amp;lt;/tt&amp;gt; in order to obtain the hibernate session.&lt;br /&gt;
&lt;br /&gt;
In situations where you are passing through the service engine the &amp;lt;tt&amp;gt;dispatcher&amp;lt;/tt&amp;gt; is obtained from the &amp;lt;tt&amp;gt;DispatchContext&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
        public static Map myNewService(DispatchContext dctx, Map context) {&lt;br /&gt;
            LocalDispatcher dispatcher = dctx.getDispatcher();&lt;br /&gt;
    &lt;br /&gt;
            try {&lt;br /&gt;
                Infrastructure infrastructure = new Infrastructure(dispatcher);&lt;br /&gt;
                Session session = infrastructure.getSession();&lt;br /&gt;
            } catch (InfrastructureException e) {&lt;br /&gt;
                // TODO Auto-generated catch block&lt;br /&gt;
                e.printStackTrace();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
In situations where you are bypassing the service engine and accessing the Java method directly the &amp;lt;tt&amp;gt;dispatcher&amp;lt;/tt&amp;gt; is obtained from &amp;lt;tt&amp;gt;HttpServletRequest&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
    public static Map myNewService(HttpServletRequest request, HttpServletResponse response) {&lt;br /&gt;
        LocalDispatcher dispatcher = (LocalDispatcher) request.getAttribute(&amp;quot;dispatcher&amp;quot;);&lt;br /&gt;
    &lt;br /&gt;
        try {&lt;br /&gt;
            Infrastructure infrastructure = new Infrastructure(dispatcher);&lt;br /&gt;
            Session session = infrastructure.getSession();&lt;br /&gt;
        } catch (InfrastructureException e) {&lt;br /&gt;
            // TODO Auto-generated catch block&lt;br /&gt;
            e.printStackTrace();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
Then, you can work with it as if it were a Hibernate &amp;lt;tt&amp;gt;Session&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
        Transaction tx = session.beginTransaction();&lt;br /&gt;
        TestEntity newTestEntity = new TestEntity();&lt;br /&gt;
        newTestEntity.setTestStringField(&amp;quot;testInsertTestEntity string field&amp;quot;);&lt;br /&gt;
        newTestEntity.setCreatedStamp(UtilDateTime.nowTimestamp());&lt;br /&gt;
        session.save(newTestEntity);&lt;br /&gt;
        tx.commit();&lt;br /&gt;
        session.flush();&lt;br /&gt;
        // ...&lt;br /&gt;
        TestEntity loadEntity = (TestEntity) session.load(TestEntity.class, newTestEntity.getTestId());&lt;br /&gt;
        // ...&lt;br /&gt;
        String hql = &amp;quot;from TestEntity eo where eo.testId='&amp;quot; + testEntityId2 + &amp;quot;'&amp;quot;;&lt;br /&gt;
        Query query = session.createQuery(hql);&lt;br /&gt;
        List&amp;lt;TestEntity&amp;gt; list = query.list()&lt;br /&gt;
 &lt;br /&gt;
You do not need to close your JDBC connection manually with the opentaps Session, however.  When you call&lt;br /&gt;
            session.close();&lt;br /&gt;
It will do it for you automatically.&lt;br /&gt;
&lt;br /&gt;
=== Traversing Related Entities ===&lt;br /&gt;
&lt;br /&gt;
opentaps will automatically create the relationship annotations, such as @OneToMany, @ManyToMany, and @Join, for your Java classes.&lt;br /&gt;
&lt;br /&gt;
To get related entities, use the hibernate query language (HQL):&lt;br /&gt;
    String hql = &amp;quot;from TestEntityItem eo where eo.testEntity.testId='&amp;quot; + testEntity.getTestId() + &amp;quot;'&amp;quot;&lt;br /&gt;
               + &amp;quot; and eo.testEntityItemSeqId in (&amp;quot; + testEntityItemSeqIds + &amp;quot;)&amp;quot;;&lt;br /&gt;
    Query query = session.createQuery(hql);&lt;br /&gt;
    List&amp;lt;TestEntityItem&amp;gt; list = query.list();&lt;br /&gt;
&lt;br /&gt;
Or use the getter methods in the base entities:&lt;br /&gt;
    List&amp;lt;TestEntityItem&amp;gt; list = testEntity.getTestEntityItems();&lt;br /&gt;
&lt;br /&gt;
Note that hibernate will automatically load related entities for you, so the getRelated  methods from Repository which were designed for the ofbiz entity engine are no longer needed when you work with hibernate.&lt;br /&gt;
&lt;br /&gt;
=== Working with View Entities ===&lt;br /&gt;
&lt;br /&gt;
Once a view entity has been defined in &amp;lt;tt&amp;gt;entitymodel.xml&amp;lt;/tt&amp;gt;, you can access it as any other Java object from hibernate, for example:&lt;br /&gt;
        Query query = session.createQuery(&amp;quot;from TestEntityAndItem eo where eo.testId='&amp;quot; &lt;br /&gt;
                    + testEntityId + &amp;quot;' order by eo.testEntityItemSeqId&amp;quot;);&lt;br /&gt;
        List&amp;lt;TestEntityAndItem&amp;gt; list = query.list();&lt;br /&gt;
        &lt;br /&gt;
The opentaps  Session, which extends the hibernate Session, will automatically create the SQL for accessing the view entity.&lt;br /&gt;
&lt;br /&gt;
=== Using Transactions ===&lt;br /&gt;
&lt;br /&gt;
You should use the transaction manager configured in the ofbiz entity engine through the &amp;lt;tt&amp;gt;[http://java.sun.com/j2ee/sdk_1.3/techdocs/api/javax/transaction/UserTransaction.html UserTransaction]&amp;lt;/tt&amp;gt;  class.  In the entity engine, the transaction manager is configured as:&lt;br /&gt;
  &amp;lt;transaction-factory class=&amp;quot;org.ofbiz.geronimo.GeronimoTransactionFactory&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is obtained from the ofbiz &amp;lt;tt&amp;gt;TransactionFactory&amp;lt;/tt&amp;gt; by our &amp;lt;tt&amp;gt;Session&amp;lt;/tt&amp;gt; and used the same way as a hibernate transaction:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     UserTransaction tx = session.beginUserTransaction();&lt;br /&gt;
     // do something useful&lt;br /&gt;
     tx.commit();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Auto Generating ID Values ===&lt;br /&gt;
&lt;br /&gt;
ofbiz keeps track of auto generated sequence IDs in an entity called &amp;lt;tt&amp;gt;SequenceValueItem&amp;lt;/tt&amp;gt;  To make sure that the auto generated sequence IDs from hibernate and the ofbiz entity engine work well together, we have created an &amp;lt;tt&amp;gt;OpentapsIdentifierGenerator&amp;lt;/tt&amp;gt; which also uses the same &amp;lt;tt&amp;gt;SequenceValueItem&amp;lt;/tt&amp;gt; to obtain the next sequential ID.  This ID generator is wired to the base entity POJO Java objects with hibernate annotations, like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 @org.hibernate.annotations.GenericGenerator(name=&amp;quot;Party_GEN&amp;quot;,  strategy=&amp;quot;org.opentaps.foundation.entity.hibernate.OpentapsIdentifierGenerator&amp;quot;)&lt;br /&gt;
 @GeneratedValue(generator=&amp;quot;Party_GEN&amp;quot;)   &lt;br /&gt;
 @Id&lt;br /&gt;
    &lt;br /&gt;
 @Column(name=&amp;quot;PARTY_ID&amp;quot;)&lt;br /&gt;
    &lt;br /&gt;
 private String partyId;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So that a &amp;lt;tt&amp;gt;partyId&amp;lt;/tt&amp;gt; field is automatically set for you.&lt;br /&gt;
&lt;br /&gt;
You can also ask the &amp;lt;tt&amp;gt;Session&amp;lt;/tt&amp;gt; to generate a particular sequence ID for you:&lt;br /&gt;
 String testEntityItemSeqId = session.getNextSeqId(&amp;quot;TestEntityItemSeqId&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
This can be helpful when you have complex keys with several fields, and you want the secondary key fields to be auto sequenced as well.&lt;br /&gt;
&lt;br /&gt;
=== Support for OFBIZ EECA's ===&lt;br /&gt;
&lt;br /&gt;
ofbiz EECA's are supported with custom event listeners which are registered with hibernate when &amp;lt;tt&amp;gt;Infrastructure.getSessionFactory(String delegatorName)&amp;lt;/tt&amp;gt; is called, usually during the initial startup.  These event listeners will run ofbiz services defined in &amp;lt;tt&amp;gt;eeca.xml&amp;lt;/tt&amp;gt;'s  when hibernate is used to update the same entities.&lt;br /&gt;
&lt;br /&gt;
=== Caching ===&lt;br /&gt;
Our caching system now support ofbiz &amp;lt;-&amp;gt; hibernate mutual cache clearing. It mean it will sync hibernate cache on you update GenericValue with ofbiz entity engine, and vice versa. The hibernate cache configuration is locate in HibernateCfg.ftl (it also in hibernate.cfg.xml) as following:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  &amp;lt;property name=&amp;quot;hibernate.search.worker.execution&amp;quot;&amp;gt;async&amp;lt;/property&amp;gt;&lt;br /&gt;
  &amp;lt;property name=&amp;quot;hibernate.cache.use_query_cache&amp;quot;&amp;gt;true&amp;lt;/property&amp;gt;&lt;br /&gt;
  &amp;lt;property name=&amp;quot;hibernate.cache.use_second_level_cache&amp;quot;&amp;gt;true&amp;lt;/property&amp;gt;&lt;br /&gt;
  &amp;lt;property name=&amp;quot;hibernate.search.worker.buffer_queue.max&amp;quot;&amp;gt;5&amp;lt;/property&amp;gt;&lt;br /&gt;
  &amp;lt;property name=&amp;quot;hibernate.search.worker.thread_pool.size&amp;quot;&amp;gt;5&amp;lt;/property&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
you can disable the caching feature by remove these lines (both HibernateCfg.ftl and hibernate.cfg.xml).&lt;br /&gt;
&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
{{note|Important|The entities of current open session will not update when it changed by ofbiz entity engine after session open, you must using open a new session to get fresh object. Creating a session is not expensive, keeping one alive a long time is maybe less expensive.}}&lt;br /&gt;
&lt;br /&gt;
=== Using Hibernate without the OFBIZ Entity Engine ===&lt;br /&gt;
&lt;br /&gt;
You can also use hibernate without the ofbiz entity engine by adding your Java objects to the template opentaps uses to generate the hibernate configuration files, &amp;lt;tt&amp;gt;hot-deploy/opentaps-common/templates/HibernateCfg.ftl&amp;lt;/tt&amp;gt;.  Simply put your Java objects after the &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  &amp;lt;#list&amp;gt;&lt;br /&gt;
    ...&lt;br /&gt;
  &amp;lt;/#list&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
directives in the file, like in the following example:    &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;!DOCTYPE hibernate-configuration PUBLIC &amp;quot;-//Hibernate/Hibernate Configuration DTD 3.0//EN&amp;quot; &amp;quot;http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;hibernate-configuration&amp;gt;&lt;br /&gt;
  &amp;lt;session-factory&amp;gt;&lt;br /&gt;
  &amp;lt;property name=&amp;quot;hibernate.connection.provider_class&amp;quot;&amp;gt;org.opentaps.foundation.entity.hibernate.OpentapsConnectionProvider&amp;lt;/property&amp;gt;  &lt;br /&gt;
  &amp;lt;property name=&amp;quot;hibernate.transaction.factory_class&amp;quot;&amp;gt;org.opentaps.foundation.entity.hibernate.OpentapsTransactionFactory&amp;lt;/property&amp;gt;&lt;br /&gt;
  &amp;lt;property name=&amp;quot;hibernate.transaction.manager_lookup_class&amp;quot;&amp;gt;org.opentaps.foundation.entity.hibernate.OpentapsTransactionManagerLookup&amp;lt;/property&amp;gt;  &lt;br /&gt;
  &amp;lt;property name=&amp;quot;hibernate.search.default.directory_provider&amp;quot;&amp;gt;org.hibernate.search.store.FSDirectoryProvider&amp;lt;/property&amp;gt;&lt;br /&gt;
&amp;lt;#list entities as entity&amp;gt;&lt;br /&gt;
  &amp;lt;mapping class=&amp;quot;org.opentaps.domain.base.entities.${entity}&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/#list&amp;gt;&lt;br /&gt;
  &amp;lt;mapping class=&amp;quot;org.opentaps.domain.base.entities.MyPojo1&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;mapping class=&amp;quot;org.opentaps.domain.base.entities.MyPojo2&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;/session-factory&amp;gt;&lt;br /&gt;
&amp;lt;/hibernate-configuration&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
opentaps will then create the hibernate configuration file for each database and include your Java objects in it.  However, you would not be able to access these Java objects as generic values from the ofbiz entity engine.&lt;br /&gt;
&lt;br /&gt;
== Under the Hood: How It Works ==&lt;br /&gt;
&lt;br /&gt;
=== Base Class Annotations ===&lt;br /&gt;
&lt;br /&gt;
In opentaps version 1.4, the entity model XML from the ofbiz entity engine is still used as the base definition for all entities.  The opentaps POJO generator is used to create [[Base Entity Classes|base Java objects]] automatically from these entity definitions.  This POJO generator will also create the annotations which hibernate can then use to map those base objects to the database persistence layer.  The definitions of the annotations can be found in &amp;lt;tt&amp;gt;BaseEntity.ftl&amp;lt;/tt&amp;gt; file used by the POJO generator.&lt;br /&gt;
&lt;br /&gt;
=== How Hibernate Configuration Files are Generated ===&lt;br /&gt;
&lt;br /&gt;
The POJO Generator will use &amp;lt;tt&amp;gt;hot-deploy/opentaps-common/templates/HibernateCfg.ftl&amp;lt;/tt&amp;gt; to generate a base hibernate configuration file in &amp;lt;tt&amp;gt;hot-deploy/opentaps-common/config/hibernate.cfg.xml&amp;lt;/tt&amp;gt;  When opentaps is started, the following new container in &amp;lt;tt&amp;gt;framework/base/config/ofbiz-containers.xml&amp;lt;/tt&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    &amp;lt;container name=&amp;quot;hibernate-container&amp;quot; class=&amp;quot;org.opentaps.common.container.HibernateContainer&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;property name=&amp;quot;delegator-name&amp;quot; value=&amp;quot;default&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;/container&amp;gt;    &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will generate all the hibernate configuration XML files in the &amp;lt;tt&amp;gt;hot-deploy/opentaps/config/&amp;lt;/tt&amp;gt; directory for each data source in your entity engine XML file.  For example, it will generate a &amp;lt;tt&amp;gt;localmysql.cfg.xml&amp;lt;/tt&amp;gt;, a &amp;lt;tt&amp;gt;localpostgres.cfg.xml&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How We Get the Hibernate Session ===&lt;br /&gt;
&lt;br /&gt;
The opentaps &amp;lt;tt&amp;gt;Infrastructure&amp;lt;/tt&amp;gt; Class maintains a Map of delegatorName and hibernate SessionFactory objects.  Each SessionFactory is created for its corresponding delegatorName the first time it is requested from the &amp;lt;tt&amp;gt;Infrastructure.getSessionFactory(delegatorName)&amp;lt;/tt&amp;gt; method.  This SessionFactory is created from ofbiz entity engine configurations:&lt;br /&gt;
* The &amp;lt;tt&amp;gt;HibernateContainer&amp;lt;/tt&amp;gt; in &amp;lt;tt&amp;gt;ofbiz-containers.xml&amp;lt;/tt&amp;gt; has a property called &amp;lt;tt&amp;gt;delegator-name&amp;lt;/tt&amp;gt;&lt;br /&gt;
* From this delegator, we get the data source defined in &amp;lt;tt&amp;gt;entityengine.xml&amp;lt;/tt&amp;gt; for the default group helper name.  This is set to &amp;lt;tt&amp;gt;org.ofbiz&amp;lt;/tt&amp;gt; by default in the &amp;lt;tt&amp;gt;Infrastructure&amp;lt;/tt&amp;gt; class and is the &amp;lt;tt&amp;gt;group&amp;lt;/tt&amp;gt; attribute of the &amp;lt;tt&amp;gt;entitygroup.xml&amp;lt;/tt&amp;gt; definitions in ofbiz:&lt;br /&gt;
  &amp;lt;entity-group group=&amp;quot;org.ofbiz&amp;quot; entity=&amp;quot;AcctgTagEnumType&amp;quot;/&amp;gt;&lt;br /&gt;
In &amp;lt;tt&amp;gt;entityengine.xml&amp;lt;/tt&amp;gt;, you map a data source to each group:&lt;br /&gt;
    &amp;lt;delegator name=&amp;quot;default&amp;quot; entity-model-reader=&amp;quot;main&amp;quot; entity-group-reader=&amp;quot;main&amp;quot; entity-eca-reader=&amp;quot;main&amp;quot; distributed-cache-clear-enabled=&amp;quot;false&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;group-map group-name=&amp;quot;org.ofbiz&amp;quot; datasource-name=&amp;quot;localmysql&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;/delegator&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So, we are basically following the entity engine from the delegator to the data source via the group.&lt;br /&gt;
* Once we have the data source, we can create the SessionFactory from the hibernate.cfg.xml for that data source.  For example, if your data source is &amp;quot;localmysql&amp;quot;, we will create the SessionFactory from the &amp;lt;tt&amp;gt;localmysql.cfg.xml&amp;lt;/tt&amp;gt;   created by the &amp;lt;tt&amp;gt;HibernateContainer&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;HibernateContainer&amp;lt;/tt&amp;gt;, which loads on startup, will cause a SessionFactory to be loaded for the delegator in the &amp;lt;tt&amp;gt;delegator-name&amp;lt;/tt&amp;gt; attribute.  Once this SessionFactory is loaded, it will be available for future use.  Additional session factories can be obtained later by calling the &amp;lt;tt&amp;gt;getSessionFactory&amp;lt;/tt&amp;gt; directly.&lt;br /&gt;
&lt;br /&gt;
When the &amp;lt;tt&amp;gt;Infrastructure.getSession()&amp;lt;/tt&amp;gt; method is called,  it will use the delegator already in the Infrastructure object to open a JDBC connection first, and then use that JDBC connection and the SessionFactory for the delegator to return a Session.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;Infrastructure.getSession()&amp;lt;/tt&amp;gt; will return an &amp;lt;tt&amp;gt;org.opentaps.foundation.entity.hibernate.Session&amp;lt;/tt&amp;gt;, which extends the hibernate Session with the following differences:&lt;br /&gt;
* when the session is closed, the JDBC connection is also automatically closed&lt;br /&gt;
* when a Query is created, this Session will check if the query is on an entity engine view entity and construct the Query from native SQL first&lt;br /&gt;
&lt;br /&gt;
=== View Entities ===&lt;br /&gt;
&lt;br /&gt;
View entities are supported with @NamedNativeQuery annotations in the base entity Java classes, which are automatically generated by the opentaps POJO Generator.&lt;br /&gt;
&lt;br /&gt;
=== Encryption ===&lt;br /&gt;
&lt;br /&gt;
The ofbiz delegator allows you to set a field to be encrypted in the database with the &amp;lt;tt&amp;gt;encrypt=&amp;quot;true&amp;quot;&amp;lt;/tt&amp;gt; attribute in the &amp;lt;tt&amp;gt;field&amp;lt;/tt&amp;gt; tag of an entity definition.  The opentaps hibernate will support the same encryption/decryption algorithm, so that encrypted values can be stored with the delegator and decrypted when it's retrieved with hibernate or vice versa.  This is done by:&lt;br /&gt;
# When an object is being stored, the &amp;lt;tt&amp;gt;EcaCommEvent.beforeSave&amp;lt;/tt&amp;gt; Method will come for the object to an ofbiz GenericValue and then use the ofbiz delegator to encrypt it.&lt;br /&gt;
# When an object is retrieved from the database, the &amp;lt;tt&amp;gt;Session.load&amp;lt;/tt&amp;gt; will call the &amp;lt;tt&amp;gt;HibernateUtil.decryptField&amp;lt;/tt&amp;gt; to decrypt it.&lt;br /&gt;
&lt;br /&gt;
=== Transaction Management ===&lt;br /&gt;
&lt;br /&gt;
To maintain compatibility with the ofbiz entity engine's transaction manager and connection pool providers, we have defined transaction manager look up, transaction factory, and connection provider classes which use the ofbiz transaction manager and transaction factory to begin transactions.  These are defined in the &amp;lt;tt&amp;gt;hibernate.cfg.xml&amp;lt;/tt&amp;gt; configuration file.  They allow you to mix delegator and hibernate transaction codes as in this following example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        UserTransaction tx = session.beginUserTransaction();&lt;br /&gt;
        TestEntity useIdentifierTestEntity = new TestEntity();&lt;br /&gt;
        useIdentifierTestEntity.setTestStringField(&amp;quot;Use IdentifierGenerator string field&amp;quot;);&lt;br /&gt;
        session.save(useIdentifierTestEntity);&lt;br /&gt;
        String getNextSeqIdTestEntityId = delegator.getNextSeqId(&amp;quot;TestEntity&amp;quot;);&lt;br /&gt;
        GenericValue useGetNextSeqIdTestEntity = delegator.create(&amp;quot;TestEntity&amp;quot;,&lt;br /&gt;
                UtilMisc.toMap(&amp;quot;testId&amp;quot;, getNextSeqIdTestEntityId,  &amp;quot;testStringField&amp;quot;, &amp;quot;Use getNextSeqId string field&amp;quot;));&lt;br /&gt;
        session.flush();&lt;br /&gt;
        tx.commit();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Support for BLOBs ===&lt;br /&gt;
&lt;br /&gt;
To make the &amp;quot;BLOB&amp;quot; type work with postgresql, we made the following changes:&lt;br /&gt;
# change blob field mapping to Java byte[] &lt;br /&gt;
# avoid using the &amp;lt;tt&amp;gt;@Lob&amp;lt;/tt&amp;gt; annotation&lt;br /&gt;
# add this element in hibernate.cfg.xml&lt;br /&gt;
 &amp;lt;property name=&amp;quot;hibernate.jdbc.use_streams_for_binary&amp;quot;&amp;gt;true&amp;lt;/property&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Unit Tests ===&lt;br /&gt;
&lt;br /&gt;
Unit tests for hibernate are found in &amp;lt;tt&amp;gt;org.opentaps.tests.entity.HibernateTests&amp;lt;/tt&amp;gt; in the opentaps-tests component.&lt;br /&gt;
&lt;br /&gt;
== Learning More ==&lt;br /&gt;
&lt;br /&gt;
The best way to learn more about how to use hibernate with opentaps is to look through the unit tests in &amp;lt;tt&amp;gt;org.opentaps.tests.entity.HibernateTests&amp;lt;/tt&amp;gt; as an example.&lt;/div&gt;</summary>
		<author><name>Spark</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=Opentaps_Hibernate_Integration&amp;diff=5040</id>
		<title>Opentaps Hibernate Integration</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=Opentaps_Hibernate_Integration&amp;diff=5040"/>
		<updated>2009-11-21T04:00:51Z</updated>

		<summary type="html">&lt;p&gt;Spark: /* Caching */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Beginning with opentaps version 1.4, [http://www.hibernate.org Hibernate] will be available as a persistence tool alongside with the original ofbiz entity engine.  Hibernate is a more object oriented persistence framework and better suited for the new [[Domain Driven Architecture]], while the ofbiz entity engine will continue to be supported for legacy features from both ofbiz and opentaps.  In this document, we will review how the hibernate integration in opentaps works.&lt;br /&gt;
&lt;br /&gt;
== Working with Hibernate in opentaps ==&lt;br /&gt;
&lt;br /&gt;
=== Generating Hibernate Configuration Files ===&lt;br /&gt;
&lt;br /&gt;
After changing or defining new entities in your &amp;lt;tt&amp;gt;entitymodel.xml&amp;lt;/tt&amp;gt; files, you need to generate new Java classes for your entities with&lt;br /&gt;
 $ ant make-base-entities&lt;br /&gt;
&lt;br /&gt;
This command updates the Java classes defined in &amp;lt;tt&amp;gt;org.opentaps.domain.base.entities&amp;lt;/tt&amp;gt;, including their hibernate annotations, and the &amp;lt;tt&amp;gt;hibernate.cfg.xml&amp;lt;/tt&amp;gt; for integrating with hibernate.  (If you use a repository management system, you must commit both and you Java classes and the updated &amp;lt;tt&amp;gt;hibernate.cfg.xml&amp;lt;/tt&amp;gt; files.)&lt;br /&gt;
&lt;br /&gt;
{{note|Important|Be sure to reference the JARs from &amp;lt;tt&amp;gt;/hot-deploy/opentaps-common/lib/hibernate&amp;lt;/tt&amp;gt; in your Ant build file, or else during build it will not be able to locate the appropriate Hibernate files.}}&lt;br /&gt;
&lt;br /&gt;
=== Accessing Entities with Hibernate ===&lt;br /&gt;
&lt;br /&gt;
{{tip|Tip|If you are developing in Eclipse, when using Hibernate make sure to run the ant task &amp;lt;tt&amp;gt;make-base-entities&amp;lt;/tt&amp;gt; immediately after you are done defining new entities. Also make sure you refresh the Eclipse project so that it picks up the new Hibernate POJOs for code-assist.}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To use hibernate to access your entities, you will need an &amp;lt;tt&amp;gt;org.opentaps.foundation.entity.hibernate.Session&amp;lt;/tt&amp;gt;, which is an extension of the &amp;lt;tt&amp;gt;org.hibernate.Session&amp;lt;/tt&amp;gt; class.  You can obtain it from the Infrastructure class like this:&lt;br /&gt;
        session = infrastructure.getSession();&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;Infrastructure&amp;lt;/tt&amp;gt; must be created from &amp;lt;tt&amp;gt;dispatcher&amp;lt;/tt&amp;gt; in order to obtain the hibernate session.&lt;br /&gt;
&lt;br /&gt;
In situations where you are passing through the service engine the &amp;lt;tt&amp;gt;dispatcher&amp;lt;/tt&amp;gt; is obtained from the &amp;lt;tt&amp;gt;DispatchContext&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
        public static Map myNewService(DispatchContext dctx, Map context) {&lt;br /&gt;
            LocalDispatcher dispatcher = dctx.getDispatcher();&lt;br /&gt;
    &lt;br /&gt;
            try {&lt;br /&gt;
                Infrastructure infrastructure = new Infrastructure(dispatcher);&lt;br /&gt;
                Session session = infrastructure.getSession();&lt;br /&gt;
            } catch (InfrastructureException e) {&lt;br /&gt;
                // TODO Auto-generated catch block&lt;br /&gt;
                e.printStackTrace();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
In situations where you are bypassing the service engine and accessing the Java method directly the &amp;lt;tt&amp;gt;dispatcher&amp;lt;/tt&amp;gt; is obtained from &amp;lt;tt&amp;gt;HttpServletRequest&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
    public static Map myNewService(HttpServletRequest request, HttpServletResponse response) {&lt;br /&gt;
        LocalDispatcher dispatcher = (LocalDispatcher) request.getAttribute(&amp;quot;dispatcher&amp;quot;);&lt;br /&gt;
    &lt;br /&gt;
        try {&lt;br /&gt;
            Infrastructure infrastructure = new Infrastructure(dispatcher);&lt;br /&gt;
            Session session = infrastructure.getSession();&lt;br /&gt;
        } catch (InfrastructureException e) {&lt;br /&gt;
            // TODO Auto-generated catch block&lt;br /&gt;
            e.printStackTrace();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
Then, you can work with it as if it were a Hibernate &amp;lt;tt&amp;gt;Session&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
        Transaction tx = session.beginTransaction();&lt;br /&gt;
        TestEntity newTestEntity = new TestEntity();&lt;br /&gt;
        newTestEntity.setTestStringField(&amp;quot;testInsertTestEntity string field&amp;quot;);&lt;br /&gt;
        newTestEntity.setCreatedStamp(UtilDateTime.nowTimestamp());&lt;br /&gt;
        session.save(newTestEntity);&lt;br /&gt;
        tx.commit();&lt;br /&gt;
        session.flush();&lt;br /&gt;
        // ...&lt;br /&gt;
        TestEntity loadEntity = (TestEntity) session.load(TestEntity.class, newTestEntity.getTestId());&lt;br /&gt;
        // ...&lt;br /&gt;
        String hql = &amp;quot;from TestEntity eo where eo.testId='&amp;quot; + testEntityId2 + &amp;quot;'&amp;quot;;&lt;br /&gt;
        Query query = session.createQuery(hql);&lt;br /&gt;
        List&amp;lt;TestEntity&amp;gt; list = query.list()&lt;br /&gt;
 &lt;br /&gt;
You do not need to close your JDBC connection manually with the opentaps Session, however.  When you call&lt;br /&gt;
            session.close();&lt;br /&gt;
It will do it for you automatically.&lt;br /&gt;
&lt;br /&gt;
=== Traversing Related Entities ===&lt;br /&gt;
&lt;br /&gt;
opentaps will automatically create the relationship annotations, such as @OneToMany, @ManyToMany, and @Join, for your Java classes.&lt;br /&gt;
&lt;br /&gt;
To get related entities, use the hibernate query language (HQL):&lt;br /&gt;
    String hql = &amp;quot;from TestEntityItem eo where eo.testEntity.testId='&amp;quot; + testEntity.getTestId() + &amp;quot;'&amp;quot;&lt;br /&gt;
               + &amp;quot; and eo.testEntityItemSeqId in (&amp;quot; + testEntityItemSeqIds + &amp;quot;)&amp;quot;;&lt;br /&gt;
    Query query = session.createQuery(hql);&lt;br /&gt;
    List&amp;lt;TestEntityItem&amp;gt; list = query.list();&lt;br /&gt;
&lt;br /&gt;
Or use the getter methods in the base entities:&lt;br /&gt;
    List&amp;lt;TestEntityItem&amp;gt; list = testEntity.getTestEntityItems();&lt;br /&gt;
&lt;br /&gt;
Note that hibernate will automatically load related entities for you, so the getRelated  methods from Repository which were designed for the ofbiz entity engine are no longer needed when you work with hibernate.&lt;br /&gt;
&lt;br /&gt;
=== Working with View Entities ===&lt;br /&gt;
&lt;br /&gt;
Once a view entity has been defined in &amp;lt;tt&amp;gt;entitymodel.xml&amp;lt;/tt&amp;gt;, you can access it as any other Java object from hibernate, for example:&lt;br /&gt;
        Query query = session.createQuery(&amp;quot;from TestEntityAndItem eo where eo.testId='&amp;quot; &lt;br /&gt;
                    + testEntityId + &amp;quot;' order by eo.testEntityItemSeqId&amp;quot;);&lt;br /&gt;
        List&amp;lt;TestEntityAndItem&amp;gt; list = query.list();&lt;br /&gt;
        &lt;br /&gt;
The opentaps  Session, which extends the hibernate Session, will automatically create the SQL for accessing the view entity.&lt;br /&gt;
&lt;br /&gt;
=== Using Transactions ===&lt;br /&gt;
&lt;br /&gt;
You should use the transaction manager configured in the ofbiz entity engine through the &amp;lt;tt&amp;gt;[http://java.sun.com/j2ee/sdk_1.3/techdocs/api/javax/transaction/UserTransaction.html UserTransaction]&amp;lt;/tt&amp;gt;  class.  In the entity engine, the transaction manager is configured as:&lt;br /&gt;
  &amp;lt;transaction-factory class=&amp;quot;org.ofbiz.geronimo.GeronimoTransactionFactory&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is obtained from the ofbiz &amp;lt;tt&amp;gt;TransactionFactory&amp;lt;/tt&amp;gt; by our &amp;lt;tt&amp;gt;Session&amp;lt;/tt&amp;gt; and used the same way as a hibernate transaction:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     UserTransaction tx = session.beginUserTransaction();&lt;br /&gt;
     // do something useful&lt;br /&gt;
     tx.commit();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Auto Generating ID Values ===&lt;br /&gt;
&lt;br /&gt;
ofbiz keeps track of auto generated sequence IDs in an entity called &amp;lt;tt&amp;gt;SequenceValueItem&amp;lt;/tt&amp;gt;  To make sure that the auto generated sequence IDs from hibernate and the ofbiz entity engine work well together, we have created an &amp;lt;tt&amp;gt;OpentapsIdentifierGenerator&amp;lt;/tt&amp;gt; which also uses the same &amp;lt;tt&amp;gt;SequenceValueItem&amp;lt;/tt&amp;gt; to obtain the next sequential ID.  This ID generator is wired to the base entity POJO Java objects with hibernate annotations, like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 @org.hibernate.annotations.GenericGenerator(name=&amp;quot;Party_GEN&amp;quot;,  strategy=&amp;quot;org.opentaps.foundation.entity.hibernate.OpentapsIdentifierGenerator&amp;quot;)&lt;br /&gt;
 @GeneratedValue(generator=&amp;quot;Party_GEN&amp;quot;)   &lt;br /&gt;
 @Id&lt;br /&gt;
    &lt;br /&gt;
 @Column(name=&amp;quot;PARTY_ID&amp;quot;)&lt;br /&gt;
    &lt;br /&gt;
 private String partyId;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So that a &amp;lt;tt&amp;gt;partyId&amp;lt;/tt&amp;gt; field is automatically set for you.&lt;br /&gt;
&lt;br /&gt;
You can also ask the &amp;lt;tt&amp;gt;Session&amp;lt;/tt&amp;gt; to generate a particular sequence ID for you:&lt;br /&gt;
 String testEntityItemSeqId = session.getNextSeqId(&amp;quot;TestEntityItemSeqId&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
This can be helpful when you have complex keys with several fields, and you want the secondary key fields to be auto sequenced as well.&lt;br /&gt;
&lt;br /&gt;
=== Support for OFBIZ EECA's ===&lt;br /&gt;
&lt;br /&gt;
ofbiz EECA's are supported with custom event listeners which are registered with hibernate when &amp;lt;tt&amp;gt;Infrastructure.getSessionFactory(String delegatorName)&amp;lt;/tt&amp;gt; is called, usually during the initial startup.  These event listeners will run ofbiz services defined in &amp;lt;tt&amp;gt;eeca.xml&amp;lt;/tt&amp;gt;'s  when hibernate is used to update the same entities.&lt;br /&gt;
&lt;br /&gt;
=== Caching ===&lt;br /&gt;
Our caching system now support ofbiz &amp;lt;-&amp;gt; hibernate mutual cache clearing. It mean it will sync hibernate cache on you update GenericValue with ofbiz entity engine, and vice versa. The hibernate cache configuration is locate in HibernateCfg.ftl (it also in hibernate.cfg.xml) as following:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  &amp;lt;property name=&amp;quot;hibernate.search.worker.execution&amp;quot;&amp;gt;async&amp;lt;/property&amp;gt;&lt;br /&gt;
  &amp;lt;property name=&amp;quot;hibernate.cache.use_query_cache&amp;quot;&amp;gt;true&amp;lt;/property&amp;gt;&lt;br /&gt;
  &amp;lt;property name=&amp;quot;hibernate.cache.use_second_level_cache&amp;quot;&amp;gt;true&amp;lt;/property&amp;gt;&lt;br /&gt;
  &amp;lt;property name=&amp;quot;hibernate.search.worker.buffer_queue.max&amp;quot;&amp;gt;5&amp;lt;/property&amp;gt;&lt;br /&gt;
  &amp;lt;property name=&amp;quot;hibernate.search.worker.thread_pool.size&amp;quot;&amp;gt;5&amp;lt;/property&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
you can disable the caching feature by remove these lines (both HibernateCfg.ftl and hibernate.cfg.xml).&lt;br /&gt;
&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
{{note|Important|The entities of current open session will not update when it change by ofbiz entity engine, you must using open a new session to get fresh object. and the best practise is also close your session when it finish the job.}}&lt;br /&gt;
&lt;br /&gt;
=== Using Hibernate without the OFBIZ Entity Engine ===&lt;br /&gt;
&lt;br /&gt;
You can also use hibernate without the ofbiz entity engine by adding your Java objects to the template opentaps uses to generate the hibernate configuration files, &amp;lt;tt&amp;gt;hot-deploy/opentaps-common/templates/HibernateCfg.ftl&amp;lt;/tt&amp;gt;.  Simply put your Java objects after the &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  &amp;lt;#list&amp;gt;&lt;br /&gt;
    ...&lt;br /&gt;
  &amp;lt;/#list&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
directives in the file, like in the following example:    &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;!DOCTYPE hibernate-configuration PUBLIC &amp;quot;-//Hibernate/Hibernate Configuration DTD 3.0//EN&amp;quot; &amp;quot;http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;hibernate-configuration&amp;gt;&lt;br /&gt;
  &amp;lt;session-factory&amp;gt;&lt;br /&gt;
  &amp;lt;property name=&amp;quot;hibernate.connection.provider_class&amp;quot;&amp;gt;org.opentaps.foundation.entity.hibernate.OpentapsConnectionProvider&amp;lt;/property&amp;gt;  &lt;br /&gt;
  &amp;lt;property name=&amp;quot;hibernate.transaction.factory_class&amp;quot;&amp;gt;org.opentaps.foundation.entity.hibernate.OpentapsTransactionFactory&amp;lt;/property&amp;gt;&lt;br /&gt;
  &amp;lt;property name=&amp;quot;hibernate.transaction.manager_lookup_class&amp;quot;&amp;gt;org.opentaps.foundation.entity.hibernate.OpentapsTransactionManagerLookup&amp;lt;/property&amp;gt;  &lt;br /&gt;
  &amp;lt;property name=&amp;quot;hibernate.search.default.directory_provider&amp;quot;&amp;gt;org.hibernate.search.store.FSDirectoryProvider&amp;lt;/property&amp;gt;&lt;br /&gt;
&amp;lt;#list entities as entity&amp;gt;&lt;br /&gt;
  &amp;lt;mapping class=&amp;quot;org.opentaps.domain.base.entities.${entity}&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/#list&amp;gt;&lt;br /&gt;
  &amp;lt;mapping class=&amp;quot;org.opentaps.domain.base.entities.MyPojo1&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;mapping class=&amp;quot;org.opentaps.domain.base.entities.MyPojo2&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;/session-factory&amp;gt;&lt;br /&gt;
&amp;lt;/hibernate-configuration&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
opentaps will then create the hibernate configuration file for each database and include your Java objects in it.  However, you would not be able to access these Java objects as generic values from the ofbiz entity engine.&lt;br /&gt;
&lt;br /&gt;
== Under the Hood: How It Works ==&lt;br /&gt;
&lt;br /&gt;
=== Base Class Annotations ===&lt;br /&gt;
&lt;br /&gt;
In opentaps version 1.4, the entity model XML from the ofbiz entity engine is still used as the base definition for all entities.  The opentaps POJO generator is used to create [[Base Entity Classes|base Java objects]] automatically from these entity definitions.  This POJO generator will also create the annotations which hibernate can then use to map those base objects to the database persistence layer.  The definitions of the annotations can be found in &amp;lt;tt&amp;gt;BaseEntity.ftl&amp;lt;/tt&amp;gt; file used by the POJO generator.&lt;br /&gt;
&lt;br /&gt;
=== How Hibernate Configuration Files are Generated ===&lt;br /&gt;
&lt;br /&gt;
The POJO Generator will use &amp;lt;tt&amp;gt;hot-deploy/opentaps-common/templates/HibernateCfg.ftl&amp;lt;/tt&amp;gt; to generate a base hibernate configuration file in &amp;lt;tt&amp;gt;hot-deploy/opentaps-common/config/hibernate.cfg.xml&amp;lt;/tt&amp;gt;  When opentaps is started, the following new container in &amp;lt;tt&amp;gt;framework/base/config/ofbiz-containers.xml&amp;lt;/tt&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    &amp;lt;container name=&amp;quot;hibernate-container&amp;quot; class=&amp;quot;org.opentaps.common.container.HibernateContainer&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;property name=&amp;quot;delegator-name&amp;quot; value=&amp;quot;default&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;/container&amp;gt;    &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will generate all the hibernate configuration XML files in the &amp;lt;tt&amp;gt;hot-deploy/opentaps/config/&amp;lt;/tt&amp;gt; directory for each data source in your entity engine XML file.  For example, it will generate a &amp;lt;tt&amp;gt;localmysql.cfg.xml&amp;lt;/tt&amp;gt;, a &amp;lt;tt&amp;gt;localpostgres.cfg.xml&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How We Get the Hibernate Session ===&lt;br /&gt;
&lt;br /&gt;
The opentaps &amp;lt;tt&amp;gt;Infrastructure&amp;lt;/tt&amp;gt; Class maintains a Map of delegatorName and hibernate SessionFactory objects.  Each SessionFactory is created for its corresponding delegatorName the first time it is requested from the &amp;lt;tt&amp;gt;Infrastructure.getSessionFactory(delegatorName)&amp;lt;/tt&amp;gt; method.  This SessionFactory is created from ofbiz entity engine configurations:&lt;br /&gt;
* The &amp;lt;tt&amp;gt;HibernateContainer&amp;lt;/tt&amp;gt; in &amp;lt;tt&amp;gt;ofbiz-containers.xml&amp;lt;/tt&amp;gt; has a property called &amp;lt;tt&amp;gt;delegator-name&amp;lt;/tt&amp;gt;&lt;br /&gt;
* From this delegator, we get the data source defined in &amp;lt;tt&amp;gt;entityengine.xml&amp;lt;/tt&amp;gt; for the default group helper name.  This is set to &amp;lt;tt&amp;gt;org.ofbiz&amp;lt;/tt&amp;gt; by default in the &amp;lt;tt&amp;gt;Infrastructure&amp;lt;/tt&amp;gt; class and is the &amp;lt;tt&amp;gt;group&amp;lt;/tt&amp;gt; attribute of the &amp;lt;tt&amp;gt;entitygroup.xml&amp;lt;/tt&amp;gt; definitions in ofbiz:&lt;br /&gt;
  &amp;lt;entity-group group=&amp;quot;org.ofbiz&amp;quot; entity=&amp;quot;AcctgTagEnumType&amp;quot;/&amp;gt;&lt;br /&gt;
In &amp;lt;tt&amp;gt;entityengine.xml&amp;lt;/tt&amp;gt;, you map a data source to each group:&lt;br /&gt;
    &amp;lt;delegator name=&amp;quot;default&amp;quot; entity-model-reader=&amp;quot;main&amp;quot; entity-group-reader=&amp;quot;main&amp;quot; entity-eca-reader=&amp;quot;main&amp;quot; distributed-cache-clear-enabled=&amp;quot;false&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;group-map group-name=&amp;quot;org.ofbiz&amp;quot; datasource-name=&amp;quot;localmysql&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;/delegator&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So, we are basically following the entity engine from the delegator to the data source via the group.&lt;br /&gt;
* Once we have the data source, we can create the SessionFactory from the hibernate.cfg.xml for that data source.  For example, if your data source is &amp;quot;localmysql&amp;quot;, we will create the SessionFactory from the &amp;lt;tt&amp;gt;localmysql.cfg.xml&amp;lt;/tt&amp;gt;   created by the &amp;lt;tt&amp;gt;HibernateContainer&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;HibernateContainer&amp;lt;/tt&amp;gt;, which loads on startup, will cause a SessionFactory to be loaded for the delegator in the &amp;lt;tt&amp;gt;delegator-name&amp;lt;/tt&amp;gt; attribute.  Once this SessionFactory is loaded, it will be available for future use.  Additional session factories can be obtained later by calling the &amp;lt;tt&amp;gt;getSessionFactory&amp;lt;/tt&amp;gt; directly.&lt;br /&gt;
&lt;br /&gt;
When the &amp;lt;tt&amp;gt;Infrastructure.getSession()&amp;lt;/tt&amp;gt; method is called,  it will use the delegator already in the Infrastructure object to open a JDBC connection first, and then use that JDBC connection and the SessionFactory for the delegator to return a Session.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;Infrastructure.getSession()&amp;lt;/tt&amp;gt; will return an &amp;lt;tt&amp;gt;org.opentaps.foundation.entity.hibernate.Session&amp;lt;/tt&amp;gt;, which extends the hibernate Session with the following differences:&lt;br /&gt;
* when the session is closed, the JDBC connection is also automatically closed&lt;br /&gt;
* when a Query is created, this Session will check if the query is on an entity engine view entity and construct the Query from native SQL first&lt;br /&gt;
&lt;br /&gt;
=== View Entities ===&lt;br /&gt;
&lt;br /&gt;
View entities are supported with @NamedNativeQuery annotations in the base entity Java classes, which are automatically generated by the opentaps POJO Generator.&lt;br /&gt;
&lt;br /&gt;
=== Encryption ===&lt;br /&gt;
&lt;br /&gt;
The ofbiz delegator allows you to set a field to be encrypted in the database with the &amp;lt;tt&amp;gt;encrypt=&amp;quot;true&amp;quot;&amp;lt;/tt&amp;gt; attribute in the &amp;lt;tt&amp;gt;field&amp;lt;/tt&amp;gt; tag of an entity definition.  The opentaps hibernate will support the same encryption/decryption algorithm, so that encrypted values can be stored with the delegator and decrypted when it's retrieved with hibernate or vice versa.  This is done by:&lt;br /&gt;
# When an object is being stored, the &amp;lt;tt&amp;gt;EcaCommEvent.beforeSave&amp;lt;/tt&amp;gt; Method will come for the object to an ofbiz GenericValue and then use the ofbiz delegator to encrypt it.&lt;br /&gt;
# When an object is retrieved from the database, the &amp;lt;tt&amp;gt;Session.load&amp;lt;/tt&amp;gt; will call the &amp;lt;tt&amp;gt;HibernateUtil.decryptField&amp;lt;/tt&amp;gt; to decrypt it.&lt;br /&gt;
&lt;br /&gt;
=== Transaction Management ===&lt;br /&gt;
&lt;br /&gt;
To maintain compatibility with the ofbiz entity engine's transaction manager and connection pool providers, we have defined transaction manager look up, transaction factory, and connection provider classes which use the ofbiz transaction manager and transaction factory to begin transactions.  These are defined in the &amp;lt;tt&amp;gt;hibernate.cfg.xml&amp;lt;/tt&amp;gt; configuration file.  They allow you to mix delegator and hibernate transaction codes as in this following example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        UserTransaction tx = session.beginUserTransaction();&lt;br /&gt;
        TestEntity useIdentifierTestEntity = new TestEntity();&lt;br /&gt;
        useIdentifierTestEntity.setTestStringField(&amp;quot;Use IdentifierGenerator string field&amp;quot;);&lt;br /&gt;
        session.save(useIdentifierTestEntity);&lt;br /&gt;
        String getNextSeqIdTestEntityId = delegator.getNextSeqId(&amp;quot;TestEntity&amp;quot;);&lt;br /&gt;
        GenericValue useGetNextSeqIdTestEntity = delegator.create(&amp;quot;TestEntity&amp;quot;,&lt;br /&gt;
                UtilMisc.toMap(&amp;quot;testId&amp;quot;, getNextSeqIdTestEntityId,  &amp;quot;testStringField&amp;quot;, &amp;quot;Use getNextSeqId string field&amp;quot;));&lt;br /&gt;
        session.flush();&lt;br /&gt;
        tx.commit();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Support for BLOBs ===&lt;br /&gt;
&lt;br /&gt;
To make the &amp;quot;BLOB&amp;quot; type work with postgresql, we made the following changes:&lt;br /&gt;
# change blob field mapping to Java byte[] &lt;br /&gt;
# avoid using the &amp;lt;tt&amp;gt;@Lob&amp;lt;/tt&amp;gt; annotation&lt;br /&gt;
# add this element in hibernate.cfg.xml&lt;br /&gt;
 &amp;lt;property name=&amp;quot;hibernate.jdbc.use_streams_for_binary&amp;quot;&amp;gt;true&amp;lt;/property&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Unit Tests ===&lt;br /&gt;
&lt;br /&gt;
Unit tests for hibernate are found in &amp;lt;tt&amp;gt;org.opentaps.tests.entity.HibernateTests&amp;lt;/tt&amp;gt; in the opentaps-tests component.&lt;br /&gt;
&lt;br /&gt;
== Learning More ==&lt;br /&gt;
&lt;br /&gt;
The best way to learn more about how to use hibernate with opentaps is to look through the unit tests in &amp;lt;tt&amp;gt;org.opentaps.tests.entity.HibernateTests&amp;lt;/tt&amp;gt; as an example.&lt;/div&gt;</summary>
		<author><name>Spark</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=Opentaps_Hibernate_Integration&amp;diff=5039</id>
		<title>Opentaps Hibernate Integration</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=Opentaps_Hibernate_Integration&amp;diff=5039"/>
		<updated>2009-11-21T03:58:42Z</updated>

		<summary type="html">&lt;p&gt;Spark: /* Caching */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Beginning with opentaps version 1.4, [http://www.hibernate.org Hibernate] will be available as a persistence tool alongside with the original ofbiz entity engine.  Hibernate is a more object oriented persistence framework and better suited for the new [[Domain Driven Architecture]], while the ofbiz entity engine will continue to be supported for legacy features from both ofbiz and opentaps.  In this document, we will review how the hibernate integration in opentaps works.&lt;br /&gt;
&lt;br /&gt;
== Working with Hibernate in opentaps ==&lt;br /&gt;
&lt;br /&gt;
=== Generating Hibernate Configuration Files ===&lt;br /&gt;
&lt;br /&gt;
After changing or defining new entities in your &amp;lt;tt&amp;gt;entitymodel.xml&amp;lt;/tt&amp;gt; files, you need to generate new Java classes for your entities with&lt;br /&gt;
 $ ant make-base-entities&lt;br /&gt;
&lt;br /&gt;
This command updates the Java classes defined in &amp;lt;tt&amp;gt;org.opentaps.domain.base.entities&amp;lt;/tt&amp;gt;, including their hibernate annotations, and the &amp;lt;tt&amp;gt;hibernate.cfg.xml&amp;lt;/tt&amp;gt; for integrating with hibernate.  (If you use a repository management system, you must commit both and you Java classes and the updated &amp;lt;tt&amp;gt;hibernate.cfg.xml&amp;lt;/tt&amp;gt; files.)&lt;br /&gt;
&lt;br /&gt;
{{note|Important|Be sure to reference the JARs from &amp;lt;tt&amp;gt;/hot-deploy/opentaps-common/lib/hibernate&amp;lt;/tt&amp;gt; in your Ant build file, or else during build it will not be able to locate the appropriate Hibernate files.}}&lt;br /&gt;
&lt;br /&gt;
=== Accessing Entities with Hibernate ===&lt;br /&gt;
&lt;br /&gt;
{{tip|Tip|If you are developing in Eclipse, when using Hibernate make sure to run the ant task &amp;lt;tt&amp;gt;make-base-entities&amp;lt;/tt&amp;gt; immediately after you are done defining new entities. Also make sure you refresh the Eclipse project so that it picks up the new Hibernate POJOs for code-assist.}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To use hibernate to access your entities, you will need an &amp;lt;tt&amp;gt;org.opentaps.foundation.entity.hibernate.Session&amp;lt;/tt&amp;gt;, which is an extension of the &amp;lt;tt&amp;gt;org.hibernate.Session&amp;lt;/tt&amp;gt; class.  You can obtain it from the Infrastructure class like this:&lt;br /&gt;
        session = infrastructure.getSession();&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;Infrastructure&amp;lt;/tt&amp;gt; must be created from &amp;lt;tt&amp;gt;dispatcher&amp;lt;/tt&amp;gt; in order to obtain the hibernate session.&lt;br /&gt;
&lt;br /&gt;
In situations where you are passing through the service engine the &amp;lt;tt&amp;gt;dispatcher&amp;lt;/tt&amp;gt; is obtained from the &amp;lt;tt&amp;gt;DispatchContext&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
        public static Map myNewService(DispatchContext dctx, Map context) {&lt;br /&gt;
            LocalDispatcher dispatcher = dctx.getDispatcher();&lt;br /&gt;
    &lt;br /&gt;
            try {&lt;br /&gt;
                Infrastructure infrastructure = new Infrastructure(dispatcher);&lt;br /&gt;
                Session session = infrastructure.getSession();&lt;br /&gt;
            } catch (InfrastructureException e) {&lt;br /&gt;
                // TODO Auto-generated catch block&lt;br /&gt;
                e.printStackTrace();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
In situations where you are bypassing the service engine and accessing the Java method directly the &amp;lt;tt&amp;gt;dispatcher&amp;lt;/tt&amp;gt; is obtained from &amp;lt;tt&amp;gt;HttpServletRequest&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
    public static Map myNewService(HttpServletRequest request, HttpServletResponse response) {&lt;br /&gt;
        LocalDispatcher dispatcher = (LocalDispatcher) request.getAttribute(&amp;quot;dispatcher&amp;quot;);&lt;br /&gt;
    &lt;br /&gt;
        try {&lt;br /&gt;
            Infrastructure infrastructure = new Infrastructure(dispatcher);&lt;br /&gt;
            Session session = infrastructure.getSession();&lt;br /&gt;
        } catch (InfrastructureException e) {&lt;br /&gt;
            // TODO Auto-generated catch block&lt;br /&gt;
            e.printStackTrace();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
Then, you can work with it as if it were a Hibernate &amp;lt;tt&amp;gt;Session&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
        Transaction tx = session.beginTransaction();&lt;br /&gt;
        TestEntity newTestEntity = new TestEntity();&lt;br /&gt;
        newTestEntity.setTestStringField(&amp;quot;testInsertTestEntity string field&amp;quot;);&lt;br /&gt;
        newTestEntity.setCreatedStamp(UtilDateTime.nowTimestamp());&lt;br /&gt;
        session.save(newTestEntity);&lt;br /&gt;
        tx.commit();&lt;br /&gt;
        session.flush();&lt;br /&gt;
        // ...&lt;br /&gt;
        TestEntity loadEntity = (TestEntity) session.load(TestEntity.class, newTestEntity.getTestId());&lt;br /&gt;
        // ...&lt;br /&gt;
        String hql = &amp;quot;from TestEntity eo where eo.testId='&amp;quot; + testEntityId2 + &amp;quot;'&amp;quot;;&lt;br /&gt;
        Query query = session.createQuery(hql);&lt;br /&gt;
        List&amp;lt;TestEntity&amp;gt; list = query.list()&lt;br /&gt;
 &lt;br /&gt;
You do not need to close your JDBC connection manually with the opentaps Session, however.  When you call&lt;br /&gt;
            session.close();&lt;br /&gt;
It will do it for you automatically.&lt;br /&gt;
&lt;br /&gt;
=== Traversing Related Entities ===&lt;br /&gt;
&lt;br /&gt;
opentaps will automatically create the relationship annotations, such as @OneToMany, @ManyToMany, and @Join, for your Java classes.&lt;br /&gt;
&lt;br /&gt;
To get related entities, use the hibernate query language (HQL):&lt;br /&gt;
    String hql = &amp;quot;from TestEntityItem eo where eo.testEntity.testId='&amp;quot; + testEntity.getTestId() + &amp;quot;'&amp;quot;&lt;br /&gt;
               + &amp;quot; and eo.testEntityItemSeqId in (&amp;quot; + testEntityItemSeqIds + &amp;quot;)&amp;quot;;&lt;br /&gt;
    Query query = session.createQuery(hql);&lt;br /&gt;
    List&amp;lt;TestEntityItem&amp;gt; list = query.list();&lt;br /&gt;
&lt;br /&gt;
Or use the getter methods in the base entities:&lt;br /&gt;
    List&amp;lt;TestEntityItem&amp;gt; list = testEntity.getTestEntityItems();&lt;br /&gt;
&lt;br /&gt;
Note that hibernate will automatically load related entities for you, so the getRelated  methods from Repository which were designed for the ofbiz entity engine are no longer needed when you work with hibernate.&lt;br /&gt;
&lt;br /&gt;
=== Working with View Entities ===&lt;br /&gt;
&lt;br /&gt;
Once a view entity has been defined in &amp;lt;tt&amp;gt;entitymodel.xml&amp;lt;/tt&amp;gt;, you can access it as any other Java object from hibernate, for example:&lt;br /&gt;
        Query query = session.createQuery(&amp;quot;from TestEntityAndItem eo where eo.testId='&amp;quot; &lt;br /&gt;
                    + testEntityId + &amp;quot;' order by eo.testEntityItemSeqId&amp;quot;);&lt;br /&gt;
        List&amp;lt;TestEntityAndItem&amp;gt; list = query.list();&lt;br /&gt;
        &lt;br /&gt;
The opentaps  Session, which extends the hibernate Session, will automatically create the SQL for accessing the view entity.&lt;br /&gt;
&lt;br /&gt;
=== Using Transactions ===&lt;br /&gt;
&lt;br /&gt;
You should use the transaction manager configured in the ofbiz entity engine through the &amp;lt;tt&amp;gt;[http://java.sun.com/j2ee/sdk_1.3/techdocs/api/javax/transaction/UserTransaction.html UserTransaction]&amp;lt;/tt&amp;gt;  class.  In the entity engine, the transaction manager is configured as:&lt;br /&gt;
  &amp;lt;transaction-factory class=&amp;quot;org.ofbiz.geronimo.GeronimoTransactionFactory&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is obtained from the ofbiz &amp;lt;tt&amp;gt;TransactionFactory&amp;lt;/tt&amp;gt; by our &amp;lt;tt&amp;gt;Session&amp;lt;/tt&amp;gt; and used the same way as a hibernate transaction:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     UserTransaction tx = session.beginUserTransaction();&lt;br /&gt;
     // do something useful&lt;br /&gt;
     tx.commit();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Auto Generating ID Values ===&lt;br /&gt;
&lt;br /&gt;
ofbiz keeps track of auto generated sequence IDs in an entity called &amp;lt;tt&amp;gt;SequenceValueItem&amp;lt;/tt&amp;gt;  To make sure that the auto generated sequence IDs from hibernate and the ofbiz entity engine work well together, we have created an &amp;lt;tt&amp;gt;OpentapsIdentifierGenerator&amp;lt;/tt&amp;gt; which also uses the same &amp;lt;tt&amp;gt;SequenceValueItem&amp;lt;/tt&amp;gt; to obtain the next sequential ID.  This ID generator is wired to the base entity POJO Java objects with hibernate annotations, like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 @org.hibernate.annotations.GenericGenerator(name=&amp;quot;Party_GEN&amp;quot;,  strategy=&amp;quot;org.opentaps.foundation.entity.hibernate.OpentapsIdentifierGenerator&amp;quot;)&lt;br /&gt;
 @GeneratedValue(generator=&amp;quot;Party_GEN&amp;quot;)   &lt;br /&gt;
 @Id&lt;br /&gt;
    &lt;br /&gt;
 @Column(name=&amp;quot;PARTY_ID&amp;quot;)&lt;br /&gt;
    &lt;br /&gt;
 private String partyId;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So that a &amp;lt;tt&amp;gt;partyId&amp;lt;/tt&amp;gt; field is automatically set for you.&lt;br /&gt;
&lt;br /&gt;
You can also ask the &amp;lt;tt&amp;gt;Session&amp;lt;/tt&amp;gt; to generate a particular sequence ID for you:&lt;br /&gt;
 String testEntityItemSeqId = session.getNextSeqId(&amp;quot;TestEntityItemSeqId&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
This can be helpful when you have complex keys with several fields, and you want the secondary key fields to be auto sequenced as well.&lt;br /&gt;
&lt;br /&gt;
=== Support for OFBIZ EECA's ===&lt;br /&gt;
&lt;br /&gt;
ofbiz EECA's are supported with custom event listeners which are registered with hibernate when &amp;lt;tt&amp;gt;Infrastructure.getSessionFactory(String delegatorName)&amp;lt;/tt&amp;gt; is called, usually during the initial startup.  These event listeners will run ofbiz services defined in &amp;lt;tt&amp;gt;eeca.xml&amp;lt;/tt&amp;gt;'s  when hibernate is used to update the same entities.&lt;br /&gt;
&lt;br /&gt;
=== Caching ===&lt;br /&gt;
Our caching system now support ofbiz &amp;lt;-&amp;gt; hibernate mutual cache clearing. It mean it will sync hibernate cache on you update GenericValue with ofbiz entity engine, and vice versa. The hibernate cache configuration is locate in HibernateCfg.ftl (it also in hibernate.cfg.xml) as following:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  &amp;lt;property name=&amp;quot;hibernate.search.worker.execution&amp;quot;&amp;gt;async&amp;lt;/property&amp;gt;&lt;br /&gt;
  &amp;lt;property name=&amp;quot;hibernate.cache.use_query_cache&amp;quot;&amp;gt;true&amp;lt;/property&amp;gt;&lt;br /&gt;
  &amp;lt;property name=&amp;quot;hibernate.cache.use_second_level_cache&amp;quot;&amp;gt;true&amp;lt;/property&amp;gt;&lt;br /&gt;
  &amp;lt;property name=&amp;quot;hibernate.search.worker.buffer_queue.max&amp;quot;&amp;gt;5&amp;lt;/property&amp;gt;&lt;br /&gt;
  &amp;lt;property name=&amp;quot;hibernate.search.worker.thread_pool.size&amp;quot;&amp;gt;5&amp;lt;/property&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
you can disable the caching feature by remove these lines (both HibernateCfg.ftl and hibernate.cfg.xml).&lt;br /&gt;
&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
'''Note:''' the entities of current open session will not update when it change by ofbiz entity engine, you must using open a new session to get fresh object. and the best practise is also close your session when it finish the job.&lt;br /&gt;
&lt;br /&gt;
=== Using Hibernate without the OFBIZ Entity Engine ===&lt;br /&gt;
&lt;br /&gt;
You can also use hibernate without the ofbiz entity engine by adding your Java objects to the template opentaps uses to generate the hibernate configuration files, &amp;lt;tt&amp;gt;hot-deploy/opentaps-common/templates/HibernateCfg.ftl&amp;lt;/tt&amp;gt;.  Simply put your Java objects after the &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  &amp;lt;#list&amp;gt;&lt;br /&gt;
    ...&lt;br /&gt;
  &amp;lt;/#list&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
directives in the file, like in the following example:    &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;!DOCTYPE hibernate-configuration PUBLIC &amp;quot;-//Hibernate/Hibernate Configuration DTD 3.0//EN&amp;quot; &amp;quot;http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;hibernate-configuration&amp;gt;&lt;br /&gt;
  &amp;lt;session-factory&amp;gt;&lt;br /&gt;
  &amp;lt;property name=&amp;quot;hibernate.connection.provider_class&amp;quot;&amp;gt;org.opentaps.foundation.entity.hibernate.OpentapsConnectionProvider&amp;lt;/property&amp;gt;  &lt;br /&gt;
  &amp;lt;property name=&amp;quot;hibernate.transaction.factory_class&amp;quot;&amp;gt;org.opentaps.foundation.entity.hibernate.OpentapsTransactionFactory&amp;lt;/property&amp;gt;&lt;br /&gt;
  &amp;lt;property name=&amp;quot;hibernate.transaction.manager_lookup_class&amp;quot;&amp;gt;org.opentaps.foundation.entity.hibernate.OpentapsTransactionManagerLookup&amp;lt;/property&amp;gt;  &lt;br /&gt;
  &amp;lt;property name=&amp;quot;hibernate.search.default.directory_provider&amp;quot;&amp;gt;org.hibernate.search.store.FSDirectoryProvider&amp;lt;/property&amp;gt;&lt;br /&gt;
&amp;lt;#list entities as entity&amp;gt;&lt;br /&gt;
  &amp;lt;mapping class=&amp;quot;org.opentaps.domain.base.entities.${entity}&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/#list&amp;gt;&lt;br /&gt;
  &amp;lt;mapping class=&amp;quot;org.opentaps.domain.base.entities.MyPojo1&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;mapping class=&amp;quot;org.opentaps.domain.base.entities.MyPojo2&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;/session-factory&amp;gt;&lt;br /&gt;
&amp;lt;/hibernate-configuration&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
opentaps will then create the hibernate configuration file for each database and include your Java objects in it.  However, you would not be able to access these Java objects as generic values from the ofbiz entity engine.&lt;br /&gt;
&lt;br /&gt;
== Under the Hood: How It Works ==&lt;br /&gt;
&lt;br /&gt;
=== Base Class Annotations ===&lt;br /&gt;
&lt;br /&gt;
In opentaps version 1.4, the entity model XML from the ofbiz entity engine is still used as the base definition for all entities.  The opentaps POJO generator is used to create [[Base Entity Classes|base Java objects]] automatically from these entity definitions.  This POJO generator will also create the annotations which hibernate can then use to map those base objects to the database persistence layer.  The definitions of the annotations can be found in &amp;lt;tt&amp;gt;BaseEntity.ftl&amp;lt;/tt&amp;gt; file used by the POJO generator.&lt;br /&gt;
&lt;br /&gt;
=== How Hibernate Configuration Files are Generated ===&lt;br /&gt;
&lt;br /&gt;
The POJO Generator will use &amp;lt;tt&amp;gt;hot-deploy/opentaps-common/templates/HibernateCfg.ftl&amp;lt;/tt&amp;gt; to generate a base hibernate configuration file in &amp;lt;tt&amp;gt;hot-deploy/opentaps-common/config/hibernate.cfg.xml&amp;lt;/tt&amp;gt;  When opentaps is started, the following new container in &amp;lt;tt&amp;gt;framework/base/config/ofbiz-containers.xml&amp;lt;/tt&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    &amp;lt;container name=&amp;quot;hibernate-container&amp;quot; class=&amp;quot;org.opentaps.common.container.HibernateContainer&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;property name=&amp;quot;delegator-name&amp;quot; value=&amp;quot;default&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;/container&amp;gt;    &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will generate all the hibernate configuration XML files in the &amp;lt;tt&amp;gt;hot-deploy/opentaps/config/&amp;lt;/tt&amp;gt; directory for each data source in your entity engine XML file.  For example, it will generate a &amp;lt;tt&amp;gt;localmysql.cfg.xml&amp;lt;/tt&amp;gt;, a &amp;lt;tt&amp;gt;localpostgres.cfg.xml&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How We Get the Hibernate Session ===&lt;br /&gt;
&lt;br /&gt;
The opentaps &amp;lt;tt&amp;gt;Infrastructure&amp;lt;/tt&amp;gt; Class maintains a Map of delegatorName and hibernate SessionFactory objects.  Each SessionFactory is created for its corresponding delegatorName the first time it is requested from the &amp;lt;tt&amp;gt;Infrastructure.getSessionFactory(delegatorName)&amp;lt;/tt&amp;gt; method.  This SessionFactory is created from ofbiz entity engine configurations:&lt;br /&gt;
* The &amp;lt;tt&amp;gt;HibernateContainer&amp;lt;/tt&amp;gt; in &amp;lt;tt&amp;gt;ofbiz-containers.xml&amp;lt;/tt&amp;gt; has a property called &amp;lt;tt&amp;gt;delegator-name&amp;lt;/tt&amp;gt;&lt;br /&gt;
* From this delegator, we get the data source defined in &amp;lt;tt&amp;gt;entityengine.xml&amp;lt;/tt&amp;gt; for the default group helper name.  This is set to &amp;lt;tt&amp;gt;org.ofbiz&amp;lt;/tt&amp;gt; by default in the &amp;lt;tt&amp;gt;Infrastructure&amp;lt;/tt&amp;gt; class and is the &amp;lt;tt&amp;gt;group&amp;lt;/tt&amp;gt; attribute of the &amp;lt;tt&amp;gt;entitygroup.xml&amp;lt;/tt&amp;gt; definitions in ofbiz:&lt;br /&gt;
  &amp;lt;entity-group group=&amp;quot;org.ofbiz&amp;quot; entity=&amp;quot;AcctgTagEnumType&amp;quot;/&amp;gt;&lt;br /&gt;
In &amp;lt;tt&amp;gt;entityengine.xml&amp;lt;/tt&amp;gt;, you map a data source to each group:&lt;br /&gt;
    &amp;lt;delegator name=&amp;quot;default&amp;quot; entity-model-reader=&amp;quot;main&amp;quot; entity-group-reader=&amp;quot;main&amp;quot; entity-eca-reader=&amp;quot;main&amp;quot; distributed-cache-clear-enabled=&amp;quot;false&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;group-map group-name=&amp;quot;org.ofbiz&amp;quot; datasource-name=&amp;quot;localmysql&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;/delegator&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So, we are basically following the entity engine from the delegator to the data source via the group.&lt;br /&gt;
* Once we have the data source, we can create the SessionFactory from the hibernate.cfg.xml for that data source.  For example, if your data source is &amp;quot;localmysql&amp;quot;, we will create the SessionFactory from the &amp;lt;tt&amp;gt;localmysql.cfg.xml&amp;lt;/tt&amp;gt;   created by the &amp;lt;tt&amp;gt;HibernateContainer&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;HibernateContainer&amp;lt;/tt&amp;gt;, which loads on startup, will cause a SessionFactory to be loaded for the delegator in the &amp;lt;tt&amp;gt;delegator-name&amp;lt;/tt&amp;gt; attribute.  Once this SessionFactory is loaded, it will be available for future use.  Additional session factories can be obtained later by calling the &amp;lt;tt&amp;gt;getSessionFactory&amp;lt;/tt&amp;gt; directly.&lt;br /&gt;
&lt;br /&gt;
When the &amp;lt;tt&amp;gt;Infrastructure.getSession()&amp;lt;/tt&amp;gt; method is called,  it will use the delegator already in the Infrastructure object to open a JDBC connection first, and then use that JDBC connection and the SessionFactory for the delegator to return a Session.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;Infrastructure.getSession()&amp;lt;/tt&amp;gt; will return an &amp;lt;tt&amp;gt;org.opentaps.foundation.entity.hibernate.Session&amp;lt;/tt&amp;gt;, which extends the hibernate Session with the following differences:&lt;br /&gt;
* when the session is closed, the JDBC connection is also automatically closed&lt;br /&gt;
* when a Query is created, this Session will check if the query is on an entity engine view entity and construct the Query from native SQL first&lt;br /&gt;
&lt;br /&gt;
=== View Entities ===&lt;br /&gt;
&lt;br /&gt;
View entities are supported with @NamedNativeQuery annotations in the base entity Java classes, which are automatically generated by the opentaps POJO Generator.&lt;br /&gt;
&lt;br /&gt;
=== Encryption ===&lt;br /&gt;
&lt;br /&gt;
The ofbiz delegator allows you to set a field to be encrypted in the database with the &amp;lt;tt&amp;gt;encrypt=&amp;quot;true&amp;quot;&amp;lt;/tt&amp;gt; attribute in the &amp;lt;tt&amp;gt;field&amp;lt;/tt&amp;gt; tag of an entity definition.  The opentaps hibernate will support the same encryption/decryption algorithm, so that encrypted values can be stored with the delegator and decrypted when it's retrieved with hibernate or vice versa.  This is done by:&lt;br /&gt;
# When an object is being stored, the &amp;lt;tt&amp;gt;EcaCommEvent.beforeSave&amp;lt;/tt&amp;gt; Method will come for the object to an ofbiz GenericValue and then use the ofbiz delegator to encrypt it.&lt;br /&gt;
# When an object is retrieved from the database, the &amp;lt;tt&amp;gt;Session.load&amp;lt;/tt&amp;gt; will call the &amp;lt;tt&amp;gt;HibernateUtil.decryptField&amp;lt;/tt&amp;gt; to decrypt it.&lt;br /&gt;
&lt;br /&gt;
=== Transaction Management ===&lt;br /&gt;
&lt;br /&gt;
To maintain compatibility with the ofbiz entity engine's transaction manager and connection pool providers, we have defined transaction manager look up, transaction factory, and connection provider classes which use the ofbiz transaction manager and transaction factory to begin transactions.  These are defined in the &amp;lt;tt&amp;gt;hibernate.cfg.xml&amp;lt;/tt&amp;gt; configuration file.  They allow you to mix delegator and hibernate transaction codes as in this following example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        UserTransaction tx = session.beginUserTransaction();&lt;br /&gt;
        TestEntity useIdentifierTestEntity = new TestEntity();&lt;br /&gt;
        useIdentifierTestEntity.setTestStringField(&amp;quot;Use IdentifierGenerator string field&amp;quot;);&lt;br /&gt;
        session.save(useIdentifierTestEntity);&lt;br /&gt;
        String getNextSeqIdTestEntityId = delegator.getNextSeqId(&amp;quot;TestEntity&amp;quot;);&lt;br /&gt;
        GenericValue useGetNextSeqIdTestEntity = delegator.create(&amp;quot;TestEntity&amp;quot;,&lt;br /&gt;
                UtilMisc.toMap(&amp;quot;testId&amp;quot;, getNextSeqIdTestEntityId,  &amp;quot;testStringField&amp;quot;, &amp;quot;Use getNextSeqId string field&amp;quot;));&lt;br /&gt;
        session.flush();&lt;br /&gt;
        tx.commit();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Support for BLOBs ===&lt;br /&gt;
&lt;br /&gt;
To make the &amp;quot;BLOB&amp;quot; type work with postgresql, we made the following changes:&lt;br /&gt;
# change blob field mapping to Java byte[] &lt;br /&gt;
# avoid using the &amp;lt;tt&amp;gt;@Lob&amp;lt;/tt&amp;gt; annotation&lt;br /&gt;
# add this element in hibernate.cfg.xml&lt;br /&gt;
 &amp;lt;property name=&amp;quot;hibernate.jdbc.use_streams_for_binary&amp;quot;&amp;gt;true&amp;lt;/property&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Unit Tests ===&lt;br /&gt;
&lt;br /&gt;
Unit tests for hibernate are found in &amp;lt;tt&amp;gt;org.opentaps.tests.entity.HibernateTests&amp;lt;/tt&amp;gt; in the opentaps-tests component.&lt;br /&gt;
&lt;br /&gt;
== Learning More ==&lt;br /&gt;
&lt;br /&gt;
The best way to learn more about how to use hibernate with opentaps is to look through the unit tests in &amp;lt;tt&amp;gt;org.opentaps.tests.entity.HibernateTests&amp;lt;/tt&amp;gt; as an example.&lt;/div&gt;</summary>
		<author><name>Spark</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=Opentaps_Hibernate_Integration&amp;diff=5038</id>
		<title>Opentaps Hibernate Integration</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=Opentaps_Hibernate_Integration&amp;diff=5038"/>
		<updated>2009-11-21T03:58:03Z</updated>

		<summary type="html">&lt;p&gt;Spark: /* Caching */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Beginning with opentaps version 1.4, [http://www.hibernate.org Hibernate] will be available as a persistence tool alongside with the original ofbiz entity engine.  Hibernate is a more object oriented persistence framework and better suited for the new [[Domain Driven Architecture]], while the ofbiz entity engine will continue to be supported for legacy features from both ofbiz and opentaps.  In this document, we will review how the hibernate integration in opentaps works.&lt;br /&gt;
&lt;br /&gt;
== Working with Hibernate in opentaps ==&lt;br /&gt;
&lt;br /&gt;
=== Generating Hibernate Configuration Files ===&lt;br /&gt;
&lt;br /&gt;
After changing or defining new entities in your &amp;lt;tt&amp;gt;entitymodel.xml&amp;lt;/tt&amp;gt; files, you need to generate new Java classes for your entities with&lt;br /&gt;
 $ ant make-base-entities&lt;br /&gt;
&lt;br /&gt;
This command updates the Java classes defined in &amp;lt;tt&amp;gt;org.opentaps.domain.base.entities&amp;lt;/tt&amp;gt;, including their hibernate annotations, and the &amp;lt;tt&amp;gt;hibernate.cfg.xml&amp;lt;/tt&amp;gt; for integrating with hibernate.  (If you use a repository management system, you must commit both and you Java classes and the updated &amp;lt;tt&amp;gt;hibernate.cfg.xml&amp;lt;/tt&amp;gt; files.)&lt;br /&gt;
&lt;br /&gt;
{{note|Important|Be sure to reference the JARs from &amp;lt;tt&amp;gt;/hot-deploy/opentaps-common/lib/hibernate&amp;lt;/tt&amp;gt; in your Ant build file, or else during build it will not be able to locate the appropriate Hibernate files.}}&lt;br /&gt;
&lt;br /&gt;
=== Accessing Entities with Hibernate ===&lt;br /&gt;
&lt;br /&gt;
{{tip|Tip|If you are developing in Eclipse, when using Hibernate make sure to run the ant task &amp;lt;tt&amp;gt;make-base-entities&amp;lt;/tt&amp;gt; immediately after you are done defining new entities. Also make sure you refresh the Eclipse project so that it picks up the new Hibernate POJOs for code-assist.}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To use hibernate to access your entities, you will need an &amp;lt;tt&amp;gt;org.opentaps.foundation.entity.hibernate.Session&amp;lt;/tt&amp;gt;, which is an extension of the &amp;lt;tt&amp;gt;org.hibernate.Session&amp;lt;/tt&amp;gt; class.  You can obtain it from the Infrastructure class like this:&lt;br /&gt;
        session = infrastructure.getSession();&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;Infrastructure&amp;lt;/tt&amp;gt; must be created from &amp;lt;tt&amp;gt;dispatcher&amp;lt;/tt&amp;gt; in order to obtain the hibernate session.&lt;br /&gt;
&lt;br /&gt;
In situations where you are passing through the service engine the &amp;lt;tt&amp;gt;dispatcher&amp;lt;/tt&amp;gt; is obtained from the &amp;lt;tt&amp;gt;DispatchContext&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
        public static Map myNewService(DispatchContext dctx, Map context) {&lt;br /&gt;
            LocalDispatcher dispatcher = dctx.getDispatcher();&lt;br /&gt;
    &lt;br /&gt;
            try {&lt;br /&gt;
                Infrastructure infrastructure = new Infrastructure(dispatcher);&lt;br /&gt;
                Session session = infrastructure.getSession();&lt;br /&gt;
            } catch (InfrastructureException e) {&lt;br /&gt;
                // TODO Auto-generated catch block&lt;br /&gt;
                e.printStackTrace();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
In situations where you are bypassing the service engine and accessing the Java method directly the &amp;lt;tt&amp;gt;dispatcher&amp;lt;/tt&amp;gt; is obtained from &amp;lt;tt&amp;gt;HttpServletRequest&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
    public static Map myNewService(HttpServletRequest request, HttpServletResponse response) {&lt;br /&gt;
        LocalDispatcher dispatcher = (LocalDispatcher) request.getAttribute(&amp;quot;dispatcher&amp;quot;);&lt;br /&gt;
    &lt;br /&gt;
        try {&lt;br /&gt;
            Infrastructure infrastructure = new Infrastructure(dispatcher);&lt;br /&gt;
            Session session = infrastructure.getSession();&lt;br /&gt;
        } catch (InfrastructureException e) {&lt;br /&gt;
            // TODO Auto-generated catch block&lt;br /&gt;
            e.printStackTrace();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
Then, you can work with it as if it were a Hibernate &amp;lt;tt&amp;gt;Session&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
        Transaction tx = session.beginTransaction();&lt;br /&gt;
        TestEntity newTestEntity = new TestEntity();&lt;br /&gt;
        newTestEntity.setTestStringField(&amp;quot;testInsertTestEntity string field&amp;quot;);&lt;br /&gt;
        newTestEntity.setCreatedStamp(UtilDateTime.nowTimestamp());&lt;br /&gt;
        session.save(newTestEntity);&lt;br /&gt;
        tx.commit();&lt;br /&gt;
        session.flush();&lt;br /&gt;
        // ...&lt;br /&gt;
        TestEntity loadEntity = (TestEntity) session.load(TestEntity.class, newTestEntity.getTestId());&lt;br /&gt;
        // ...&lt;br /&gt;
        String hql = &amp;quot;from TestEntity eo where eo.testId='&amp;quot; + testEntityId2 + &amp;quot;'&amp;quot;;&lt;br /&gt;
        Query query = session.createQuery(hql);&lt;br /&gt;
        List&amp;lt;TestEntity&amp;gt; list = query.list()&lt;br /&gt;
 &lt;br /&gt;
You do not need to close your JDBC connection manually with the opentaps Session, however.  When you call&lt;br /&gt;
            session.close();&lt;br /&gt;
It will do it for you automatically.&lt;br /&gt;
&lt;br /&gt;
=== Traversing Related Entities ===&lt;br /&gt;
&lt;br /&gt;
opentaps will automatically create the relationship annotations, such as @OneToMany, @ManyToMany, and @Join, for your Java classes.&lt;br /&gt;
&lt;br /&gt;
To get related entities, use the hibernate query language (HQL):&lt;br /&gt;
    String hql = &amp;quot;from TestEntityItem eo where eo.testEntity.testId='&amp;quot; + testEntity.getTestId() + &amp;quot;'&amp;quot;&lt;br /&gt;
               + &amp;quot; and eo.testEntityItemSeqId in (&amp;quot; + testEntityItemSeqIds + &amp;quot;)&amp;quot;;&lt;br /&gt;
    Query query = session.createQuery(hql);&lt;br /&gt;
    List&amp;lt;TestEntityItem&amp;gt; list = query.list();&lt;br /&gt;
&lt;br /&gt;
Or use the getter methods in the base entities:&lt;br /&gt;
    List&amp;lt;TestEntityItem&amp;gt; list = testEntity.getTestEntityItems();&lt;br /&gt;
&lt;br /&gt;
Note that hibernate will automatically load related entities for you, so the getRelated  methods from Repository which were designed for the ofbiz entity engine are no longer needed when you work with hibernate.&lt;br /&gt;
&lt;br /&gt;
=== Working with View Entities ===&lt;br /&gt;
&lt;br /&gt;
Once a view entity has been defined in &amp;lt;tt&amp;gt;entitymodel.xml&amp;lt;/tt&amp;gt;, you can access it as any other Java object from hibernate, for example:&lt;br /&gt;
        Query query = session.createQuery(&amp;quot;from TestEntityAndItem eo where eo.testId='&amp;quot; &lt;br /&gt;
                    + testEntityId + &amp;quot;' order by eo.testEntityItemSeqId&amp;quot;);&lt;br /&gt;
        List&amp;lt;TestEntityAndItem&amp;gt; list = query.list();&lt;br /&gt;
        &lt;br /&gt;
The opentaps  Session, which extends the hibernate Session, will automatically create the SQL for accessing the view entity.&lt;br /&gt;
&lt;br /&gt;
=== Using Transactions ===&lt;br /&gt;
&lt;br /&gt;
You should use the transaction manager configured in the ofbiz entity engine through the &amp;lt;tt&amp;gt;[http://java.sun.com/j2ee/sdk_1.3/techdocs/api/javax/transaction/UserTransaction.html UserTransaction]&amp;lt;/tt&amp;gt;  class.  In the entity engine, the transaction manager is configured as:&lt;br /&gt;
  &amp;lt;transaction-factory class=&amp;quot;org.ofbiz.geronimo.GeronimoTransactionFactory&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is obtained from the ofbiz &amp;lt;tt&amp;gt;TransactionFactory&amp;lt;/tt&amp;gt; by our &amp;lt;tt&amp;gt;Session&amp;lt;/tt&amp;gt; and used the same way as a hibernate transaction:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     UserTransaction tx = session.beginUserTransaction();&lt;br /&gt;
     // do something useful&lt;br /&gt;
     tx.commit();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Auto Generating ID Values ===&lt;br /&gt;
&lt;br /&gt;
ofbiz keeps track of auto generated sequence IDs in an entity called &amp;lt;tt&amp;gt;SequenceValueItem&amp;lt;/tt&amp;gt;  To make sure that the auto generated sequence IDs from hibernate and the ofbiz entity engine work well together, we have created an &amp;lt;tt&amp;gt;OpentapsIdentifierGenerator&amp;lt;/tt&amp;gt; which also uses the same &amp;lt;tt&amp;gt;SequenceValueItem&amp;lt;/tt&amp;gt; to obtain the next sequential ID.  This ID generator is wired to the base entity POJO Java objects with hibernate annotations, like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 @org.hibernate.annotations.GenericGenerator(name=&amp;quot;Party_GEN&amp;quot;,  strategy=&amp;quot;org.opentaps.foundation.entity.hibernate.OpentapsIdentifierGenerator&amp;quot;)&lt;br /&gt;
 @GeneratedValue(generator=&amp;quot;Party_GEN&amp;quot;)   &lt;br /&gt;
 @Id&lt;br /&gt;
    &lt;br /&gt;
 @Column(name=&amp;quot;PARTY_ID&amp;quot;)&lt;br /&gt;
    &lt;br /&gt;
 private String partyId;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So that a &amp;lt;tt&amp;gt;partyId&amp;lt;/tt&amp;gt; field is automatically set for you.&lt;br /&gt;
&lt;br /&gt;
You can also ask the &amp;lt;tt&amp;gt;Session&amp;lt;/tt&amp;gt; to generate a particular sequence ID for you:&lt;br /&gt;
 String testEntityItemSeqId = session.getNextSeqId(&amp;quot;TestEntityItemSeqId&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
This can be helpful when you have complex keys with several fields, and you want the secondary key fields to be auto sequenced as well.&lt;br /&gt;
&lt;br /&gt;
=== Support for OFBIZ EECA's ===&lt;br /&gt;
&lt;br /&gt;
ofbiz EECA's are supported with custom event listeners which are registered with hibernate when &amp;lt;tt&amp;gt;Infrastructure.getSessionFactory(String delegatorName)&amp;lt;/tt&amp;gt; is called, usually during the initial startup.  These event listeners will run ofbiz services defined in &amp;lt;tt&amp;gt;eeca.xml&amp;lt;/tt&amp;gt;'s  when hibernate is used to update the same entities.&lt;br /&gt;
&lt;br /&gt;
=== Caching ===&lt;br /&gt;
Our caching system now support ofbiz &amp;lt;-&amp;gt; hibernate mutual cache clearing. It mean it will sync hibernate cache on you update GenericValue with ofbiz entity engine, and vice versa. The hibernate cache configuration is locate in HibernateCfg.ftl (it also in hibernate.cfg.xml) as following:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  &amp;lt;property name=&amp;quot;hibernate.search.worker.execution&amp;quot;&amp;gt;async&amp;lt;/property&amp;gt;&lt;br /&gt;
  &amp;lt;property name=&amp;quot;hibernate.cache.use_query_cache&amp;quot;&amp;gt;true&amp;lt;/property&amp;gt;&lt;br /&gt;
  &amp;lt;property name=&amp;quot;hibernate.cache.use_second_level_cache&amp;quot;&amp;gt;true&amp;lt;/property&amp;gt;&lt;br /&gt;
  &amp;lt;property name=&amp;quot;hibernate.search.worker.buffer_queue.max&amp;quot;&amp;gt;5&amp;lt;/property&amp;gt;&lt;br /&gt;
  &amp;lt;property name=&amp;quot;hibernate.search.worker.thread_pool.size&amp;quot;&amp;gt;5&amp;lt;/property&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
you can disable the caching feature by remove these lines (both HibernateCfg.ftl and hibernate.cfg.xml).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Note: the entities of current open session will not update when it change by ofbiz entity engine, you must using open a new session to get fresh object. and the best practise is also close your session when it finish the job.&lt;br /&gt;
&lt;br /&gt;
=== Using Hibernate without the OFBIZ Entity Engine ===&lt;br /&gt;
&lt;br /&gt;
You can also use hibernate without the ofbiz entity engine by adding your Java objects to the template opentaps uses to generate the hibernate configuration files, &amp;lt;tt&amp;gt;hot-deploy/opentaps-common/templates/HibernateCfg.ftl&amp;lt;/tt&amp;gt;.  Simply put your Java objects after the &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  &amp;lt;#list&amp;gt;&lt;br /&gt;
    ...&lt;br /&gt;
  &amp;lt;/#list&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
directives in the file, like in the following example:    &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;!DOCTYPE hibernate-configuration PUBLIC &amp;quot;-//Hibernate/Hibernate Configuration DTD 3.0//EN&amp;quot; &amp;quot;http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;hibernate-configuration&amp;gt;&lt;br /&gt;
  &amp;lt;session-factory&amp;gt;&lt;br /&gt;
  &amp;lt;property name=&amp;quot;hibernate.connection.provider_class&amp;quot;&amp;gt;org.opentaps.foundation.entity.hibernate.OpentapsConnectionProvider&amp;lt;/property&amp;gt;  &lt;br /&gt;
  &amp;lt;property name=&amp;quot;hibernate.transaction.factory_class&amp;quot;&amp;gt;org.opentaps.foundation.entity.hibernate.OpentapsTransactionFactory&amp;lt;/property&amp;gt;&lt;br /&gt;
  &amp;lt;property name=&amp;quot;hibernate.transaction.manager_lookup_class&amp;quot;&amp;gt;org.opentaps.foundation.entity.hibernate.OpentapsTransactionManagerLookup&amp;lt;/property&amp;gt;  &lt;br /&gt;
  &amp;lt;property name=&amp;quot;hibernate.search.default.directory_provider&amp;quot;&amp;gt;org.hibernate.search.store.FSDirectoryProvider&amp;lt;/property&amp;gt;&lt;br /&gt;
&amp;lt;#list entities as entity&amp;gt;&lt;br /&gt;
  &amp;lt;mapping class=&amp;quot;org.opentaps.domain.base.entities.${entity}&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/#list&amp;gt;&lt;br /&gt;
  &amp;lt;mapping class=&amp;quot;org.opentaps.domain.base.entities.MyPojo1&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;mapping class=&amp;quot;org.opentaps.domain.base.entities.MyPojo2&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;/session-factory&amp;gt;&lt;br /&gt;
&amp;lt;/hibernate-configuration&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
opentaps will then create the hibernate configuration file for each database and include your Java objects in it.  However, you would not be able to access these Java objects as generic values from the ofbiz entity engine.&lt;br /&gt;
&lt;br /&gt;
== Under the Hood: How It Works ==&lt;br /&gt;
&lt;br /&gt;
=== Base Class Annotations ===&lt;br /&gt;
&lt;br /&gt;
In opentaps version 1.4, the entity model XML from the ofbiz entity engine is still used as the base definition for all entities.  The opentaps POJO generator is used to create [[Base Entity Classes|base Java objects]] automatically from these entity definitions.  This POJO generator will also create the annotations which hibernate can then use to map those base objects to the database persistence layer.  The definitions of the annotations can be found in &amp;lt;tt&amp;gt;BaseEntity.ftl&amp;lt;/tt&amp;gt; file used by the POJO generator.&lt;br /&gt;
&lt;br /&gt;
=== How Hibernate Configuration Files are Generated ===&lt;br /&gt;
&lt;br /&gt;
The POJO Generator will use &amp;lt;tt&amp;gt;hot-deploy/opentaps-common/templates/HibernateCfg.ftl&amp;lt;/tt&amp;gt; to generate a base hibernate configuration file in &amp;lt;tt&amp;gt;hot-deploy/opentaps-common/config/hibernate.cfg.xml&amp;lt;/tt&amp;gt;  When opentaps is started, the following new container in &amp;lt;tt&amp;gt;framework/base/config/ofbiz-containers.xml&amp;lt;/tt&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    &amp;lt;container name=&amp;quot;hibernate-container&amp;quot; class=&amp;quot;org.opentaps.common.container.HibernateContainer&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;property name=&amp;quot;delegator-name&amp;quot; value=&amp;quot;default&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;/container&amp;gt;    &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will generate all the hibernate configuration XML files in the &amp;lt;tt&amp;gt;hot-deploy/opentaps/config/&amp;lt;/tt&amp;gt; directory for each data source in your entity engine XML file.  For example, it will generate a &amp;lt;tt&amp;gt;localmysql.cfg.xml&amp;lt;/tt&amp;gt;, a &amp;lt;tt&amp;gt;localpostgres.cfg.xml&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How We Get the Hibernate Session ===&lt;br /&gt;
&lt;br /&gt;
The opentaps &amp;lt;tt&amp;gt;Infrastructure&amp;lt;/tt&amp;gt; Class maintains a Map of delegatorName and hibernate SessionFactory objects.  Each SessionFactory is created for its corresponding delegatorName the first time it is requested from the &amp;lt;tt&amp;gt;Infrastructure.getSessionFactory(delegatorName)&amp;lt;/tt&amp;gt; method.  This SessionFactory is created from ofbiz entity engine configurations:&lt;br /&gt;
* The &amp;lt;tt&amp;gt;HibernateContainer&amp;lt;/tt&amp;gt; in &amp;lt;tt&amp;gt;ofbiz-containers.xml&amp;lt;/tt&amp;gt; has a property called &amp;lt;tt&amp;gt;delegator-name&amp;lt;/tt&amp;gt;&lt;br /&gt;
* From this delegator, we get the data source defined in &amp;lt;tt&amp;gt;entityengine.xml&amp;lt;/tt&amp;gt; for the default group helper name.  This is set to &amp;lt;tt&amp;gt;org.ofbiz&amp;lt;/tt&amp;gt; by default in the &amp;lt;tt&amp;gt;Infrastructure&amp;lt;/tt&amp;gt; class and is the &amp;lt;tt&amp;gt;group&amp;lt;/tt&amp;gt; attribute of the &amp;lt;tt&amp;gt;entitygroup.xml&amp;lt;/tt&amp;gt; definitions in ofbiz:&lt;br /&gt;
  &amp;lt;entity-group group=&amp;quot;org.ofbiz&amp;quot; entity=&amp;quot;AcctgTagEnumType&amp;quot;/&amp;gt;&lt;br /&gt;
In &amp;lt;tt&amp;gt;entityengine.xml&amp;lt;/tt&amp;gt;, you map a data source to each group:&lt;br /&gt;
    &amp;lt;delegator name=&amp;quot;default&amp;quot; entity-model-reader=&amp;quot;main&amp;quot; entity-group-reader=&amp;quot;main&amp;quot; entity-eca-reader=&amp;quot;main&amp;quot; distributed-cache-clear-enabled=&amp;quot;false&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;group-map group-name=&amp;quot;org.ofbiz&amp;quot; datasource-name=&amp;quot;localmysql&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;/delegator&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So, we are basically following the entity engine from the delegator to the data source via the group.&lt;br /&gt;
* Once we have the data source, we can create the SessionFactory from the hibernate.cfg.xml for that data source.  For example, if your data source is &amp;quot;localmysql&amp;quot;, we will create the SessionFactory from the &amp;lt;tt&amp;gt;localmysql.cfg.xml&amp;lt;/tt&amp;gt;   created by the &amp;lt;tt&amp;gt;HibernateContainer&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;HibernateContainer&amp;lt;/tt&amp;gt;, which loads on startup, will cause a SessionFactory to be loaded for the delegator in the &amp;lt;tt&amp;gt;delegator-name&amp;lt;/tt&amp;gt; attribute.  Once this SessionFactory is loaded, it will be available for future use.  Additional session factories can be obtained later by calling the &amp;lt;tt&amp;gt;getSessionFactory&amp;lt;/tt&amp;gt; directly.&lt;br /&gt;
&lt;br /&gt;
When the &amp;lt;tt&amp;gt;Infrastructure.getSession()&amp;lt;/tt&amp;gt; method is called,  it will use the delegator already in the Infrastructure object to open a JDBC connection first, and then use that JDBC connection and the SessionFactory for the delegator to return a Session.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;Infrastructure.getSession()&amp;lt;/tt&amp;gt; will return an &amp;lt;tt&amp;gt;org.opentaps.foundation.entity.hibernate.Session&amp;lt;/tt&amp;gt;, which extends the hibernate Session with the following differences:&lt;br /&gt;
* when the session is closed, the JDBC connection is also automatically closed&lt;br /&gt;
* when a Query is created, this Session will check if the query is on an entity engine view entity and construct the Query from native SQL first&lt;br /&gt;
&lt;br /&gt;
=== View Entities ===&lt;br /&gt;
&lt;br /&gt;
View entities are supported with @NamedNativeQuery annotations in the base entity Java classes, which are automatically generated by the opentaps POJO Generator.&lt;br /&gt;
&lt;br /&gt;
=== Encryption ===&lt;br /&gt;
&lt;br /&gt;
The ofbiz delegator allows you to set a field to be encrypted in the database with the &amp;lt;tt&amp;gt;encrypt=&amp;quot;true&amp;quot;&amp;lt;/tt&amp;gt; attribute in the &amp;lt;tt&amp;gt;field&amp;lt;/tt&amp;gt; tag of an entity definition.  The opentaps hibernate will support the same encryption/decryption algorithm, so that encrypted values can be stored with the delegator and decrypted when it's retrieved with hibernate or vice versa.  This is done by:&lt;br /&gt;
# When an object is being stored, the &amp;lt;tt&amp;gt;EcaCommEvent.beforeSave&amp;lt;/tt&amp;gt; Method will come for the object to an ofbiz GenericValue and then use the ofbiz delegator to encrypt it.&lt;br /&gt;
# When an object is retrieved from the database, the &amp;lt;tt&amp;gt;Session.load&amp;lt;/tt&amp;gt; will call the &amp;lt;tt&amp;gt;HibernateUtil.decryptField&amp;lt;/tt&amp;gt; to decrypt it.&lt;br /&gt;
&lt;br /&gt;
=== Transaction Management ===&lt;br /&gt;
&lt;br /&gt;
To maintain compatibility with the ofbiz entity engine's transaction manager and connection pool providers, we have defined transaction manager look up, transaction factory, and connection provider classes which use the ofbiz transaction manager and transaction factory to begin transactions.  These are defined in the &amp;lt;tt&amp;gt;hibernate.cfg.xml&amp;lt;/tt&amp;gt; configuration file.  They allow you to mix delegator and hibernate transaction codes as in this following example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        UserTransaction tx = session.beginUserTransaction();&lt;br /&gt;
        TestEntity useIdentifierTestEntity = new TestEntity();&lt;br /&gt;
        useIdentifierTestEntity.setTestStringField(&amp;quot;Use IdentifierGenerator string field&amp;quot;);&lt;br /&gt;
        session.save(useIdentifierTestEntity);&lt;br /&gt;
        String getNextSeqIdTestEntityId = delegator.getNextSeqId(&amp;quot;TestEntity&amp;quot;);&lt;br /&gt;
        GenericValue useGetNextSeqIdTestEntity = delegator.create(&amp;quot;TestEntity&amp;quot;,&lt;br /&gt;
                UtilMisc.toMap(&amp;quot;testId&amp;quot;, getNextSeqIdTestEntityId,  &amp;quot;testStringField&amp;quot;, &amp;quot;Use getNextSeqId string field&amp;quot;));&lt;br /&gt;
        session.flush();&lt;br /&gt;
        tx.commit();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Support for BLOBs ===&lt;br /&gt;
&lt;br /&gt;
To make the &amp;quot;BLOB&amp;quot; type work with postgresql, we made the following changes:&lt;br /&gt;
# change blob field mapping to Java byte[] &lt;br /&gt;
# avoid using the &amp;lt;tt&amp;gt;@Lob&amp;lt;/tt&amp;gt; annotation&lt;br /&gt;
# add this element in hibernate.cfg.xml&lt;br /&gt;
 &amp;lt;property name=&amp;quot;hibernate.jdbc.use_streams_for_binary&amp;quot;&amp;gt;true&amp;lt;/property&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Unit Tests ===&lt;br /&gt;
&lt;br /&gt;
Unit tests for hibernate are found in &amp;lt;tt&amp;gt;org.opentaps.tests.entity.HibernateTests&amp;lt;/tt&amp;gt; in the opentaps-tests component.&lt;br /&gt;
&lt;br /&gt;
== Learning More ==&lt;br /&gt;
&lt;br /&gt;
The best way to learn more about how to use hibernate with opentaps is to look through the unit tests in &amp;lt;tt&amp;gt;org.opentaps.tests.entity.HibernateTests&amp;lt;/tt&amp;gt; as an example.&lt;/div&gt;</summary>
		<author><name>Spark</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=Opentaps_Hibernate_Integration&amp;diff=5037</id>
		<title>Opentaps Hibernate Integration</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=Opentaps_Hibernate_Integration&amp;diff=5037"/>
		<updated>2009-11-21T03:56:58Z</updated>

		<summary type="html">&lt;p&gt;Spark: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Beginning with opentaps version 1.4, [http://www.hibernate.org Hibernate] will be available as a persistence tool alongside with the original ofbiz entity engine.  Hibernate is a more object oriented persistence framework and better suited for the new [[Domain Driven Architecture]], while the ofbiz entity engine will continue to be supported for legacy features from both ofbiz and opentaps.  In this document, we will review how the hibernate integration in opentaps works.&lt;br /&gt;
&lt;br /&gt;
== Working with Hibernate in opentaps ==&lt;br /&gt;
&lt;br /&gt;
=== Generating Hibernate Configuration Files ===&lt;br /&gt;
&lt;br /&gt;
After changing or defining new entities in your &amp;lt;tt&amp;gt;entitymodel.xml&amp;lt;/tt&amp;gt; files, you need to generate new Java classes for your entities with&lt;br /&gt;
 $ ant make-base-entities&lt;br /&gt;
&lt;br /&gt;
This command updates the Java classes defined in &amp;lt;tt&amp;gt;org.opentaps.domain.base.entities&amp;lt;/tt&amp;gt;, including their hibernate annotations, and the &amp;lt;tt&amp;gt;hibernate.cfg.xml&amp;lt;/tt&amp;gt; for integrating with hibernate.  (If you use a repository management system, you must commit both and you Java classes and the updated &amp;lt;tt&amp;gt;hibernate.cfg.xml&amp;lt;/tt&amp;gt; files.)&lt;br /&gt;
&lt;br /&gt;
{{note|Important|Be sure to reference the JARs from &amp;lt;tt&amp;gt;/hot-deploy/opentaps-common/lib/hibernate&amp;lt;/tt&amp;gt; in your Ant build file, or else during build it will not be able to locate the appropriate Hibernate files.}}&lt;br /&gt;
&lt;br /&gt;
=== Accessing Entities with Hibernate ===&lt;br /&gt;
&lt;br /&gt;
{{tip|Tip|If you are developing in Eclipse, when using Hibernate make sure to run the ant task &amp;lt;tt&amp;gt;make-base-entities&amp;lt;/tt&amp;gt; immediately after you are done defining new entities. Also make sure you refresh the Eclipse project so that it picks up the new Hibernate POJOs for code-assist.}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To use hibernate to access your entities, you will need an &amp;lt;tt&amp;gt;org.opentaps.foundation.entity.hibernate.Session&amp;lt;/tt&amp;gt;, which is an extension of the &amp;lt;tt&amp;gt;org.hibernate.Session&amp;lt;/tt&amp;gt; class.  You can obtain it from the Infrastructure class like this:&lt;br /&gt;
        session = infrastructure.getSession();&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;Infrastructure&amp;lt;/tt&amp;gt; must be created from &amp;lt;tt&amp;gt;dispatcher&amp;lt;/tt&amp;gt; in order to obtain the hibernate session.&lt;br /&gt;
&lt;br /&gt;
In situations where you are passing through the service engine the &amp;lt;tt&amp;gt;dispatcher&amp;lt;/tt&amp;gt; is obtained from the &amp;lt;tt&amp;gt;DispatchContext&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
        public static Map myNewService(DispatchContext dctx, Map context) {&lt;br /&gt;
            LocalDispatcher dispatcher = dctx.getDispatcher();&lt;br /&gt;
    &lt;br /&gt;
            try {&lt;br /&gt;
                Infrastructure infrastructure = new Infrastructure(dispatcher);&lt;br /&gt;
                Session session = infrastructure.getSession();&lt;br /&gt;
            } catch (InfrastructureException e) {&lt;br /&gt;
                // TODO Auto-generated catch block&lt;br /&gt;
                e.printStackTrace();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
In situations where you are bypassing the service engine and accessing the Java method directly the &amp;lt;tt&amp;gt;dispatcher&amp;lt;/tt&amp;gt; is obtained from &amp;lt;tt&amp;gt;HttpServletRequest&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
    public static Map myNewService(HttpServletRequest request, HttpServletResponse response) {&lt;br /&gt;
        LocalDispatcher dispatcher = (LocalDispatcher) request.getAttribute(&amp;quot;dispatcher&amp;quot;);&lt;br /&gt;
    &lt;br /&gt;
        try {&lt;br /&gt;
            Infrastructure infrastructure = new Infrastructure(dispatcher);&lt;br /&gt;
            Session session = infrastructure.getSession();&lt;br /&gt;
        } catch (InfrastructureException e) {&lt;br /&gt;
            // TODO Auto-generated catch block&lt;br /&gt;
            e.printStackTrace();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
Then, you can work with it as if it were a Hibernate &amp;lt;tt&amp;gt;Session&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
        Transaction tx = session.beginTransaction();&lt;br /&gt;
        TestEntity newTestEntity = new TestEntity();&lt;br /&gt;
        newTestEntity.setTestStringField(&amp;quot;testInsertTestEntity string field&amp;quot;);&lt;br /&gt;
        newTestEntity.setCreatedStamp(UtilDateTime.nowTimestamp());&lt;br /&gt;
        session.save(newTestEntity);&lt;br /&gt;
        tx.commit();&lt;br /&gt;
        session.flush();&lt;br /&gt;
        // ...&lt;br /&gt;
        TestEntity loadEntity = (TestEntity) session.load(TestEntity.class, newTestEntity.getTestId());&lt;br /&gt;
        // ...&lt;br /&gt;
        String hql = &amp;quot;from TestEntity eo where eo.testId='&amp;quot; + testEntityId2 + &amp;quot;'&amp;quot;;&lt;br /&gt;
        Query query = session.createQuery(hql);&lt;br /&gt;
        List&amp;lt;TestEntity&amp;gt; list = query.list()&lt;br /&gt;
 &lt;br /&gt;
You do not need to close your JDBC connection manually with the opentaps Session, however.  When you call&lt;br /&gt;
            session.close();&lt;br /&gt;
It will do it for you automatically.&lt;br /&gt;
&lt;br /&gt;
=== Traversing Related Entities ===&lt;br /&gt;
&lt;br /&gt;
opentaps will automatically create the relationship annotations, such as @OneToMany, @ManyToMany, and @Join, for your Java classes.&lt;br /&gt;
&lt;br /&gt;
To get related entities, use the hibernate query language (HQL):&lt;br /&gt;
    String hql = &amp;quot;from TestEntityItem eo where eo.testEntity.testId='&amp;quot; + testEntity.getTestId() + &amp;quot;'&amp;quot;&lt;br /&gt;
               + &amp;quot; and eo.testEntityItemSeqId in (&amp;quot; + testEntityItemSeqIds + &amp;quot;)&amp;quot;;&lt;br /&gt;
    Query query = session.createQuery(hql);&lt;br /&gt;
    List&amp;lt;TestEntityItem&amp;gt; list = query.list();&lt;br /&gt;
&lt;br /&gt;
Or use the getter methods in the base entities:&lt;br /&gt;
    List&amp;lt;TestEntityItem&amp;gt; list = testEntity.getTestEntityItems();&lt;br /&gt;
&lt;br /&gt;
Note that hibernate will automatically load related entities for you, so the getRelated  methods from Repository which were designed for the ofbiz entity engine are no longer needed when you work with hibernate.&lt;br /&gt;
&lt;br /&gt;
=== Working with View Entities ===&lt;br /&gt;
&lt;br /&gt;
Once a view entity has been defined in &amp;lt;tt&amp;gt;entitymodel.xml&amp;lt;/tt&amp;gt;, you can access it as any other Java object from hibernate, for example:&lt;br /&gt;
        Query query = session.createQuery(&amp;quot;from TestEntityAndItem eo where eo.testId='&amp;quot; &lt;br /&gt;
                    + testEntityId + &amp;quot;' order by eo.testEntityItemSeqId&amp;quot;);&lt;br /&gt;
        List&amp;lt;TestEntityAndItem&amp;gt; list = query.list();&lt;br /&gt;
        &lt;br /&gt;
The opentaps  Session, which extends the hibernate Session, will automatically create the SQL for accessing the view entity.&lt;br /&gt;
&lt;br /&gt;
=== Using Transactions ===&lt;br /&gt;
&lt;br /&gt;
You should use the transaction manager configured in the ofbiz entity engine through the &amp;lt;tt&amp;gt;[http://java.sun.com/j2ee/sdk_1.3/techdocs/api/javax/transaction/UserTransaction.html UserTransaction]&amp;lt;/tt&amp;gt;  class.  In the entity engine, the transaction manager is configured as:&lt;br /&gt;
  &amp;lt;transaction-factory class=&amp;quot;org.ofbiz.geronimo.GeronimoTransactionFactory&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is obtained from the ofbiz &amp;lt;tt&amp;gt;TransactionFactory&amp;lt;/tt&amp;gt; by our &amp;lt;tt&amp;gt;Session&amp;lt;/tt&amp;gt; and used the same way as a hibernate transaction:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     UserTransaction tx = session.beginUserTransaction();&lt;br /&gt;
     // do something useful&lt;br /&gt;
     tx.commit();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Auto Generating ID Values ===&lt;br /&gt;
&lt;br /&gt;
ofbiz keeps track of auto generated sequence IDs in an entity called &amp;lt;tt&amp;gt;SequenceValueItem&amp;lt;/tt&amp;gt;  To make sure that the auto generated sequence IDs from hibernate and the ofbiz entity engine work well together, we have created an &amp;lt;tt&amp;gt;OpentapsIdentifierGenerator&amp;lt;/tt&amp;gt; which also uses the same &amp;lt;tt&amp;gt;SequenceValueItem&amp;lt;/tt&amp;gt; to obtain the next sequential ID.  This ID generator is wired to the base entity POJO Java objects with hibernate annotations, like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 @org.hibernate.annotations.GenericGenerator(name=&amp;quot;Party_GEN&amp;quot;,  strategy=&amp;quot;org.opentaps.foundation.entity.hibernate.OpentapsIdentifierGenerator&amp;quot;)&lt;br /&gt;
 @GeneratedValue(generator=&amp;quot;Party_GEN&amp;quot;)   &lt;br /&gt;
 @Id&lt;br /&gt;
    &lt;br /&gt;
 @Column(name=&amp;quot;PARTY_ID&amp;quot;)&lt;br /&gt;
    &lt;br /&gt;
 private String partyId;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So that a &amp;lt;tt&amp;gt;partyId&amp;lt;/tt&amp;gt; field is automatically set for you.&lt;br /&gt;
&lt;br /&gt;
You can also ask the &amp;lt;tt&amp;gt;Session&amp;lt;/tt&amp;gt; to generate a particular sequence ID for you:&lt;br /&gt;
 String testEntityItemSeqId = session.getNextSeqId(&amp;quot;TestEntityItemSeqId&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
This can be helpful when you have complex keys with several fields, and you want the secondary key fields to be auto sequenced as well.&lt;br /&gt;
&lt;br /&gt;
=== Support for OFBIZ EECA's ===&lt;br /&gt;
&lt;br /&gt;
ofbiz EECA's are supported with custom event listeners which are registered with hibernate when &amp;lt;tt&amp;gt;Infrastructure.getSessionFactory(String delegatorName)&amp;lt;/tt&amp;gt; is called, usually during the initial startup.  These event listeners will run ofbiz services defined in &amp;lt;tt&amp;gt;eeca.xml&amp;lt;/tt&amp;gt;'s  when hibernate is used to update the same entities.&lt;br /&gt;
&lt;br /&gt;
=== Caching ===&lt;br /&gt;
Our caching system now support ofbiz &amp;lt;-&amp;gt; hibernate mutual cache clearing. It mean it will sync hibernate cache on you update GenericValue with ofbiz entity engine, and vice versa. The hibernate cache configuration is locate in HibernateCfg.ftl (it also in hibernate.cfg.xml) as following:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  &amp;lt;property name=&amp;quot;hibernate.search.worker.execution&amp;quot;&amp;gt;async&amp;lt;/property&amp;gt;&lt;br /&gt;
  &amp;lt;property name=&amp;quot;hibernate.cache.use_query_cache&amp;quot;&amp;gt;true&amp;lt;/property&amp;gt;&lt;br /&gt;
  &amp;lt;property name=&amp;quot;hibernate.cache.use_second_level_cache&amp;quot;&amp;gt;true&amp;lt;/property&amp;gt;&lt;br /&gt;
  &amp;lt;property name=&amp;quot;hibernate.search.worker.buffer_queue.max&amp;quot;&amp;gt;5&amp;lt;/property&amp;gt;&lt;br /&gt;
  &amp;lt;property name=&amp;quot;hibernate.search.worker.thread_pool.size&amp;quot;&amp;gt;5&amp;lt;/property&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
you can disable the caching feature by remove these lines (both HibernateCfg.ftl and hibernate.cfg.xml).&lt;br /&gt;
Note: the entities of current open session will not update when it change by ofbiz entity engine, you must using open a new session to get fresh object. and the best practise is also close your session when it finish the job.&lt;br /&gt;
&lt;br /&gt;
=== Using Hibernate without the OFBIZ Entity Engine ===&lt;br /&gt;
&lt;br /&gt;
You can also use hibernate without the ofbiz entity engine by adding your Java objects to the template opentaps uses to generate the hibernate configuration files, &amp;lt;tt&amp;gt;hot-deploy/opentaps-common/templates/HibernateCfg.ftl&amp;lt;/tt&amp;gt;.  Simply put your Java objects after the &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  &amp;lt;#list&amp;gt;&lt;br /&gt;
    ...&lt;br /&gt;
  &amp;lt;/#list&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
directives in the file, like in the following example:    &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;!DOCTYPE hibernate-configuration PUBLIC &amp;quot;-//Hibernate/Hibernate Configuration DTD 3.0//EN&amp;quot; &amp;quot;http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;hibernate-configuration&amp;gt;&lt;br /&gt;
  &amp;lt;session-factory&amp;gt;&lt;br /&gt;
  &amp;lt;property name=&amp;quot;hibernate.connection.provider_class&amp;quot;&amp;gt;org.opentaps.foundation.entity.hibernate.OpentapsConnectionProvider&amp;lt;/property&amp;gt;  &lt;br /&gt;
  &amp;lt;property name=&amp;quot;hibernate.transaction.factory_class&amp;quot;&amp;gt;org.opentaps.foundation.entity.hibernate.OpentapsTransactionFactory&amp;lt;/property&amp;gt;&lt;br /&gt;
  &amp;lt;property name=&amp;quot;hibernate.transaction.manager_lookup_class&amp;quot;&amp;gt;org.opentaps.foundation.entity.hibernate.OpentapsTransactionManagerLookup&amp;lt;/property&amp;gt;  &lt;br /&gt;
  &amp;lt;property name=&amp;quot;hibernate.search.default.directory_provider&amp;quot;&amp;gt;org.hibernate.search.store.FSDirectoryProvider&amp;lt;/property&amp;gt;&lt;br /&gt;
&amp;lt;#list entities as entity&amp;gt;&lt;br /&gt;
  &amp;lt;mapping class=&amp;quot;org.opentaps.domain.base.entities.${entity}&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/#list&amp;gt;&lt;br /&gt;
  &amp;lt;mapping class=&amp;quot;org.opentaps.domain.base.entities.MyPojo1&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;mapping class=&amp;quot;org.opentaps.domain.base.entities.MyPojo2&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;/session-factory&amp;gt;&lt;br /&gt;
&amp;lt;/hibernate-configuration&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
opentaps will then create the hibernate configuration file for each database and include your Java objects in it.  However, you would not be able to access these Java objects as generic values from the ofbiz entity engine.&lt;br /&gt;
&lt;br /&gt;
== Under the Hood: How It Works ==&lt;br /&gt;
&lt;br /&gt;
=== Base Class Annotations ===&lt;br /&gt;
&lt;br /&gt;
In opentaps version 1.4, the entity model XML from the ofbiz entity engine is still used as the base definition for all entities.  The opentaps POJO generator is used to create [[Base Entity Classes|base Java objects]] automatically from these entity definitions.  This POJO generator will also create the annotations which hibernate can then use to map those base objects to the database persistence layer.  The definitions of the annotations can be found in &amp;lt;tt&amp;gt;BaseEntity.ftl&amp;lt;/tt&amp;gt; file used by the POJO generator.&lt;br /&gt;
&lt;br /&gt;
=== How Hibernate Configuration Files are Generated ===&lt;br /&gt;
&lt;br /&gt;
The POJO Generator will use &amp;lt;tt&amp;gt;hot-deploy/opentaps-common/templates/HibernateCfg.ftl&amp;lt;/tt&amp;gt; to generate a base hibernate configuration file in &amp;lt;tt&amp;gt;hot-deploy/opentaps-common/config/hibernate.cfg.xml&amp;lt;/tt&amp;gt;  When opentaps is started, the following new container in &amp;lt;tt&amp;gt;framework/base/config/ofbiz-containers.xml&amp;lt;/tt&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    &amp;lt;container name=&amp;quot;hibernate-container&amp;quot; class=&amp;quot;org.opentaps.common.container.HibernateContainer&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;property name=&amp;quot;delegator-name&amp;quot; value=&amp;quot;default&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;/container&amp;gt;    &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will generate all the hibernate configuration XML files in the &amp;lt;tt&amp;gt;hot-deploy/opentaps/config/&amp;lt;/tt&amp;gt; directory for each data source in your entity engine XML file.  For example, it will generate a &amp;lt;tt&amp;gt;localmysql.cfg.xml&amp;lt;/tt&amp;gt;, a &amp;lt;tt&amp;gt;localpostgres.cfg.xml&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How We Get the Hibernate Session ===&lt;br /&gt;
&lt;br /&gt;
The opentaps &amp;lt;tt&amp;gt;Infrastructure&amp;lt;/tt&amp;gt; Class maintains a Map of delegatorName and hibernate SessionFactory objects.  Each SessionFactory is created for its corresponding delegatorName the first time it is requested from the &amp;lt;tt&amp;gt;Infrastructure.getSessionFactory(delegatorName)&amp;lt;/tt&amp;gt; method.  This SessionFactory is created from ofbiz entity engine configurations:&lt;br /&gt;
* The &amp;lt;tt&amp;gt;HibernateContainer&amp;lt;/tt&amp;gt; in &amp;lt;tt&amp;gt;ofbiz-containers.xml&amp;lt;/tt&amp;gt; has a property called &amp;lt;tt&amp;gt;delegator-name&amp;lt;/tt&amp;gt;&lt;br /&gt;
* From this delegator, we get the data source defined in &amp;lt;tt&amp;gt;entityengine.xml&amp;lt;/tt&amp;gt; for the default group helper name.  This is set to &amp;lt;tt&amp;gt;org.ofbiz&amp;lt;/tt&amp;gt; by default in the &amp;lt;tt&amp;gt;Infrastructure&amp;lt;/tt&amp;gt; class and is the &amp;lt;tt&amp;gt;group&amp;lt;/tt&amp;gt; attribute of the &amp;lt;tt&amp;gt;entitygroup.xml&amp;lt;/tt&amp;gt; definitions in ofbiz:&lt;br /&gt;
  &amp;lt;entity-group group=&amp;quot;org.ofbiz&amp;quot; entity=&amp;quot;AcctgTagEnumType&amp;quot;/&amp;gt;&lt;br /&gt;
In &amp;lt;tt&amp;gt;entityengine.xml&amp;lt;/tt&amp;gt;, you map a data source to each group:&lt;br /&gt;
    &amp;lt;delegator name=&amp;quot;default&amp;quot; entity-model-reader=&amp;quot;main&amp;quot; entity-group-reader=&amp;quot;main&amp;quot; entity-eca-reader=&amp;quot;main&amp;quot; distributed-cache-clear-enabled=&amp;quot;false&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;group-map group-name=&amp;quot;org.ofbiz&amp;quot; datasource-name=&amp;quot;localmysql&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;/delegator&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So, we are basically following the entity engine from the delegator to the data source via the group.&lt;br /&gt;
* Once we have the data source, we can create the SessionFactory from the hibernate.cfg.xml for that data source.  For example, if your data source is &amp;quot;localmysql&amp;quot;, we will create the SessionFactory from the &amp;lt;tt&amp;gt;localmysql.cfg.xml&amp;lt;/tt&amp;gt;   created by the &amp;lt;tt&amp;gt;HibernateContainer&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;HibernateContainer&amp;lt;/tt&amp;gt;, which loads on startup, will cause a SessionFactory to be loaded for the delegator in the &amp;lt;tt&amp;gt;delegator-name&amp;lt;/tt&amp;gt; attribute.  Once this SessionFactory is loaded, it will be available for future use.  Additional session factories can be obtained later by calling the &amp;lt;tt&amp;gt;getSessionFactory&amp;lt;/tt&amp;gt; directly.&lt;br /&gt;
&lt;br /&gt;
When the &amp;lt;tt&amp;gt;Infrastructure.getSession()&amp;lt;/tt&amp;gt; method is called,  it will use the delegator already in the Infrastructure object to open a JDBC connection first, and then use that JDBC connection and the SessionFactory for the delegator to return a Session.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;Infrastructure.getSession()&amp;lt;/tt&amp;gt; will return an &amp;lt;tt&amp;gt;org.opentaps.foundation.entity.hibernate.Session&amp;lt;/tt&amp;gt;, which extends the hibernate Session with the following differences:&lt;br /&gt;
* when the session is closed, the JDBC connection is also automatically closed&lt;br /&gt;
* when a Query is created, this Session will check if the query is on an entity engine view entity and construct the Query from native SQL first&lt;br /&gt;
&lt;br /&gt;
=== View Entities ===&lt;br /&gt;
&lt;br /&gt;
View entities are supported with @NamedNativeQuery annotations in the base entity Java classes, which are automatically generated by the opentaps POJO Generator.&lt;br /&gt;
&lt;br /&gt;
=== Encryption ===&lt;br /&gt;
&lt;br /&gt;
The ofbiz delegator allows you to set a field to be encrypted in the database with the &amp;lt;tt&amp;gt;encrypt=&amp;quot;true&amp;quot;&amp;lt;/tt&amp;gt; attribute in the &amp;lt;tt&amp;gt;field&amp;lt;/tt&amp;gt; tag of an entity definition.  The opentaps hibernate will support the same encryption/decryption algorithm, so that encrypted values can be stored with the delegator and decrypted when it's retrieved with hibernate or vice versa.  This is done by:&lt;br /&gt;
# When an object is being stored, the &amp;lt;tt&amp;gt;EcaCommEvent.beforeSave&amp;lt;/tt&amp;gt; Method will come for the object to an ofbiz GenericValue and then use the ofbiz delegator to encrypt it.&lt;br /&gt;
# When an object is retrieved from the database, the &amp;lt;tt&amp;gt;Session.load&amp;lt;/tt&amp;gt; will call the &amp;lt;tt&amp;gt;HibernateUtil.decryptField&amp;lt;/tt&amp;gt; to decrypt it.&lt;br /&gt;
&lt;br /&gt;
=== Transaction Management ===&lt;br /&gt;
&lt;br /&gt;
To maintain compatibility with the ofbiz entity engine's transaction manager and connection pool providers, we have defined transaction manager look up, transaction factory, and connection provider classes which use the ofbiz transaction manager and transaction factory to begin transactions.  These are defined in the &amp;lt;tt&amp;gt;hibernate.cfg.xml&amp;lt;/tt&amp;gt; configuration file.  They allow you to mix delegator and hibernate transaction codes as in this following example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        UserTransaction tx = session.beginUserTransaction();&lt;br /&gt;
        TestEntity useIdentifierTestEntity = new TestEntity();&lt;br /&gt;
        useIdentifierTestEntity.setTestStringField(&amp;quot;Use IdentifierGenerator string field&amp;quot;);&lt;br /&gt;
        session.save(useIdentifierTestEntity);&lt;br /&gt;
        String getNextSeqIdTestEntityId = delegator.getNextSeqId(&amp;quot;TestEntity&amp;quot;);&lt;br /&gt;
        GenericValue useGetNextSeqIdTestEntity = delegator.create(&amp;quot;TestEntity&amp;quot;,&lt;br /&gt;
                UtilMisc.toMap(&amp;quot;testId&amp;quot;, getNextSeqIdTestEntityId,  &amp;quot;testStringField&amp;quot;, &amp;quot;Use getNextSeqId string field&amp;quot;));&lt;br /&gt;
        session.flush();&lt;br /&gt;
        tx.commit();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Support for BLOBs ===&lt;br /&gt;
&lt;br /&gt;
To make the &amp;quot;BLOB&amp;quot; type work with postgresql, we made the following changes:&lt;br /&gt;
# change blob field mapping to Java byte[] &lt;br /&gt;
# avoid using the &amp;lt;tt&amp;gt;@Lob&amp;lt;/tt&amp;gt; annotation&lt;br /&gt;
# add this element in hibernate.cfg.xml&lt;br /&gt;
 &amp;lt;property name=&amp;quot;hibernate.jdbc.use_streams_for_binary&amp;quot;&amp;gt;true&amp;lt;/property&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Unit Tests ===&lt;br /&gt;
&lt;br /&gt;
Unit tests for hibernate are found in &amp;lt;tt&amp;gt;org.opentaps.tests.entity.HibernateTests&amp;lt;/tt&amp;gt; in the opentaps-tests component.&lt;br /&gt;
&lt;br /&gt;
== Learning More ==&lt;br /&gt;
&lt;br /&gt;
The best way to learn more about how to use hibernate with opentaps is to look through the unit tests in &amp;lt;tt&amp;gt;org.opentaps.tests.entity.HibernateTests&amp;lt;/tt&amp;gt; as an example.&lt;/div&gt;</summary>
		<author><name>Spark</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=Upgrading_from_opentaps_1.0_to_opentaps_1.4&amp;diff=4368</id>
		<title>Upgrading from opentaps 1.0 to opentaps 1.4</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=Upgrading_from_opentaps_1.0_to_opentaps_1.4&amp;diff=4368"/>
		<updated>2009-09-15T23:36:06Z</updated>

		<summary type="html">&lt;p&gt;Spark: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
== Data Changes ==&lt;br /&gt;
&lt;br /&gt;
* Run the service &amp;lt;tt&amp;gt;opentaps.setSupplementalDataForAllParties&amp;lt;/tt&amp;gt; to populate primary contact data for all parties.&lt;br /&gt;
* Configuration of GL accounts for invoice writeoffs have been changed.  Instead of using &amp;lt;tt&amp;gt;GlAccountTypeDefault&amp;lt;/tt&amp;gt;, they are now configured with &amp;lt;tt&amp;gt;InvoiceAdjustmentGlAccount&amp;lt;/tt&amp;gt; with the adjustment type &amp;quot;WRITEOFF&amp;quot;&lt;br /&gt;
* If you have custom UI labels, they may be loaded by adding them to &amp;lt;tt&amp;gt;LabelConfiguration.properties&amp;lt;/tt&amp;gt; in &amp;lt;tt&amp;gt;opentaps-common/config/&amp;lt;/tt&amp;gt;&lt;br /&gt;
** If previously you were using &amp;lt;tt&amp;gt;UtilMessage.registerLabelMap()&amp;lt;/tt&amp;gt; to load custom labels, you may now remove all calls to this function as it is no longer needed.&lt;br /&gt;
* Run the upgrade SQL script in hot-deploy/opentaps-common/scripts/sql for the following:&lt;br /&gt;
** &amp;lt;tt&amp;gt;ProductAverageCost&amp;lt;/tt&amp;gt; has been re-factored to use a single productAverageCostId as its primary key.  The script will alter the table and automatically fill in its values and update &amp;lt;tt&amp;gt;SequenceValueItem&amp;lt;/tt&amp;gt; so that opentaps will generate correct future keys.&lt;br /&gt;
* Add the following to your custom component's build.xml:&lt;br /&gt;
   &amp;lt;fileset dir=&amp;quot;${ofbiz.dir}/hot-deploy/opentaps-common/lib&amp;quot; includes=&amp;quot;*.jar&amp;quot;/&amp;gt;&lt;br /&gt;
   &amp;lt;fileset dir=&amp;quot;${ofbiz.dir}/hot-deploy/opentaps-common/lib/hibernate&amp;quot; includes=&amp;quot;*.jar&amp;quot;/&amp;gt;&lt;br /&gt;
* Set &amp;lt;tt&amp;gt;SupplierProduct.supplierPrefOrderId&amp;lt;/tt&amp;gt; to '''10_MAIN_SUPPL''' where it is null.&lt;br /&gt;
&lt;br /&gt;
== Coding Changes ==&lt;br /&gt;
&lt;br /&gt;
Changes in the ofbiz framework would require the following changes to your code:&lt;br /&gt;
&lt;br /&gt;
=== URL Parameter Security ===&lt;br /&gt;
&lt;br /&gt;
You can no longer pass parameters to a service request directly in the URL.  These requests must be part of a POST form.  To make buttons work as before, you need to change them to forms and then activate them with javascript.  For example, in earlier versions, you could have a button to delete a lead like this:&lt;br /&gt;
  &amp;lt;#assign update_options = update_options + &amp;quot;&amp;lt;a class='subMenuButtonDangerous' &lt;br /&gt;
           href='deleteLead?leadPartyId=&amp;quot; + partySummary.partyId + &amp;quot;'&amp;gt;&amp;quot; + uiLabelMap.CommonDelete + &amp;quot;&amp;lt;/a&amp;gt;&amp;quot;  /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In opentaps 1.4, you must do it this way:&lt;br /&gt;
   &amp;lt;form name=&amp;quot;deleteLeadForm&amp;quot; method=&amp;quot;post&amp;quot; action=&amp;quot;&amp;lt;@ofbizUrl&amp;gt;deleteLead&amp;lt;/@ofbizUrl&amp;gt;&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;@inputHidden name=&amp;quot;leadPartyId&amp;quot; value=&amp;quot;${partySummary.partyId}&amp;quot;/&amp;gt;&lt;br /&gt;
   &amp;lt;/form&amp;gt;&lt;br /&gt;
   &amp;lt;#assign update_options = update_options + &amp;quot;&amp;lt;a class='subMenuButtonDangerous' &lt;br /&gt;
            href='javascript:document.deleteLeadForm.submit()'&amp;gt;&amp;quot; + uiLabelMap.CommonDelete + &amp;quot;&amp;lt;/a&amp;gt;&amp;quot;  /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Controller redirects ===&lt;br /&gt;
&lt;br /&gt;
Redirects have been changed, now ''request-redirect'' will only copy the parameters that were in the URL string by default. To forward posted or service output parameter, use the ''redirect-parameter'' elements (one per parameter).&lt;br /&gt;
   &amp;lt;response name=&amp;quot;success&amp;quot; type=&amp;quot;request-redirect&amp;quot; value=&amp;quot;viewAccount&amp;quot;&amp;gt;&lt;br /&gt;
       &amp;lt;redirect-parameter name=&amp;quot;partyId&amp;quot;/&amp;gt;&lt;br /&gt;
   &amp;lt;/response&amp;gt;&lt;br /&gt;
Also ''request-redirect-filter-param'' is now considered deprecated.&lt;br /&gt;
&lt;br /&gt;
=== Js dateTime format ===&lt;br /&gt;
&lt;br /&gt;
Js dataTime format in ftl have been changed, now the format will return html encode string which will cause the parse exception, you should use StringUtil.wrapString to avoid this issue. For example, in earlier versions, you could have define a js dataTime format variable like this:&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;#assign dateFormat = Static[&amp;quot;org.opentaps.common.util.UtilDate&amp;quot;].getJsDateTimeFormat(Static[&amp;quot;org.opentaps.common.util.UtilDate&amp;quot;].getDateFormat(locale))/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In opentaps 1.4, you must do it this way:&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;#assign dateFormat = StringUtil.wrapString(Static[&amp;quot;org.opentaps.common.util.UtilDate&amp;quot;].getJsDateTimeFormat(Static[&amp;quot;org.opentaps.common.util.UtilDate&amp;quot;].getDateFormat(locale)))/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Spark</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=Upgrading_from_opentaps_1.0_to_opentaps_1.4&amp;diff=4367</id>
		<title>Upgrading from opentaps 1.0 to opentaps 1.4</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=Upgrading_from_opentaps_1.0_to_opentaps_1.4&amp;diff=4367"/>
		<updated>2009-09-15T23:35:01Z</updated>

		<summary type="html">&lt;p&gt;Spark: /* Js dateTime format */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
== Data Changes ==&lt;br /&gt;
&lt;br /&gt;
* Run the service &amp;lt;tt&amp;gt;opentaps.setSupplementalDataForAllParties&amp;lt;/tt&amp;gt; to populate primary contact data for all parties.&lt;br /&gt;
* Configuration of GL accounts for invoice writeoffs have been changed.  Instead of using &amp;lt;tt&amp;gt;GlAccountTypeDefault&amp;lt;/tt&amp;gt;, they are now configured with &amp;lt;tt&amp;gt;InvoiceAdjustmentGlAccount&amp;lt;/tt&amp;gt; with the adjustment type &amp;quot;WRITEOFF&amp;quot;&lt;br /&gt;
* If you have custom UI labels, they may be loaded by adding them to &amp;lt;tt&amp;gt;LabelConfiguration.properties&amp;lt;/tt&amp;gt; in &amp;lt;tt&amp;gt;opentaps-common/config/&amp;lt;/tt&amp;gt;&lt;br /&gt;
** If previously you were using &amp;lt;tt&amp;gt;UtilMessage.registerLabelMap()&amp;lt;/tt&amp;gt; to load custom labels, you may now remove all calls to this function as it is no longer needed.&lt;br /&gt;
* Run the upgrade SQL script in hot-deploy/opentaps-common/scripts/sql for the following:&lt;br /&gt;
** &amp;lt;tt&amp;gt;ProductAverageCost&amp;lt;/tt&amp;gt; has been re-factored to use a single productAverageCostId as its primary key.  The script will alter the table and automatically fill in its values and update &amp;lt;tt&amp;gt;SequenceValueItem&amp;lt;/tt&amp;gt; so that opentaps will generate correct future keys.&lt;br /&gt;
* Add the following to your custom component's build.xml:&lt;br /&gt;
   &amp;lt;fileset dir=&amp;quot;${ofbiz.dir}/hot-deploy/opentaps-common/lib&amp;quot; includes=&amp;quot;*.jar&amp;quot;/&amp;gt;&lt;br /&gt;
   &amp;lt;fileset dir=&amp;quot;${ofbiz.dir}/hot-deploy/opentaps-common/lib/hibernate&amp;quot; includes=&amp;quot;*.jar&amp;quot;/&amp;gt;&lt;br /&gt;
* Set &amp;lt;tt&amp;gt;SupplierProduct.supplierPrefOrderId&amp;lt;/tt&amp;gt; to '''10_MAIN_SUPPL''' where it is null.&lt;br /&gt;
&lt;br /&gt;
== Coding Changes ==&lt;br /&gt;
&lt;br /&gt;
Changes in the ofbiz framework would require the following changes to your code:&lt;br /&gt;
&lt;br /&gt;
=== URL Parameter Security ===&lt;br /&gt;
&lt;br /&gt;
You can no longer pass parameters to a service request directly in the URL.  These requests must be part of a POST form.  To make buttons work as before, you need to change them to forms and then activate them with javascript.  For example, in earlier versions, you could have a button to delete a lead like this:&lt;br /&gt;
  &amp;lt;#assign update_options = update_options + &amp;quot;&amp;lt;a class='subMenuButtonDangerous' &lt;br /&gt;
           href='deleteLead?leadPartyId=&amp;quot; + partySummary.partyId + &amp;quot;'&amp;gt;&amp;quot; + uiLabelMap.CommonDelete + &amp;quot;&amp;lt;/a&amp;gt;&amp;quot;  /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In opentaps 1.4, you must do it this way:&lt;br /&gt;
   &amp;lt;form name=&amp;quot;deleteLeadForm&amp;quot; method=&amp;quot;post&amp;quot; action=&amp;quot;&amp;lt;@ofbizUrl&amp;gt;deleteLead&amp;lt;/@ofbizUrl&amp;gt;&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;@inputHidden name=&amp;quot;leadPartyId&amp;quot; value=&amp;quot;${partySummary.partyId}&amp;quot;/&amp;gt;&lt;br /&gt;
   &amp;lt;/form&amp;gt;&lt;br /&gt;
   &amp;lt;#assign update_options = update_options + &amp;quot;&amp;lt;a class='subMenuButtonDangerous' &lt;br /&gt;
            href='javascript:document.deleteLeadForm.submit()'&amp;gt;&amp;quot; + uiLabelMap.CommonDelete + &amp;quot;&amp;lt;/a&amp;gt;&amp;quot;  /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Controller redirects ===&lt;br /&gt;
&lt;br /&gt;
Redirects have been changed, now ''request-redirect'' will only copy the parameters that were in the URL string by default. To forward posted or service output parameter, use the ''redirect-parameter'' elements (one per parameter).&lt;br /&gt;
   &amp;lt;response name=&amp;quot;success&amp;quot; type=&amp;quot;request-redirect&amp;quot; value=&amp;quot;viewAccount&amp;quot;&amp;gt;&lt;br /&gt;
       &amp;lt;redirect-parameter name=&amp;quot;partyId&amp;quot;/&amp;gt;&lt;br /&gt;
   &amp;lt;/response&amp;gt;&lt;br /&gt;
Also ''request-redirect-filter-param'' is now considered deprecated.&lt;br /&gt;
&lt;br /&gt;
=== Js dateTime format ===&lt;br /&gt;
&lt;br /&gt;
Js dataTime format in ftl have been changed, now the format will return html encode string which will cause the parse exception, you should use StringUtil.wrapString to avoid this issue. For example, in earlier versions, you could have define a js dataTime format variable like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;#assign dateFormat = Static[&amp;quot;org.opentaps.common.util.UtilDate&amp;quot;].getJsDateTimeFormat(Static[&amp;quot;org.opentaps.common.util.UtilDate&amp;quot;].getDateFormat(locale))/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In opentaps 1.4, you must do it this way:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;#assign dateFormat = StringUtil.wrapString(Static[&amp;quot;org.opentaps.common.util.UtilDate&amp;quot;]&lt;br /&gt;
.getJsDateTimeFormat(Static[&amp;quot;org.opentaps.common.util.UtilDate&amp;quot;].getDateFormat(locale)))/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Spark</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=Upgrading_from_opentaps_1.0_to_opentaps_1.4&amp;diff=4366</id>
		<title>Upgrading from opentaps 1.0 to opentaps 1.4</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=Upgrading_from_opentaps_1.0_to_opentaps_1.4&amp;diff=4366"/>
		<updated>2009-09-15T23:34:05Z</updated>

		<summary type="html">&lt;p&gt;Spark: /* Js dateTime format */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
== Data Changes ==&lt;br /&gt;
&lt;br /&gt;
* Run the service &amp;lt;tt&amp;gt;opentaps.setSupplementalDataForAllParties&amp;lt;/tt&amp;gt; to populate primary contact data for all parties.&lt;br /&gt;
* Configuration of GL accounts for invoice writeoffs have been changed.  Instead of using &amp;lt;tt&amp;gt;GlAccountTypeDefault&amp;lt;/tt&amp;gt;, they are now configured with &amp;lt;tt&amp;gt;InvoiceAdjustmentGlAccount&amp;lt;/tt&amp;gt; with the adjustment type &amp;quot;WRITEOFF&amp;quot;&lt;br /&gt;
* If you have custom UI labels, they may be loaded by adding them to &amp;lt;tt&amp;gt;LabelConfiguration.properties&amp;lt;/tt&amp;gt; in &amp;lt;tt&amp;gt;opentaps-common/config/&amp;lt;/tt&amp;gt;&lt;br /&gt;
** If previously you were using &amp;lt;tt&amp;gt;UtilMessage.registerLabelMap()&amp;lt;/tt&amp;gt; to load custom labels, you may now remove all calls to this function as it is no longer needed.&lt;br /&gt;
* Run the upgrade SQL script in hot-deploy/opentaps-common/scripts/sql for the following:&lt;br /&gt;
** &amp;lt;tt&amp;gt;ProductAverageCost&amp;lt;/tt&amp;gt; has been re-factored to use a single productAverageCostId as its primary key.  The script will alter the table and automatically fill in its values and update &amp;lt;tt&amp;gt;SequenceValueItem&amp;lt;/tt&amp;gt; so that opentaps will generate correct future keys.&lt;br /&gt;
* Add the following to your custom component's build.xml:&lt;br /&gt;
   &amp;lt;fileset dir=&amp;quot;${ofbiz.dir}/hot-deploy/opentaps-common/lib&amp;quot; includes=&amp;quot;*.jar&amp;quot;/&amp;gt;&lt;br /&gt;
   &amp;lt;fileset dir=&amp;quot;${ofbiz.dir}/hot-deploy/opentaps-common/lib/hibernate&amp;quot; includes=&amp;quot;*.jar&amp;quot;/&amp;gt;&lt;br /&gt;
* Set &amp;lt;tt&amp;gt;SupplierProduct.supplierPrefOrderId&amp;lt;/tt&amp;gt; to '''10_MAIN_SUPPL''' where it is null.&lt;br /&gt;
&lt;br /&gt;
== Coding Changes ==&lt;br /&gt;
&lt;br /&gt;
Changes in the ofbiz framework would require the following changes to your code:&lt;br /&gt;
&lt;br /&gt;
=== URL Parameter Security ===&lt;br /&gt;
&lt;br /&gt;
You can no longer pass parameters to a service request directly in the URL.  These requests must be part of a POST form.  To make buttons work as before, you need to change them to forms and then activate them with javascript.  For example, in earlier versions, you could have a button to delete a lead like this:&lt;br /&gt;
  &amp;lt;#assign update_options = update_options + &amp;quot;&amp;lt;a class='subMenuButtonDangerous' &lt;br /&gt;
           href='deleteLead?leadPartyId=&amp;quot; + partySummary.partyId + &amp;quot;'&amp;gt;&amp;quot; + uiLabelMap.CommonDelete + &amp;quot;&amp;lt;/a&amp;gt;&amp;quot;  /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In opentaps 1.4, you must do it this way:&lt;br /&gt;
   &amp;lt;form name=&amp;quot;deleteLeadForm&amp;quot; method=&amp;quot;post&amp;quot; action=&amp;quot;&amp;lt;@ofbizUrl&amp;gt;deleteLead&amp;lt;/@ofbizUrl&amp;gt;&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;@inputHidden name=&amp;quot;leadPartyId&amp;quot; value=&amp;quot;${partySummary.partyId}&amp;quot;/&amp;gt;&lt;br /&gt;
   &amp;lt;/form&amp;gt;&lt;br /&gt;
   &amp;lt;#assign update_options = update_options + &amp;quot;&amp;lt;a class='subMenuButtonDangerous' &lt;br /&gt;
            href='javascript:document.deleteLeadForm.submit()'&amp;gt;&amp;quot; + uiLabelMap.CommonDelete + &amp;quot;&amp;lt;/a&amp;gt;&amp;quot;  /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Controller redirects ===&lt;br /&gt;
&lt;br /&gt;
Redirects have been changed, now ''request-redirect'' will only copy the parameters that were in the URL string by default. To forward posted or service output parameter, use the ''redirect-parameter'' elements (one per parameter).&lt;br /&gt;
   &amp;lt;response name=&amp;quot;success&amp;quot; type=&amp;quot;request-redirect&amp;quot; value=&amp;quot;viewAccount&amp;quot;&amp;gt;&lt;br /&gt;
       &amp;lt;redirect-parameter name=&amp;quot;partyId&amp;quot;/&amp;gt;&lt;br /&gt;
   &amp;lt;/response&amp;gt;&lt;br /&gt;
Also ''request-redirect-filter-param'' is now considered deprecated.&lt;br /&gt;
&lt;br /&gt;
=== Js dateTime format ===&lt;br /&gt;
&lt;br /&gt;
Js dataTime format in ftl have been changed, now the format will return html encode string which will cause the parse exception, you should use StringUtil.wrapString to avoid this issue. For example, in earlier versions, you could have define a js dataTime format variable like this:&lt;br /&gt;
   &amp;lt;#assign dateFormat = Static[&amp;quot;org.opentaps.common.util.UtilDate&amp;quot;].getJsDateTimeFormat(Static[&amp;quot;org.opentaps.common.util.UtilDate&amp;quot;].getDateFormat(locale))/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In opentaps 1.4, you must do it this way:&lt;br /&gt;
	&amp;lt;#assign dateFormat = StringUtil.wrapString(Static[&amp;quot;org.opentaps.common.util.UtilDate&amp;quot;]&lt;br /&gt;
.getJsDateTimeFormat(Static[&amp;quot;org.opentaps.common.util.UtilDate&amp;quot;].getDateFormat(locale)))/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Spark</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=Upgrading_from_opentaps_1.0_to_opentaps_1.4&amp;diff=4365</id>
		<title>Upgrading from opentaps 1.0 to opentaps 1.4</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=Upgrading_from_opentaps_1.0_to_opentaps_1.4&amp;diff=4365"/>
		<updated>2009-09-15T23:33:16Z</updated>

		<summary type="html">&lt;p&gt;Spark: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
== Data Changes ==&lt;br /&gt;
&lt;br /&gt;
* Run the service &amp;lt;tt&amp;gt;opentaps.setSupplementalDataForAllParties&amp;lt;/tt&amp;gt; to populate primary contact data for all parties.&lt;br /&gt;
* Configuration of GL accounts for invoice writeoffs have been changed.  Instead of using &amp;lt;tt&amp;gt;GlAccountTypeDefault&amp;lt;/tt&amp;gt;, they are now configured with &amp;lt;tt&amp;gt;InvoiceAdjustmentGlAccount&amp;lt;/tt&amp;gt; with the adjustment type &amp;quot;WRITEOFF&amp;quot;&lt;br /&gt;
* If you have custom UI labels, they may be loaded by adding them to &amp;lt;tt&amp;gt;LabelConfiguration.properties&amp;lt;/tt&amp;gt; in &amp;lt;tt&amp;gt;opentaps-common/config/&amp;lt;/tt&amp;gt;&lt;br /&gt;
** If previously you were using &amp;lt;tt&amp;gt;UtilMessage.registerLabelMap()&amp;lt;/tt&amp;gt; to load custom labels, you may now remove all calls to this function as it is no longer needed.&lt;br /&gt;
* Run the upgrade SQL script in hot-deploy/opentaps-common/scripts/sql for the following:&lt;br /&gt;
** &amp;lt;tt&amp;gt;ProductAverageCost&amp;lt;/tt&amp;gt; has been re-factored to use a single productAverageCostId as its primary key.  The script will alter the table and automatically fill in its values and update &amp;lt;tt&amp;gt;SequenceValueItem&amp;lt;/tt&amp;gt; so that opentaps will generate correct future keys.&lt;br /&gt;
* Add the following to your custom component's build.xml:&lt;br /&gt;
   &amp;lt;fileset dir=&amp;quot;${ofbiz.dir}/hot-deploy/opentaps-common/lib&amp;quot; includes=&amp;quot;*.jar&amp;quot;/&amp;gt;&lt;br /&gt;
   &amp;lt;fileset dir=&amp;quot;${ofbiz.dir}/hot-deploy/opentaps-common/lib/hibernate&amp;quot; includes=&amp;quot;*.jar&amp;quot;/&amp;gt;&lt;br /&gt;
* Set &amp;lt;tt&amp;gt;SupplierProduct.supplierPrefOrderId&amp;lt;/tt&amp;gt; to '''10_MAIN_SUPPL''' where it is null.&lt;br /&gt;
&lt;br /&gt;
== Coding Changes ==&lt;br /&gt;
&lt;br /&gt;
Changes in the ofbiz framework would require the following changes to your code:&lt;br /&gt;
&lt;br /&gt;
=== URL Parameter Security ===&lt;br /&gt;
&lt;br /&gt;
You can no longer pass parameters to a service request directly in the URL.  These requests must be part of a POST form.  To make buttons work as before, you need to change them to forms and then activate them with javascript.  For example, in earlier versions, you could have a button to delete a lead like this:&lt;br /&gt;
  &amp;lt;#assign update_options = update_options + &amp;quot;&amp;lt;a class='subMenuButtonDangerous' &lt;br /&gt;
           href='deleteLead?leadPartyId=&amp;quot; + partySummary.partyId + &amp;quot;'&amp;gt;&amp;quot; + uiLabelMap.CommonDelete + &amp;quot;&amp;lt;/a&amp;gt;&amp;quot;  /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In opentaps 1.4, you must do it this way:&lt;br /&gt;
   &amp;lt;form name=&amp;quot;deleteLeadForm&amp;quot; method=&amp;quot;post&amp;quot; action=&amp;quot;&amp;lt;@ofbizUrl&amp;gt;deleteLead&amp;lt;/@ofbizUrl&amp;gt;&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;@inputHidden name=&amp;quot;leadPartyId&amp;quot; value=&amp;quot;${partySummary.partyId}&amp;quot;/&amp;gt;&lt;br /&gt;
   &amp;lt;/form&amp;gt;&lt;br /&gt;
   &amp;lt;#assign update_options = update_options + &amp;quot;&amp;lt;a class='subMenuButtonDangerous' &lt;br /&gt;
            href='javascript:document.deleteLeadForm.submit()'&amp;gt;&amp;quot; + uiLabelMap.CommonDelete + &amp;quot;&amp;lt;/a&amp;gt;&amp;quot;  /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Controller redirects ===&lt;br /&gt;
&lt;br /&gt;
Redirects have been changed, now ''request-redirect'' will only copy the parameters that were in the URL string by default. To forward posted or service output parameter, use the ''redirect-parameter'' elements (one per parameter).&lt;br /&gt;
   &amp;lt;response name=&amp;quot;success&amp;quot; type=&amp;quot;request-redirect&amp;quot; value=&amp;quot;viewAccount&amp;quot;&amp;gt;&lt;br /&gt;
       &amp;lt;redirect-parameter name=&amp;quot;partyId&amp;quot;/&amp;gt;&lt;br /&gt;
   &amp;lt;/response&amp;gt;&lt;br /&gt;
Also ''request-redirect-filter-param'' is now considered deprecated.&lt;br /&gt;
&lt;br /&gt;
=== Js dateTime format ===&lt;br /&gt;
&lt;br /&gt;
Js dataTime format in ftl have been changed, now the format will return html encode string which will cause the parse exception, you should use StringUtil.wrapString to avoid this issue. For example, in earlier versions, you could have define a js dataTime format variable like this:&lt;br /&gt;
   &amp;lt;#assign dateFormat = Static[&amp;quot;org.opentaps.common.util.UtilDate&amp;quot;].getJsDateTimeFormat(Static[&amp;quot;org.opentaps.common.util.UtilDate&amp;quot;].getDateFormat(locale))/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In opentaps 1.4, you must do it this way:&lt;br /&gt;
	&amp;lt;#assign dateFormat = StringUtil.wrapString(Static[&amp;quot;org.opentaps.common.util.UtilDate&amp;quot;].getJsDateTimeFormat(Static[&amp;quot;org.opentaps.common.util.UtilDate&amp;quot;].getDateFormat(locale)))/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Spark</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=Opentaps_Hibernate_Integration&amp;diff=3836</id>
		<title>Opentaps Hibernate Integration</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=Opentaps_Hibernate_Integration&amp;diff=3836"/>
		<updated>2009-04-02T10:24:13Z</updated>

		<summary type="html">&lt;p&gt;Spark: /* How We Get the Hibernate Session */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Beginning with opentaps version 1.4, [http://www.hibernate.org Hibernate] will be available as a persistence tool alongside with the original ofbiz entity engine.  Hibernate is a more object oriented persistence framework and better suited for the new [[Domain Driven Architecture]], while the ofbiz entity engine will continue to be supported for legacy features from both ofbiz and opentaps.  In this document, we will review how the hibernate integration in opentaps works.&lt;br /&gt;
&lt;br /&gt;
== Working with Hibernate in opentaps ==&lt;br /&gt;
&lt;br /&gt;
=== Generating Hibernate Configuration Files ===&lt;br /&gt;
&lt;br /&gt;
After changing or defining new entities in your &amp;lt;tt&amp;gt;entitymodel.xml&amp;lt;/tt&amp;gt; files, you need to generate new Java classes for your entities with&lt;br /&gt;
 $ ant make-base-entities&lt;br /&gt;
&lt;br /&gt;
This command updates the Java classes defined in &amp;lt;tt&amp;gt;org.opentaps.domain.base.entities&amp;lt;/tt&amp;gt;, including their hibernate annotations, and the &amp;lt;tt&amp;gt;hibernate.cfg.xml&amp;lt;/tt&amp;gt; for integrating with hibernate.  (If you use a repository management system, you must commit both and you Java classes and the updated &amp;lt;tt&amp;gt;hibernate.cfg.xml&amp;lt;/tt&amp;gt; files.)&lt;br /&gt;
&lt;br /&gt;
=== Accessing Entities with Hibernate ===&lt;br /&gt;
&lt;br /&gt;
To use hibernate to access your entities, you will need an &amp;lt;tt&amp;gt;org.opentaps.foundation.entity.hibernate.Session&amp;lt;/tt&amp;gt;, which is an extension of the &amp;lt;tt&amp;gt;org.hibernate.Session&amp;lt;/tt&amp;gt; class.  You can obtain it from the Infrastructure class like this:&lt;br /&gt;
        session = infrastructure.getSession();&lt;br /&gt;
&lt;br /&gt;
Then, you can work with it as if it were a Hibernate &amp;lt;tt&amp;gt;Session&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
        Transaction tx = session.beginTransaction();&lt;br /&gt;
        TestEntity newTestEntity = new TestEntity();&lt;br /&gt;
        newTestEntity.setTestStringField(&amp;quot;testInsertTestEntity string field&amp;quot;);&lt;br /&gt;
        newTestEntity.setCreatedStamp(UtilDateTime.nowTimestamp());&lt;br /&gt;
        session.save(newTestEntity);&lt;br /&gt;
        tx.commit();&lt;br /&gt;
        session.flush();&lt;br /&gt;
        // ...&lt;br /&gt;
        TestEntity loadEntity = (TestEntity) session.load(TestEntity.class, newTestEntity.getTestId());&lt;br /&gt;
        // ...&lt;br /&gt;
        String hql = &amp;quot;from TestEntity eo where eo.testId='&amp;quot; + testEntityId2 + &amp;quot;'&amp;quot;;&lt;br /&gt;
        Query query = session.createQuery(hql);&lt;br /&gt;
        List&amp;lt;TestEntity&amp;gt; list = query.list()&lt;br /&gt;
 &lt;br /&gt;
You do not need to close your JDBC connection manually with the opentaps Session, however.  When you call&lt;br /&gt;
            session.close();&lt;br /&gt;
It will do it for you automatically.&lt;br /&gt;
&lt;br /&gt;
=== Traversing Related Entities ===&lt;br /&gt;
&lt;br /&gt;
opentaps will automatically create the relationship annotations, such as @OneToMany, @ManyToMany, and @Join, for your Java classes.&lt;br /&gt;
&lt;br /&gt;
To get related entities, use the hibernate query language (HQL):&lt;br /&gt;
    String hql = &amp;quot;from TestEntityItem eo where eo.testEntity.testId='&amp;quot; + testEntity.getTestId() + &amp;quot;'&amp;quot;&lt;br /&gt;
               + &amp;quot; and eo.testEntityItemSeqId in (&amp;quot; + testEntityItemSeqIds + &amp;quot;)&amp;quot;;&lt;br /&gt;
    Query query = session.createQuery(hql);&lt;br /&gt;
    List&amp;lt;TestEntityItem&amp;gt; list = query.list();&lt;br /&gt;
&lt;br /&gt;
Or use the getter methods in the base entities:&lt;br /&gt;
    List&amp;lt;TestEntityItem&amp;gt; list = testEntity.getTestEntityItems();&lt;br /&gt;
&lt;br /&gt;
Note that hibernate will automatically load related entities for you, so the getRelated  methods from Repository which were designed for the ofbiz entity engine are no longer needed when you work with hibernate.&lt;br /&gt;
&lt;br /&gt;
=== Working with View Entities ===&lt;br /&gt;
&lt;br /&gt;
Once a view entity has been defined in &amp;lt;tt&amp;gt;entitymodel.xml&amp;lt;/tt&amp;gt;, you can access it as any other Java object from hibernate, for example:&lt;br /&gt;
        Query query = session.createQuery(&amp;quot;from TestEntityAndItem eo where eo.testId='&amp;quot; &lt;br /&gt;
                    + testEntityId + &amp;quot;' order by eo.testEntityItemSeqId&amp;quot;);&lt;br /&gt;
        List&amp;lt;TestEntityAndItem&amp;gt; list = query.list();&lt;br /&gt;
        &lt;br /&gt;
The opentaps  Session, which extends the hibernate Session, will automatically create the SQL for accessing the view entity.&lt;br /&gt;
&lt;br /&gt;
=== Using Transactions ===&lt;br /&gt;
&lt;br /&gt;
You should use the transaction manager configured in the ofbiz entity engine through the &amp;lt;tt&amp;gt;[http://java.sun.com/j2ee/sdk_1.3/techdocs/api/javax/transaction/UserTransaction.html UserTransaction]&amp;lt;/tt&amp;gt;  class.  In the entity engine, the transaction manager is configured as:&lt;br /&gt;
  &amp;lt;transaction-factory class=&amp;quot;org.ofbiz.geronimo.GeronimoTransactionFactory&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is obtained from the ofbiz &amp;lt;tt&amp;gt;TransactionFactory&amp;lt;/tt&amp;gt; by our &amp;lt;tt&amp;gt;Session&amp;lt;/tt&amp;gt; and used the same way as a hibernate transaction:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     UserTransaction tx = session.beginUserTransaction();&lt;br /&gt;
     // do something useful&lt;br /&gt;
     tx.commit();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Auto Generating ID Values ===&lt;br /&gt;
&lt;br /&gt;
ofbiz keeps track of auto generated sequence IDs in an entity called &amp;lt;tt&amp;gt;SequenceValueItem&amp;lt;/tt&amp;gt;  To make sure that the auto generated sequence IDs from hibernate and the ofbiz entity engine work well together, we have created an &amp;lt;tt&amp;gt;OpentapsIdentifierGenerator&amp;lt;/tt&amp;gt; which also uses the same &amp;lt;tt&amp;gt;SequenceValueItem&amp;lt;/tt&amp;gt; to obtain the next sequential ID.  This ID generator is wired to the base entity POJO Java objects with hibernate annotations, like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 @org.hibernate.annotations.GenericGenerator(name=&amp;quot;Party_GEN&amp;quot;,  strategy=&amp;quot;org.opentaps.foundation.entity.hibernate.OpentapsIdentifierGenerator&amp;quot;)&lt;br /&gt;
 @GeneratedValue(generator=&amp;quot;Party_GEN&amp;quot;)   &lt;br /&gt;
 @Id&lt;br /&gt;
    &lt;br /&gt;
 @Column(name=&amp;quot;PARTY_ID&amp;quot;)&lt;br /&gt;
    &lt;br /&gt;
 private String partyId;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So that a &amp;lt;tt&amp;gt;partyId&amp;lt;/tt&amp;gt; field is automatically set for you.&lt;br /&gt;
&lt;br /&gt;
=== Support for OFBIZ EECA's ===&lt;br /&gt;
&lt;br /&gt;
ofbiz EECA's are supported with custom event listeners which are registered with hibernate when &amp;lt;tt&amp;gt;Infrastructure.getSessionFactory(String delegatorName)&amp;lt;/tt&amp;gt; is called, usually during the initial startup.  These event listeners will run ofbiz services defined in &amp;lt;tt&amp;gt;eeca.xml&amp;lt;/tt&amp;gt;'s  when hibernate is used to update the same entities.&lt;br /&gt;
&lt;br /&gt;
== Under the Hood: How It Works ==&lt;br /&gt;
&lt;br /&gt;
=== Base Class Annotations ===&lt;br /&gt;
&lt;br /&gt;
In opentaps version 1.4, the entity model XML from the ofbiz entity engine is still used as the base definition for all entities.  The opentaps POJO generator is used to create [[Base Entity Classes|base Java objects]] automatically from these entity definitions.  This POJO generator will also create the annotations which hibernate can then use to map those base objects to the database persistence layer.  The definitions of the annotations can be found in &amp;lt;tt&amp;gt;BaseEntity.ftl&amp;lt;/tt&amp;gt; file used by the POJO generator.&lt;br /&gt;
&lt;br /&gt;
=== How Hibernate Configuration Files are Generated ===&lt;br /&gt;
&lt;br /&gt;
The POJO Generator will use &amp;lt;tt&amp;gt;hot-deploy/opentaps-common/templates/HibernateCfg.ftl&amp;lt;/tt&amp;gt; to generate a base hibernate configuration file in &amp;lt;tt&amp;gt;hot-deploy/opentaps-common/config/hibernate.cfg.xml&amp;lt;/tt&amp;gt;  When opentaps is started, the following new container in &amp;lt;tt&amp;gt;framework/base/config/ofbiz-containers.xml&amp;lt;/tt&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    &amp;lt;container name=&amp;quot;hibernate-container&amp;quot; class=&amp;quot;org.opentaps.common.container.HibernateContainer&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;property name=&amp;quot;delegator-name&amp;quot; value=&amp;quot;default&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;/container&amp;gt;    &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will generate all the hibernate configuration XML files in the &amp;lt;tt&amp;gt;hot-deploy/opentaps/config/&amp;lt;/tt&amp;gt; directory for each data source in your entity engine XML file.  For example, it will generate a &amp;lt;tt&amp;gt;localmysql.cfg.xml&amp;lt;/tt&amp;gt;, a &amp;lt;tt&amp;gt;localpostgres.cfg.xml&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How We Get the Hibernate Session ===&lt;br /&gt;
&lt;br /&gt;
The opentaps &amp;lt;tt&amp;gt;Infrastructure&amp;lt;/tt&amp;gt; Class maintains a Map of delegatorName and hibernate SessionFactory objects.  Each SessionFactory is created for its corresponding delegatorName the first time it is requested from the &amp;lt;tt&amp;gt;Infrastructure.getSessionFactory(delegatorName)&amp;lt;/tt&amp;gt; method.  This SessionFactory is created from ofbiz entity engine configurations:&lt;br /&gt;
* The &amp;lt;tt&amp;gt;HibernateContainer&amp;lt;/tt&amp;gt; in &amp;lt;tt&amp;gt;ofbiz-containers.xml&amp;lt;/tt&amp;gt; has a property called &amp;lt;tt&amp;gt;delegator-name&amp;lt;/tt&amp;gt;&lt;br /&gt;
* From this delegator, we get the data source defined in &amp;lt;tt&amp;gt;entityengine.xml&amp;lt;/tt&amp;gt; for the default group helper name.  This is set to &amp;lt;tt&amp;gt;org.ofbiz&amp;lt;/tt&amp;gt; by default in the &amp;lt;tt&amp;gt;Infrastructure&amp;lt;/tt&amp;gt; class and is the &amp;lt;tt&amp;gt;group&amp;lt;/tt&amp;gt; attribute of the &amp;lt;tt&amp;gt;entitygroup.xml&amp;lt;/tt&amp;gt; definitions in ofbiz:&lt;br /&gt;
  &amp;lt;entity-group group=&amp;quot;org.ofbiz&amp;quot; entity=&amp;quot;AcctgTagEnumType&amp;quot;/&amp;gt;&lt;br /&gt;
In &amp;lt;tt&amp;gt;entityengine.xml&amp;lt;/tt&amp;gt;, you map a data source to each group:&lt;br /&gt;
    &amp;lt;delegator name=&amp;quot;default&amp;quot; entity-model-reader=&amp;quot;main&amp;quot; entity-group-reader=&amp;quot;main&amp;quot; entity-eca-reader=&amp;quot;main&amp;quot; distributed-cache-clear-enabled=&amp;quot;false&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;group-map group-name=&amp;quot;org.ofbiz&amp;quot; datasource-name=&amp;quot;localmysql&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;/delegator&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So, we are basically following the entity engine from the delegator to the data source via the group.&lt;br /&gt;
* Once we have the data source, we can create the SessionFactory from the hibernate.cfg.xml for that data source.  For example, if your data source is &amp;quot;localmysql&amp;quot;, we will create the SessionFactory from the &amp;lt;tt&amp;gt;localmysql.cfg.xml&amp;lt;/tt&amp;gt;   created by the &amp;lt;tt&amp;gt;HibernateContainer&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;HibernateContainer&amp;lt;/tt&amp;gt;, which loads on startup, will cause a SessionFactory to be loaded for the delegator in the &amp;lt;tt&amp;gt;delegator-name&amp;lt;/tt&amp;gt; attribute.  Once this SessionFactory is loaded, it will be available for future use.  Additional session factories can be obtained later by calling the &amp;lt;tt&amp;gt;getSessionFactory&amp;lt;/tt&amp;gt; directly.&lt;br /&gt;
&lt;br /&gt;
When the &amp;lt;tt&amp;gt;Infrastructure.getSession()&amp;lt;/tt&amp;gt; method is called,  it will use the delegator already in the Infrastructure object to open a JDBC connection first, and then use that JDBC connection and the SessionFactory for the delegator to return a Session.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;Infrastructure.getSession()&amp;lt;/tt&amp;gt; will return an &amp;lt;tt&amp;gt;org.opentaps.foundation.entity.hibernate.Session&amp;lt;/tt&amp;gt;, which extends the hibernate Session with the following differences:&lt;br /&gt;
* when the session is closed, the JDBC connection is also automatically closed&lt;br /&gt;
* when a Query is created, this Session will check if the query is on an entity engine view entity and construct the Query from native SQL first&lt;br /&gt;
&lt;br /&gt;
=== View Entities ===&lt;br /&gt;
&lt;br /&gt;
View entities are supported with @NamedNativeQuery annotations in the base entity Java classes, which are automatically generated by the opentaps POJO Generator.&lt;br /&gt;
&lt;br /&gt;
=== Unit Tests ===&lt;br /&gt;
&lt;br /&gt;
Unit tests for hibernate are found in &amp;lt;tt&amp;gt;org.opentaps.tests.entity.hibernate.HibernateTests&amp;lt;/tt&amp;gt; in the opentaps-tests component.&lt;/div&gt;</summary>
		<author><name>Spark</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=Opentaps_Hibernate_Integration&amp;diff=3835</id>
		<title>Opentaps Hibernate Integration</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=Opentaps_Hibernate_Integration&amp;diff=3835"/>
		<updated>2009-04-02T10:23:24Z</updated>

		<summary type="html">&lt;p&gt;Spark: /* Auto Generating ID Values */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Beginning with opentaps version 1.4, [http://www.hibernate.org Hibernate] will be available as a persistence tool alongside with the original ofbiz entity engine.  Hibernate is a more object oriented persistence framework and better suited for the new [[Domain Driven Architecture]], while the ofbiz entity engine will continue to be supported for legacy features from both ofbiz and opentaps.  In this document, we will review how the hibernate integration in opentaps works.&lt;br /&gt;
&lt;br /&gt;
== Working with Hibernate in opentaps ==&lt;br /&gt;
&lt;br /&gt;
=== Generating Hibernate Configuration Files ===&lt;br /&gt;
&lt;br /&gt;
After changing or defining new entities in your &amp;lt;tt&amp;gt;entitymodel.xml&amp;lt;/tt&amp;gt; files, you need to generate new Java classes for your entities with&lt;br /&gt;
 $ ant make-base-entities&lt;br /&gt;
&lt;br /&gt;
This command updates the Java classes defined in &amp;lt;tt&amp;gt;org.opentaps.domain.base.entities&amp;lt;/tt&amp;gt;, including their hibernate annotations, and the &amp;lt;tt&amp;gt;hibernate.cfg.xml&amp;lt;/tt&amp;gt; for integrating with hibernate.  (If you use a repository management system, you must commit both and you Java classes and the updated &amp;lt;tt&amp;gt;hibernate.cfg.xml&amp;lt;/tt&amp;gt; files.)&lt;br /&gt;
&lt;br /&gt;
=== Accessing Entities with Hibernate ===&lt;br /&gt;
&lt;br /&gt;
To use hibernate to access your entities, you will need an &amp;lt;tt&amp;gt;org.opentaps.foundation.entity.hibernate.Session&amp;lt;/tt&amp;gt;, which is an extension of the &amp;lt;tt&amp;gt;org.hibernate.Session&amp;lt;/tt&amp;gt; class.  You can obtain it from the Infrastructure class like this:&lt;br /&gt;
        session = infrastructure.getSession();&lt;br /&gt;
&lt;br /&gt;
Then, you can work with it as if it were a Hibernate &amp;lt;tt&amp;gt;Session&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
        Transaction tx = session.beginTransaction();&lt;br /&gt;
        TestEntity newTestEntity = new TestEntity();&lt;br /&gt;
        newTestEntity.setTestStringField(&amp;quot;testInsertTestEntity string field&amp;quot;);&lt;br /&gt;
        newTestEntity.setCreatedStamp(UtilDateTime.nowTimestamp());&lt;br /&gt;
        session.save(newTestEntity);&lt;br /&gt;
        tx.commit();&lt;br /&gt;
        session.flush();&lt;br /&gt;
        // ...&lt;br /&gt;
        TestEntity loadEntity = (TestEntity) session.load(TestEntity.class, newTestEntity.getTestId());&lt;br /&gt;
        // ...&lt;br /&gt;
        String hql = &amp;quot;from TestEntity eo where eo.testId='&amp;quot; + testEntityId2 + &amp;quot;'&amp;quot;;&lt;br /&gt;
        Query query = session.createQuery(hql);&lt;br /&gt;
        List&amp;lt;TestEntity&amp;gt; list = query.list()&lt;br /&gt;
 &lt;br /&gt;
You do not need to close your JDBC connection manually with the opentaps Session, however.  When you call&lt;br /&gt;
            session.close();&lt;br /&gt;
It will do it for you automatically.&lt;br /&gt;
&lt;br /&gt;
=== Traversing Related Entities ===&lt;br /&gt;
&lt;br /&gt;
opentaps will automatically create the relationship annotations, such as @OneToMany, @ManyToMany, and @Join, for your Java classes.&lt;br /&gt;
&lt;br /&gt;
To get related entities, use the hibernate query language (HQL):&lt;br /&gt;
    String hql = &amp;quot;from TestEntityItem eo where eo.testEntity.testId='&amp;quot; + testEntity.getTestId() + &amp;quot;'&amp;quot;&lt;br /&gt;
               + &amp;quot; and eo.testEntityItemSeqId in (&amp;quot; + testEntityItemSeqIds + &amp;quot;)&amp;quot;;&lt;br /&gt;
    Query query = session.createQuery(hql);&lt;br /&gt;
    List&amp;lt;TestEntityItem&amp;gt; list = query.list();&lt;br /&gt;
&lt;br /&gt;
Or use the getter methods in the base entities:&lt;br /&gt;
    List&amp;lt;TestEntityItem&amp;gt; list = testEntity.getTestEntityItems();&lt;br /&gt;
&lt;br /&gt;
Note that hibernate will automatically load related entities for you, so the getRelated  methods from Repository which were designed for the ofbiz entity engine are no longer needed when you work with hibernate.&lt;br /&gt;
&lt;br /&gt;
=== Working with View Entities ===&lt;br /&gt;
&lt;br /&gt;
Once a view entity has been defined in &amp;lt;tt&amp;gt;entitymodel.xml&amp;lt;/tt&amp;gt;, you can access it as any other Java object from hibernate, for example:&lt;br /&gt;
        Query query = session.createQuery(&amp;quot;from TestEntityAndItem eo where eo.testId='&amp;quot; &lt;br /&gt;
                    + testEntityId + &amp;quot;' order by eo.testEntityItemSeqId&amp;quot;);&lt;br /&gt;
        List&amp;lt;TestEntityAndItem&amp;gt; list = query.list();&lt;br /&gt;
        &lt;br /&gt;
The opentaps  Session, which extends the hibernate Session, will automatically create the SQL for accessing the view entity.&lt;br /&gt;
&lt;br /&gt;
=== Using Transactions ===&lt;br /&gt;
&lt;br /&gt;
You should use the transaction manager configured in the ofbiz entity engine through the &amp;lt;tt&amp;gt;[http://java.sun.com/j2ee/sdk_1.3/techdocs/api/javax/transaction/UserTransaction.html UserTransaction]&amp;lt;/tt&amp;gt;  class.  In the entity engine, the transaction manager is configured as:&lt;br /&gt;
  &amp;lt;transaction-factory class=&amp;quot;org.ofbiz.geronimo.GeronimoTransactionFactory&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is obtained from the ofbiz &amp;lt;tt&amp;gt;TransactionFactory&amp;lt;/tt&amp;gt; by our &amp;lt;tt&amp;gt;Session&amp;lt;/tt&amp;gt; and used the same way as a hibernate transaction:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     UserTransaction tx = session.beginUserTransaction();&lt;br /&gt;
     // do something useful&lt;br /&gt;
     tx.commit();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Auto Generating ID Values ===&lt;br /&gt;
&lt;br /&gt;
ofbiz keeps track of auto generated sequence IDs in an entity called &amp;lt;tt&amp;gt;SequenceValueItem&amp;lt;/tt&amp;gt;  To make sure that the auto generated sequence IDs from hibernate and the ofbiz entity engine work well together, we have created an &amp;lt;tt&amp;gt;OpentapsIdentifierGenerator&amp;lt;/tt&amp;gt; which also uses the same &amp;lt;tt&amp;gt;SequenceValueItem&amp;lt;/tt&amp;gt; to obtain the next sequential ID.  This ID generator is wired to the base entity POJO Java objects with hibernate annotations, like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 @org.hibernate.annotations.GenericGenerator(name=&amp;quot;Party_GEN&amp;quot;,  strategy=&amp;quot;org.opentaps.foundation.entity.hibernate.OpentapsIdentifierGenerator&amp;quot;)&lt;br /&gt;
 @GeneratedValue(generator=&amp;quot;Party_GEN&amp;quot;)   &lt;br /&gt;
 @Id&lt;br /&gt;
    &lt;br /&gt;
 @Column(name=&amp;quot;PARTY_ID&amp;quot;)&lt;br /&gt;
    &lt;br /&gt;
 private String partyId;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So that a &amp;lt;tt&amp;gt;partyId&amp;lt;/tt&amp;gt; field is automatically set for you.&lt;br /&gt;
&lt;br /&gt;
=== Support for OFBIZ EECA's ===&lt;br /&gt;
&lt;br /&gt;
ofbiz EECA's are supported with custom event listeners which are registered with hibernate when &amp;lt;tt&amp;gt;Infrastructure.getSessionFactory(String delegatorName)&amp;lt;/tt&amp;gt; is called, usually during the initial startup.  These event listeners will run ofbiz services defined in &amp;lt;tt&amp;gt;eeca.xml&amp;lt;/tt&amp;gt;'s  when hibernate is used to update the same entities.&lt;br /&gt;
&lt;br /&gt;
== Under the Hood: How It Works ==&lt;br /&gt;
&lt;br /&gt;
=== Base Class Annotations ===&lt;br /&gt;
&lt;br /&gt;
In opentaps version 1.4, the entity model XML from the ofbiz entity engine is still used as the base definition for all entities.  The opentaps POJO generator is used to create [[Base Entity Classes|base Java objects]] automatically from these entity definitions.  This POJO generator will also create the annotations which hibernate can then use to map those base objects to the database persistence layer.  The definitions of the annotations can be found in &amp;lt;tt&amp;gt;BaseEntity.ftl&amp;lt;/tt&amp;gt; file used by the POJO generator.&lt;br /&gt;
&lt;br /&gt;
=== How Hibernate Configuration Files are Generated ===&lt;br /&gt;
&lt;br /&gt;
The POJO Generator will use &amp;lt;tt&amp;gt;hot-deploy/opentaps-common/templates/HibernateCfg.ftl&amp;lt;/tt&amp;gt; to generate a base hibernate configuration file in &amp;lt;tt&amp;gt;hot-deploy/opentaps-common/config/hibernate.cfg.xml&amp;lt;/tt&amp;gt;  When opentaps is started, the following new container in &amp;lt;tt&amp;gt;framework/base/config/ofbiz-containers.xml&amp;lt;/tt&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    &amp;lt;container name=&amp;quot;hibernate-container&amp;quot; class=&amp;quot;org.opentaps.common.container.HibernateContainer&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;property name=&amp;quot;delegator-name&amp;quot; value=&amp;quot;default&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;/container&amp;gt;    &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will generate all the hibernate configuration XML files in the &amp;lt;tt&amp;gt;hot-deploy/opentaps/config/&amp;lt;/tt&amp;gt; directory for each data source in your entity engine XML file.  For example, it will generate a &amp;lt;tt&amp;gt;localmysql.cfg.xml&amp;lt;/tt&amp;gt;, a &amp;lt;tt&amp;gt;localpostgres.cfg.xml&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How We Get the Hibernate Session ===&lt;br /&gt;
&lt;br /&gt;
The opentaps &amp;lt;tt&amp;gt;Infrastructure&amp;lt;/tt&amp;gt; Class maintains a Map of delegatorName and hibernate SessionFactory objects.  Each SessionFactory is created for its corresponding delegatorName the first time it is requested from the &amp;lt;tt&amp;gt;Infrastructure.getSessionFactory(delegatorName)&amp;lt;/tt&amp;gt; method.  This SessionFactory is created from ofbiz entity engine configurations:&lt;br /&gt;
* The &amp;lt;tt&amp;gt;HibernateContainer&amp;lt;/tt&amp;gt; in &amp;lt;tt&amp;gt;ofbiz-containers.xml&amp;lt;/tt&amp;gt; has a property called &amp;lt;tt&amp;gt;delegator-name&amp;lt;/tt&amp;gt;&lt;br /&gt;
* From this delegator, we get the data source defined in &amp;lt;tt&amp;gt;entityengine.xml&amp;lt;/tt&amp;gt; for the default group helper name.  This is set to &amp;lt;tt&amp;gt;org.ofbiz&amp;lt;/tt&amp;gt; by default in the &amp;lt;tt&amp;gt;Infrastructure&amp;lt;/tt&amp;gt; class and is the &amp;lt;tt&amp;gt;group&amp;lt;/tt&amp;gt; attribute of the &amp;lt;tt&amp;gt;entitygroup.xml&amp;lt;/tt&amp;gt; definitions in ofbiz:&lt;br /&gt;
  &amp;lt;entity-group group=&amp;quot;org.ofbiz&amp;quot; entity=&amp;quot;AcctgTagEnumType&amp;quot;/&amp;gt;&lt;br /&gt;
In &amp;lt;tt&amp;gt;entityengine.xml&amp;lt;/tt&amp;gt;, you map a data source to each group:&lt;br /&gt;
    &amp;lt;delegator name=&amp;quot;default&amp;quot; entity-model-reader=&amp;quot;main&amp;quot; entity-group-reader=&amp;quot;main&amp;quot; entity-eca-reader=&amp;quot;main&amp;quot; distributed-cache-clear-enabled=&amp;quot;false&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;group-map group-name=&amp;quot;org.ofbiz&amp;quot; datasource-name=&amp;quot;localmysql&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;/delegator&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So, we are basically following the entity engine from the delegator to the data source via the group.&lt;br /&gt;
* Once we have the data source, we can create the SessionFactory from the hibernate.cfg.xml for that data source.  For example, if your data source is &amp;quot;localmysql&amp;quot;, we will create the SessionFactory from the &amp;lt;tt&amp;gt;localmysql.cfg.xml&amp;lt;/tt&amp;gt;   created by the &amp;lt;tt&amp;gt;HibernateContainer&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;HibernateContainer&amp;lt;/tt&amp;gt;, which loads on startup, will cause a SessionFactory to be loaded for the delegator in the &amp;lt;tt&amp;gt;delegator-name&amp;lt;/tt&amp;gt; attribute.  Once this SessionFactory is loaded, it will be available for future use.  Additional session factories can be obtained later by calling the &amp;lt;tt&amp;gt;getSessionFactory&amp;lt;/tt&amp;gt; directly.&lt;br /&gt;
&lt;br /&gt;
When the &amp;lt;tt&amp;gt;Infrastructure.getSession()&amp;lt;/tt&amp;gt; method is called,  it will use the delegator already in the Infrastructure object to open a JDBC connection first, and then use that JDBC connection and the SessionFactory for the delegator to return a Session.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;Infrastructure.getSession()&amp;lt;/tt&amp;gt; will return an &amp;lt;tt&amp;gt;org.opentaps.foundation.infrastructure.Session&amp;lt;/tt&amp;gt;, which extends the hibernate Session with the following differences:&lt;br /&gt;
* when the session is closed, the JDBC connection is also automatically closed&lt;br /&gt;
* when a Query is created, this Session will check if the query is on an entity engine view entity and construct the Query from native SQL first&lt;br /&gt;
&lt;br /&gt;
=== View Entities ===&lt;br /&gt;
&lt;br /&gt;
View entities are supported with @NamedNativeQuery annotations in the base entity Java classes, which are automatically generated by the opentaps POJO Generator.&lt;br /&gt;
&lt;br /&gt;
=== Unit Tests ===&lt;br /&gt;
&lt;br /&gt;
Unit tests for hibernate are found in &amp;lt;tt&amp;gt;org.opentaps.tests.entity.hibernate.HibernateTests&amp;lt;/tt&amp;gt; in the opentaps-tests component.&lt;/div&gt;</summary>
		<author><name>Spark</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=Opentaps_Hibernate_Integration&amp;diff=3834</id>
		<title>Opentaps Hibernate Integration</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=Opentaps_Hibernate_Integration&amp;diff=3834"/>
		<updated>2009-04-02T10:22:56Z</updated>

		<summary type="html">&lt;p&gt;Spark: /* Accessing Entities with Hibernate */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Beginning with opentaps version 1.4, [http://www.hibernate.org Hibernate] will be available as a persistence tool alongside with the original ofbiz entity engine.  Hibernate is a more object oriented persistence framework and better suited for the new [[Domain Driven Architecture]], while the ofbiz entity engine will continue to be supported for legacy features from both ofbiz and opentaps.  In this document, we will review how the hibernate integration in opentaps works.&lt;br /&gt;
&lt;br /&gt;
== Working with Hibernate in opentaps ==&lt;br /&gt;
&lt;br /&gt;
=== Generating Hibernate Configuration Files ===&lt;br /&gt;
&lt;br /&gt;
After changing or defining new entities in your &amp;lt;tt&amp;gt;entitymodel.xml&amp;lt;/tt&amp;gt; files, you need to generate new Java classes for your entities with&lt;br /&gt;
 $ ant make-base-entities&lt;br /&gt;
&lt;br /&gt;
This command updates the Java classes defined in &amp;lt;tt&amp;gt;org.opentaps.domain.base.entities&amp;lt;/tt&amp;gt;, including their hibernate annotations, and the &amp;lt;tt&amp;gt;hibernate.cfg.xml&amp;lt;/tt&amp;gt; for integrating with hibernate.  (If you use a repository management system, you must commit both and you Java classes and the updated &amp;lt;tt&amp;gt;hibernate.cfg.xml&amp;lt;/tt&amp;gt; files.)&lt;br /&gt;
&lt;br /&gt;
=== Accessing Entities with Hibernate ===&lt;br /&gt;
&lt;br /&gt;
To use hibernate to access your entities, you will need an &amp;lt;tt&amp;gt;org.opentaps.foundation.entity.hibernate.Session&amp;lt;/tt&amp;gt;, which is an extension of the &amp;lt;tt&amp;gt;org.hibernate.Session&amp;lt;/tt&amp;gt; class.  You can obtain it from the Infrastructure class like this:&lt;br /&gt;
        session = infrastructure.getSession();&lt;br /&gt;
&lt;br /&gt;
Then, you can work with it as if it were a Hibernate &amp;lt;tt&amp;gt;Session&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
        Transaction tx = session.beginTransaction();&lt;br /&gt;
        TestEntity newTestEntity = new TestEntity();&lt;br /&gt;
        newTestEntity.setTestStringField(&amp;quot;testInsertTestEntity string field&amp;quot;);&lt;br /&gt;
        newTestEntity.setCreatedStamp(UtilDateTime.nowTimestamp());&lt;br /&gt;
        session.save(newTestEntity);&lt;br /&gt;
        tx.commit();&lt;br /&gt;
        session.flush();&lt;br /&gt;
        // ...&lt;br /&gt;
        TestEntity loadEntity = (TestEntity) session.load(TestEntity.class, newTestEntity.getTestId());&lt;br /&gt;
        // ...&lt;br /&gt;
        String hql = &amp;quot;from TestEntity eo where eo.testId='&amp;quot; + testEntityId2 + &amp;quot;'&amp;quot;;&lt;br /&gt;
        Query query = session.createQuery(hql);&lt;br /&gt;
        List&amp;lt;TestEntity&amp;gt; list = query.list()&lt;br /&gt;
 &lt;br /&gt;
You do not need to close your JDBC connection manually with the opentaps Session, however.  When you call&lt;br /&gt;
            session.close();&lt;br /&gt;
It will do it for you automatically.&lt;br /&gt;
&lt;br /&gt;
=== Traversing Related Entities ===&lt;br /&gt;
&lt;br /&gt;
opentaps will automatically create the relationship annotations, such as @OneToMany, @ManyToMany, and @Join, for your Java classes.&lt;br /&gt;
&lt;br /&gt;
To get related entities, use the hibernate query language (HQL):&lt;br /&gt;
    String hql = &amp;quot;from TestEntityItem eo where eo.testEntity.testId='&amp;quot; + testEntity.getTestId() + &amp;quot;'&amp;quot;&lt;br /&gt;
               + &amp;quot; and eo.testEntityItemSeqId in (&amp;quot; + testEntityItemSeqIds + &amp;quot;)&amp;quot;;&lt;br /&gt;
    Query query = session.createQuery(hql);&lt;br /&gt;
    List&amp;lt;TestEntityItem&amp;gt; list = query.list();&lt;br /&gt;
&lt;br /&gt;
Or use the getter methods in the base entities:&lt;br /&gt;
    List&amp;lt;TestEntityItem&amp;gt; list = testEntity.getTestEntityItems();&lt;br /&gt;
&lt;br /&gt;
Note that hibernate will automatically load related entities for you, so the getRelated  methods from Repository which were designed for the ofbiz entity engine are no longer needed when you work with hibernate.&lt;br /&gt;
&lt;br /&gt;
=== Working with View Entities ===&lt;br /&gt;
&lt;br /&gt;
Once a view entity has been defined in &amp;lt;tt&amp;gt;entitymodel.xml&amp;lt;/tt&amp;gt;, you can access it as any other Java object from hibernate, for example:&lt;br /&gt;
        Query query = session.createQuery(&amp;quot;from TestEntityAndItem eo where eo.testId='&amp;quot; &lt;br /&gt;
                    + testEntityId + &amp;quot;' order by eo.testEntityItemSeqId&amp;quot;);&lt;br /&gt;
        List&amp;lt;TestEntityAndItem&amp;gt; list = query.list();&lt;br /&gt;
        &lt;br /&gt;
The opentaps  Session, which extends the hibernate Session, will automatically create the SQL for accessing the view entity.&lt;br /&gt;
&lt;br /&gt;
=== Using Transactions ===&lt;br /&gt;
&lt;br /&gt;
You should use the transaction manager configured in the ofbiz entity engine through the &amp;lt;tt&amp;gt;[http://java.sun.com/j2ee/sdk_1.3/techdocs/api/javax/transaction/UserTransaction.html UserTransaction]&amp;lt;/tt&amp;gt;  class.  In the entity engine, the transaction manager is configured as:&lt;br /&gt;
  &amp;lt;transaction-factory class=&amp;quot;org.ofbiz.geronimo.GeronimoTransactionFactory&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is obtained from the ofbiz &amp;lt;tt&amp;gt;TransactionFactory&amp;lt;/tt&amp;gt; by our &amp;lt;tt&amp;gt;Session&amp;lt;/tt&amp;gt; and used the same way as a hibernate transaction:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     UserTransaction tx = session.beginUserTransaction();&lt;br /&gt;
     // do something useful&lt;br /&gt;
     tx.commit();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Auto Generating ID Values ===&lt;br /&gt;
&lt;br /&gt;
ofbiz keeps track of auto generated sequence IDs in an entity called &amp;lt;tt&amp;gt;SequenceValueItem&amp;lt;/tt&amp;gt;  To make sure that the auto generated sequence IDs from hibernate and the ofbiz entity engine work well together, we have created an &amp;lt;tt&amp;gt;OpentapsIdentifierGenerator&amp;lt;/tt&amp;gt; which also uses the same &amp;lt;tt&amp;gt;SequenceValueItem&amp;lt;/tt&amp;gt; to obtain the next sequential ID.  This ID generator is wired to the base entity POJO Java objects with hibernate annotations, like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 @org.hibernate.annotations.GenericGenerator(name=&amp;quot;Party_GEN&amp;quot;,  strategy=&amp;quot;org.opentaps.foundation.infrastructure.OpentapsIdentifierGenerator&amp;quot;)&lt;br /&gt;
 @GeneratedValue(generator=&amp;quot;Party_GEN&amp;quot;)   &lt;br /&gt;
 @Id&lt;br /&gt;
    &lt;br /&gt;
 @Column(name=&amp;quot;PARTY_ID&amp;quot;)&lt;br /&gt;
    &lt;br /&gt;
 private String partyId;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So that a &amp;lt;tt&amp;gt;partyId&amp;lt;/tt&amp;gt; field is automatically set for you.&lt;br /&gt;
&lt;br /&gt;
=== Support for OFBIZ EECA's ===&lt;br /&gt;
&lt;br /&gt;
ofbiz EECA's are supported with custom event listeners which are registered with hibernate when &amp;lt;tt&amp;gt;Infrastructure.getSessionFactory(String delegatorName)&amp;lt;/tt&amp;gt; is called, usually during the initial startup.  These event listeners will run ofbiz services defined in &amp;lt;tt&amp;gt;eeca.xml&amp;lt;/tt&amp;gt;'s  when hibernate is used to update the same entities.&lt;br /&gt;
&lt;br /&gt;
== Under the Hood: How It Works ==&lt;br /&gt;
&lt;br /&gt;
=== Base Class Annotations ===&lt;br /&gt;
&lt;br /&gt;
In opentaps version 1.4, the entity model XML from the ofbiz entity engine is still used as the base definition for all entities.  The opentaps POJO generator is used to create [[Base Entity Classes|base Java objects]] automatically from these entity definitions.  This POJO generator will also create the annotations which hibernate can then use to map those base objects to the database persistence layer.  The definitions of the annotations can be found in &amp;lt;tt&amp;gt;BaseEntity.ftl&amp;lt;/tt&amp;gt; file used by the POJO generator.&lt;br /&gt;
&lt;br /&gt;
=== How Hibernate Configuration Files are Generated ===&lt;br /&gt;
&lt;br /&gt;
The POJO Generator will use &amp;lt;tt&amp;gt;hot-deploy/opentaps-common/templates/HibernateCfg.ftl&amp;lt;/tt&amp;gt; to generate a base hibernate configuration file in &amp;lt;tt&amp;gt;hot-deploy/opentaps-common/config/hibernate.cfg.xml&amp;lt;/tt&amp;gt;  When opentaps is started, the following new container in &amp;lt;tt&amp;gt;framework/base/config/ofbiz-containers.xml&amp;lt;/tt&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    &amp;lt;container name=&amp;quot;hibernate-container&amp;quot; class=&amp;quot;org.opentaps.common.container.HibernateContainer&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;property name=&amp;quot;delegator-name&amp;quot; value=&amp;quot;default&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;/container&amp;gt;    &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will generate all the hibernate configuration XML files in the &amp;lt;tt&amp;gt;hot-deploy/opentaps/config/&amp;lt;/tt&amp;gt; directory for each data source in your entity engine XML file.  For example, it will generate a &amp;lt;tt&amp;gt;localmysql.cfg.xml&amp;lt;/tt&amp;gt;, a &amp;lt;tt&amp;gt;localpostgres.cfg.xml&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How We Get the Hibernate Session ===&lt;br /&gt;
&lt;br /&gt;
The opentaps &amp;lt;tt&amp;gt;Infrastructure&amp;lt;/tt&amp;gt; Class maintains a Map of delegatorName and hibernate SessionFactory objects.  Each SessionFactory is created for its corresponding delegatorName the first time it is requested from the &amp;lt;tt&amp;gt;Infrastructure.getSessionFactory(delegatorName)&amp;lt;/tt&amp;gt; method.  This SessionFactory is created from ofbiz entity engine configurations:&lt;br /&gt;
* The &amp;lt;tt&amp;gt;HibernateContainer&amp;lt;/tt&amp;gt; in &amp;lt;tt&amp;gt;ofbiz-containers.xml&amp;lt;/tt&amp;gt; has a property called &amp;lt;tt&amp;gt;delegator-name&amp;lt;/tt&amp;gt;&lt;br /&gt;
* From this delegator, we get the data source defined in &amp;lt;tt&amp;gt;entityengine.xml&amp;lt;/tt&amp;gt; for the default group helper name.  This is set to &amp;lt;tt&amp;gt;org.ofbiz&amp;lt;/tt&amp;gt; by default in the &amp;lt;tt&amp;gt;Infrastructure&amp;lt;/tt&amp;gt; class and is the &amp;lt;tt&amp;gt;group&amp;lt;/tt&amp;gt; attribute of the &amp;lt;tt&amp;gt;entitygroup.xml&amp;lt;/tt&amp;gt; definitions in ofbiz:&lt;br /&gt;
  &amp;lt;entity-group group=&amp;quot;org.ofbiz&amp;quot; entity=&amp;quot;AcctgTagEnumType&amp;quot;/&amp;gt;&lt;br /&gt;
In &amp;lt;tt&amp;gt;entityengine.xml&amp;lt;/tt&amp;gt;, you map a data source to each group:&lt;br /&gt;
    &amp;lt;delegator name=&amp;quot;default&amp;quot; entity-model-reader=&amp;quot;main&amp;quot; entity-group-reader=&amp;quot;main&amp;quot; entity-eca-reader=&amp;quot;main&amp;quot; distributed-cache-clear-enabled=&amp;quot;false&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;group-map group-name=&amp;quot;org.ofbiz&amp;quot; datasource-name=&amp;quot;localmysql&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;/delegator&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So, we are basically following the entity engine from the delegator to the data source via the group.&lt;br /&gt;
* Once we have the data source, we can create the SessionFactory from the hibernate.cfg.xml for that data source.  For example, if your data source is &amp;quot;localmysql&amp;quot;, we will create the SessionFactory from the &amp;lt;tt&amp;gt;localmysql.cfg.xml&amp;lt;/tt&amp;gt;   created by the &amp;lt;tt&amp;gt;HibernateContainer&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;HibernateContainer&amp;lt;/tt&amp;gt;, which loads on startup, will cause a SessionFactory to be loaded for the delegator in the &amp;lt;tt&amp;gt;delegator-name&amp;lt;/tt&amp;gt; attribute.  Once this SessionFactory is loaded, it will be available for future use.  Additional session factories can be obtained later by calling the &amp;lt;tt&amp;gt;getSessionFactory&amp;lt;/tt&amp;gt; directly.&lt;br /&gt;
&lt;br /&gt;
When the &amp;lt;tt&amp;gt;Infrastructure.getSession()&amp;lt;/tt&amp;gt; method is called,  it will use the delegator already in the Infrastructure object to open a JDBC connection first, and then use that JDBC connection and the SessionFactory for the delegator to return a Session.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;Infrastructure.getSession()&amp;lt;/tt&amp;gt; will return an &amp;lt;tt&amp;gt;org.opentaps.foundation.infrastructure.Session&amp;lt;/tt&amp;gt;, which extends the hibernate Session with the following differences:&lt;br /&gt;
* when the session is closed, the JDBC connection is also automatically closed&lt;br /&gt;
* when a Query is created, this Session will check if the query is on an entity engine view entity and construct the Query from native SQL first&lt;br /&gt;
&lt;br /&gt;
=== View Entities ===&lt;br /&gt;
&lt;br /&gt;
View entities are supported with @NamedNativeQuery annotations in the base entity Java classes, which are automatically generated by the opentaps POJO Generator.&lt;br /&gt;
&lt;br /&gt;
=== Unit Tests ===&lt;br /&gt;
&lt;br /&gt;
Unit tests for hibernate are found in &amp;lt;tt&amp;gt;org.opentaps.tests.entity.hibernate.HibernateTests&amp;lt;/tt&amp;gt; in the opentaps-tests component.&lt;/div&gt;</summary>
		<author><name>Spark</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=Unit_Testing&amp;diff=3793</id>
		<title>Unit Testing</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=Unit_Testing&amp;diff=3793"/>
		<updated>2009-03-19T10:14:50Z</updated>

		<summary type="html">&lt;p&gt;Spark: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==How to Write Unit Tests==&lt;br /&gt;
===opentaps 1.0===&lt;br /&gt;
For opentaps 1.0, you would write a set of Junit tests in a class, then define it in an XML testdef file like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;test-suite suite-name=&amp;quot;entitytests&amp;quot;&lt;br /&gt;
        xmlns:xsi=&amp;quot;http://www.w3.org/2001/XMLSchema-instance&amp;quot; &lt;br /&gt;
        xsi:noNamespaceSchemaLocation=&amp;quot;http://www.ofbiz.org/dtds/test-suite.xsd&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;test-case case-name=&amp;quot;security-tests&amp;quot;&amp;gt;&amp;lt;junit-test-suite class-name=&amp;quot;com.opensourcestrategies.crmsfa.test.SecurityTests&amp;quot;/&amp;gt;&amp;lt;/test-case&amp;gt;&lt;br /&gt;
&amp;lt;/test-suite&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
You can define multiple tests per testdef xml file.  Then, add the testdef file to your ofbiz-component.xml, like this:&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;test-suite loader=&amp;quot;main&amp;quot; location=&amp;quot;testdef/crmsfa_tests.xml&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, when you do&lt;br /&gt;
   $ ant run-tests&lt;br /&gt;
your tests will be run.&lt;br /&gt;
===opentaps 0.9===&lt;br /&gt;
In opentaps 0.9, you would write your Junit tests class and add your it to the base/config/test-containers.xml file, in the &amp;quot;junit-container&amp;quot; at the bottom, like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    &amp;lt;container name=&amp;quot;junit-container&amp;quot; class=&amp;quot;org.ofbiz.base.container.JunitContainer&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;property name=&amp;quot;base-test&amp;quot; value=&amp;quot;org.ofbiz.base.test.BaseUnitTests&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;property name=&amp;quot;entity-test&amp;quot; value=&amp;quot;org.ofbiz.entity.test.EntityTestSuite&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;property name=&amp;quot;service-test&amp;quot; value=&amp;quot;org.ofbiz.service.test.ServiceEngineTests&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;property name=&amp;quot;crm-security&amp;quot; value=&amp;quot;com.opensourcestrategies.crmsfa.test.SecurityTests&amp;quot;/&amp;gt;  &amp;lt;!-- your unit tests --&amp;gt;&lt;br /&gt;
        &amp;lt;!--&lt;br /&gt;
        &amp;lt;property name=&amp;quot;usps-test&amp;quot; value=&amp;quot;org.ofbiz.shipment.thirdparty.usps.UspsServicesTests&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;property name=&amp;quot;jxunit-test&amp;quot; value=&amp;quot;net.sourceforge.jxunit.JXTestCase&amp;quot;/&amp;gt;&lt;br /&gt;
        --&amp;gt;&lt;br /&gt;
    &amp;lt;/container&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Then you would do&lt;br /&gt;
  $ ant run-tests&lt;br /&gt;
&lt;br /&gt;
Your tests will run alongside the existing OFBIZ test suites.&lt;br /&gt;
&lt;br /&gt;
'''IMPORTANT''': &lt;br /&gt;
* Use a &amp;quot;test&amp;quot; delegator to point your tests to a separate database, and make sure it is defined in framework/entity/config/entityengine.xml is set to the right database.&lt;br /&gt;
* The opentaps tests are commented out in hot-deploy/component-load.xml by default so don't forget to activate them.&lt;br /&gt;
&lt;br /&gt;
==Where are the Unit Tests?==&lt;br /&gt;
&lt;br /&gt;
All opentaps unit tests are located in hot-deploy/opentaps-tests&lt;br /&gt;
&lt;br /&gt;
There are also a small number of unit tests from ofbiz in their respective modules, such as framework/entity for the entity engine unit tests.&lt;br /&gt;
&lt;br /&gt;
==Setting Up For Unit Testing==&lt;br /&gt;
&lt;br /&gt;
We recommend that you create a separate database on the same database server for testing purposes and install all demo data into the testing database.  Let's say that this database is called &amp;quot;opentaps_testing&amp;quot;.  Then, edit the file framework/entity/config/entityengine.xml and define opentaps_testing as a new datasource, called &amp;quot;localmysltesting&amp;quot; or &amp;quot;localpostgrestesting&amp;quot;.  Next, initiate the demo data into the testing database by editing the default delegator:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   &amp;lt;delegator name=&amp;quot;default&amp;quot; entity-model-reader=&amp;quot;main&amp;quot; entity-group-reader=&amp;quot;main&amp;quot; entity-eca-reader=&amp;quot;main&amp;quot; distributed-cache-clear-enabled=&amp;quot;false&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;group-map group-name=&amp;quot;org.ofbiz&amp;quot; datasource-name=&amp;quot;localXXXtesting&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;/delegator&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then do an&lt;br /&gt;
&lt;br /&gt;
   $ ant run-install&lt;br /&gt;
&lt;br /&gt;
to install all the seed and demo data into the testing database.  Then you can edit the default delegator back to your original delegator, and set the '''test''' delegator to the testing database:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;delegator name=&amp;quot;test&amp;quot; entity-model-reader=&amp;quot;main&amp;quot; entity-group-reader=&amp;quot;main&amp;quot; entity-eca-reader=&amp;quot;main&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;group-map group-name=&amp;quot;org.ofbiz&amp;quot; datasource-name=&amp;quot;localXXXtesting&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;/delegator&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All unit tests should be run to use the test delegator.  This can be done by instantiating the the &amp;quot;test&amp;quot; delegator by name and using that delegator to instantiate a dispatcher.  Or you can just write a test suite which extends the OpentapsTests base class, which does it for you.&lt;br /&gt;
&lt;br /&gt;
If you need to modify port settings for the testing instance, you should edit the file framework/base/config/test-containers.xml.&lt;br /&gt;
&lt;br /&gt;
==Unit Testing Strategies==&lt;br /&gt;
&lt;br /&gt;
These are some strategies for unit testing:&lt;br /&gt;
&lt;br /&gt;
* Transaction comparison - Compare the transaction produced with a sample transaction, possibly pre-loaded into the system.  For example, posting a paycheck to the ledger and then comparing with test data of a correct ledger transaction to make sure that they are equivalent.  Equivalence is a very important concept: it is not possible that two sets of transactions are identical, since at a minimum they would have different ID numbers, and they would probably reference other transactions with different IDs.  For example, each order would have a different orderId and different inventory item Ids reserved against it.  However, two orders may be considered equivalent if they have the same set of items, prices, shipping methods, customer, addresses, tax and promotional amounts, etc.&lt;br /&gt;
* State change - Compare the state of the system before and after a transaction has occurred.  For example, check the inventry of an item, then ship an order, and check the resulting inventory to make sure that it is correctly decremented.  This could get very complex: Shipping an order could cause customer balances, invoices, ledger postings, and inventory changes.  Multiple tests could be run off the same transaction event.&lt;br /&gt;
* Absolute state check - At all times, certain relationships must hold.  For example, the sum of all debits must equal sum of all credits.&lt;br /&gt;
&lt;br /&gt;
Tests should be written against the services that create the original data.  For example, if you are writing tests against CRMSFA activity, you can use users from the demo data set, but you should use the CRMSFA activity services to create or update your activities.  Otherwise, if you create those activities with some other method, future changes to the services to create activities will not be covered by your unit tests.&lt;br /&gt;
&lt;br /&gt;
Tests should be run against a dedicated testing database with demo and seed data rather than production data.  Therefore, the tests generally should set up their own initial conditions and run to completion, but they do not need to &amp;quot;tear down&amp;quot; and remove all data created by the tests.  (This would be very impractical: imagine creating and shipping an order.  To tear it down would involve reverting order data, customer information, inventory data, shipment data, invoices and payments, and accounting entries.)  A good test for the tests is that if you ran the test suite in succession multiple times, they should pass during the second and third runs as well as the first run.&lt;br /&gt;
&lt;br /&gt;
==A Unit Testing Tutorial==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
IMPORTANT: Each unit test method must start with the word &amp;quot;test&amp;quot; -- it must be called testXXX(), not tryXXX() or verifyXXX().&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now let's walk through a particular unit test and see how it works.  The one that we're looking at is the ProductionRunTests.java's testProductionRunTransactions method.  This particular test verifies that a standard manufacturing process is working correctly and checks the inventory results and financial statements.  As you read through the code, you will notice that it does the following&lt;br /&gt;
&lt;br /&gt;
# Sets up by first receiving the raw materials (MAT_A_COST and MAT_B_COST) into inventory&lt;br /&gt;
# Checks the initial state by getting the GL account balances and the initial inventory quantities, both ATP and QOH&lt;br /&gt;
# Runs through the production run&lt;br /&gt;
# Checks the final state by getting the GL account balances and the inventory quantities for raw materials and the finished product. &lt;br /&gt;
# Verify the following:&lt;br /&gt;
## The change in inventory quantities is correct: raw materials are used, so their quantities are reduced, and finished product's quantity is increased because it is produced.&lt;br /&gt;
## The change in GL account balances are correct: inventory value increases and are offset by raw materials and manufacturing expenses.&lt;br /&gt;
## The financial statements are in balance at all times.&lt;br /&gt;
## The financial transactions created by this production run is in agreement with the reference transactions MFGTEST-1, -2, -3.  This is done by finding all new financial transactions after the production run has been begun, as they should only be generated by the production run.&lt;br /&gt;
## The unit value of the finished product is correct.&lt;br /&gt;
&lt;br /&gt;
Along the way, the tests will verify that all the services are run correctly and return success as well.&lt;br /&gt;
&lt;br /&gt;
The test case uses the classes InventoryAsserts and FinancialAsserts to obtain information and run tests on the inventory balances and financial statement values.  This is a common &amp;quot;delegation&amp;quot; pattern to separate the code for testing assertions to new classes.  It also uses methods such as assertMapDifferenceCorrect and assertTransactionEquivalence which are inherited from the OpentapsTestCase and FinancialsTestCase base classes.&lt;br /&gt;
&lt;br /&gt;
For comparisons of GL account changes, we have set a convention so that increases in the balances of debit GL accounts are positive, and increases in the balances of credit GL accounts are negative values.  So, if a transaction caused an inventory GL account to increase by 100 and accounts payable to increase by 100 as well, the GL account changes would be {INVENTORY: 100, ACCOUNTS_PAYABLE: -100}&lt;br /&gt;
&lt;br /&gt;
Note that in this case we used the receiveInventoryProduct service to receive inventory, called the various production run services, and then compared the results versus pre-stored AcctgTrans and AcctgTransEntries.  With other tests, such as those for invoices and payments, we have used pre-existing Invoice and Payment records stored in the hot-deploy/opentaps-tests component and merely changed their status codes to verify the results.  This brings up an interesting question--what should be done during the service, and what with existing data?&lt;br /&gt;
&lt;br /&gt;
Our recommendation is this:&lt;br /&gt;
* What you are testing must be done with the services that you would normally use as part of your application.  For example, when we are testing GL postings, the user does not actually call the &amp;quot;postInvoiceToGl&amp;quot; service anywhere on the screen.  Instead, she would set the invoice status, and the services would run behind the scenes.  Therefore, it would not do to run the &amp;quot;postInvoiceToGl&amp;quot; test, or worse, manually create the results of that service in the database.  Instead, we should be calling the service to set invoice status, which is the same one accessed via the controller.  &lt;br /&gt;
* For everything else, do whatever is easiest to set up the pre-conditions for testing.  Calling receiveInventoryProduct is pretty easy compared to storing InventoryItem and InventoryItemDetail, so we decided to use that.  Calling createInvoice and createInvoiceItem would have been many lines of code, so we just stored an invoice in the database.&lt;br /&gt;
&lt;br /&gt;
==Creating Reference Data Sets==&lt;br /&gt;
&lt;br /&gt;
In many tests you will see comparisons against pre-stored AcctgTrans and AcctgTransEntries.  These are reference data sets which are used to compare actual transactions' results and make sure that they are consistent with the reference.  Reference data sets are created in the following way:&lt;br /&gt;
# Run through a set of business transactions, such as creating an invoice and marking it as READY.&lt;br /&gt;
# Go to Webtools &amp;gt; XML Data Export and select the entities to export.  In this case, it might be the Invoice, InvoiceItem, AcctgTrans, AcctgTransEntry entities.  Export them either to a file or to a browser and copy them to a file.&lt;br /&gt;
# Edit the file of transactions and change the following:&lt;br /&gt;
## All IDs from the system-generated 100xx to something like &amp;quot;XXX-TEST-###&amp;quot; so that they would not cause primary key conflicts.&lt;br /&gt;
## For AcctgTrans, change the glFiscalTypeId of all the AcctgTrans to &amp;quot;REFERENCE&amp;quot; from &amp;quot;ACTUAL&amp;quot; so they would not interfere with actual records.&lt;br /&gt;
## Remove references to entities which would not be part of the reference set.  For example, the invoice might be part of the reference set, but workEffortId, inventoryItemId, etc. referenced by AcctgTransEntry would not be.&lt;br /&gt;
## Test by loading the new entity XML into your dedicated testing database.  It should cause no conflicts.&lt;br /&gt;
## Add it to the opentaps-tests component's ofbiz-component.xml so that it would load for future tests and commit it!&lt;br /&gt;
&lt;br /&gt;
==Running a Unit Test from Beanshell==&lt;br /&gt;
&lt;br /&gt;
After you have written a lot of unit tests, running all of them could take a long time.  Fortunately, you can use beanshell to run just one unit test at a time to speed up your development.  To do this, you would need to telnet into your beanshell port, then instantiate an object of the unit tests class, and run your test method:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
si-chens-computer:~ sichen$ telnet localhost 9990&lt;br /&gt;
Trying ::1...&lt;br /&gt;
Connected to localhost.&lt;br /&gt;
Escape character is '^]'.&lt;br /&gt;
BeanShell 2.0b4 - by Pat Niemeyer (pat@pat.net)&lt;br /&gt;
bsh % import org.opentaps.tests.purchasing.MrpTests;&lt;br /&gt;
bsh % mrpTests = new MrpTests();&lt;br /&gt;
bsh % mrpTests.testMrpPurchasedProduct();&lt;br /&gt;
bsh %&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If the test succeeded, you would see no messages on your beanshell console.  If it failed, you would see a stack trace.  In both cases, you should see the log messages in runtime/logs/ofbiz.log or runtime/logs/console.log&lt;br /&gt;
&lt;br /&gt;
To make your life even simpler, you use [[Image:Tests.bsh.zip]] as a starting point and modify it for your test, then just call it with the source method from the beanshell console:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
bsh % source(&amp;quot;tests.bsh&amp;quot;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Debugging Unit Tests with IntelliJ==&lt;br /&gt;
&lt;br /&gt;
The default task for tests will do a global compile.  To skip this, you can redefine the run-tests target in build.xml as follows,&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    &amp;lt;target name=&amp;quot;run-tests&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;java jar=&amp;quot;ofbiz.jar&amp;quot; fork=&amp;quot;true&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;arg value=&amp;quot;test&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;/java&amp;gt;&lt;br /&gt;
    &amp;lt;/target&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using a debugger can help speed up development of the unit tests.  You can enable debugging by specifying the JVM arguments for your debugging system.  For instance, if you have the [http://www.jetbrains.com/idea/ IntelliJ IDE], the run-tests target becomes,&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    &amp;lt;target name=&amp;quot;run-tests&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;java jar=&amp;quot;ofbiz.jar&amp;quot; fork=&amp;quot;true&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;jvmarg value=&amp;quot;${memory.max.param}&amp;quot;/&amp;gt;&lt;br /&gt;
            &amp;lt;jvmarg value=&amp;quot;-Xdebug&amp;quot;/&amp;gt;&lt;br /&gt;
            &amp;lt;jvmarg value=&amp;quot;-Xnoagent&amp;quot;/&amp;gt;&lt;br /&gt;
            &amp;lt;jvmarg value=&amp;quot;-Djava.compiler=NONE &amp;quot;/&amp;gt;&lt;br /&gt;
            &amp;lt;jvmarg value=&amp;quot;-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005&amp;quot;/&amp;gt;&lt;br /&gt;
            &amp;lt;arg value=&amp;quot;test&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;/java&amp;gt;&lt;br /&gt;
    &amp;lt;/target&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You should be able to attach the debugger immediately after running '''ant run-tests'''.  Don't forget to recompile the component where your tests live.&lt;br /&gt;
&lt;br /&gt;
Another tip is to comment out all unnecessary test suites.  Unfortunately, this involves searching every ofbiz-component.xml.  One way to find them, if you're on a POSIX OS, is to use find,&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$  find . -name ofbiz-component.xml -exec grep test-suite {} \; -print&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Dealing with Concurrency==&lt;br /&gt;
&lt;br /&gt;
Since each test method runs in a separate thread, there may be concurrency issues when you are using demo or test data in a test.  For example, if you are testing whether a certain number of commission invoices are being generated for sales invoices, another thread could be generating additional ones at the same time.  This leads to unexpected results which can seem very mysterious.&lt;br /&gt;
&lt;br /&gt;
To avoid concurrency issues, ensure that your tests are using generated data for comparison purposes.  For example, rather than using &amp;lt;tt&amp;gt;DemoCustomer&amp;lt;/tt&amp;gt; as the target of a sales invoice, you can create a copy of &amp;lt;tt&amp;gt;DemoCustomer&amp;lt;/tt&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    String customerPartyId = createPartyFromTemplate(&amp;quot;DemoCustomer&amp;quot;);&lt;br /&gt;
    // create invoice for customerPartyId&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
From this point, any data that relies on the partyId is sure to be specific to that test only.  An example would be when we're checking the customer balance against &amp;lt;tt&amp;gt;customerPartyId&amp;lt;/tt&amp;gt;.  If we were checking the balance of &amp;lt;tt&amp;gt;DemoCustomer&amp;lt;/tt&amp;gt;, then we might be thrown off if another thread happens to create an invoice for &amp;lt;tt&amp;gt;DemoCustomer&amp;lt;/tt&amp;gt; at the same time.&lt;br /&gt;
&lt;br /&gt;
==Warning about running Unit Tests in MySQL==&lt;br /&gt;
&lt;br /&gt;
When running unit tests in MySQL that use transactions please be aware that an assert failure can issue a rollback on the transaction leaving the data on the database in an inconsistent state, potentially allowing the test to pass even if in reality it failed.&lt;br /&gt;
&lt;br /&gt;
MySQL does not store timestamps with a greater than 1 second precision.  Therefore, it could lead to some primary key violations when several attempts to store data with a timestamp as part of the primary key take place within the same second.  For example, if you update the status of an invoice several times during the same second in a test, the InvoiceStatus could experience primary key violations because one of its primary key fields is a timestamp.  To work around this problem, put pauses inside of your test:&lt;br /&gt;
    pause(&amp;quot;product average calculation&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
When runnig a long time test in MYSQL that might cause lock wait timeout error, so we need change the MYSQL innodb_lock_wait_timeout parameter to avoid this issue. See [[Database_Tips#Mysql_Tips]]&lt;/div&gt;</summary>
		<author><name>Spark</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=Database_Tips&amp;diff=3792</id>
		<title>Database Tips</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=Database_Tips&amp;diff=3792"/>
		<updated>2009-03-19T10:07:22Z</updated>

		<summary type="html">&lt;p&gt;Spark: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
==General==&lt;br /&gt;
&lt;br /&gt;
* [http://www.javaworld.com/jw-07-2000/jw-0714-transaction.html J2EE Transaction Management]&lt;br /&gt;
* [http://publib.boulder.ibm.com/infocenter/txformp/v5r1/index.jsp?topic=/com.ibm.txseries510.doc/aetgpw0055.htm Nested Transactions]&lt;br /&gt;
* [http://www.precisejava.com/javaperf/j2ee/JDBC.htm JDBC Best Practices]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==PostgreSQL Tips==&lt;br /&gt;
&lt;br /&gt;
* [http://wiki.postgresql.org/wiki/Performance_Optimization PostgreSQL Wiki Article on Performance Optimization]&lt;br /&gt;
* [http://www.phpbuilder.com/columns/smith20010821.php3 Optimizing PostgreSQL]&lt;br /&gt;
===Monitoring PostgreSQL Deadlocks===&lt;br /&gt;
&lt;br /&gt;
You can monitor any database locks using the Entity SQL Processor in '''Webtools -&amp;gt; Entity SQL Processor''' with the following query,&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
select pg_class.relname, pg_locks.mode, pg_locks.relation, pg_locks.transaction, pg_locks.pid&lt;br /&gt;
    from pg_class, pg_locks &lt;br /&gt;
    where pg_class.relfilenode = pg_locks.relation &lt;br /&gt;
    order by pid&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will show what kinds of locks are active on what entities.  If there is an exclusive lock on a table followed by a bunch of pids that are waiting for it, then you have a deadlock.&lt;br /&gt;
&lt;br /&gt;
===Checking Open PostgreSQL Connections===&lt;br /&gt;
&lt;br /&gt;
Run this query:&lt;br /&gt;
  select datname, numbackends from pg_stat_database;&lt;br /&gt;
&lt;br /&gt;
to see the number of open connections to each of your databases.  See [http://bytes.com/forum/thread616677.html How to Know Number of Connections Made with Database - PostgreSQL]&lt;br /&gt;
&lt;br /&gt;
If you are running out of connections, edit the file &amp;lt;tt&amp;gt;framework/entity/config/entityengine.xml&amp;lt;/tt&amp;gt; and increase the number of connections available.&lt;br /&gt;
&lt;br /&gt;
==MySQL Tips==&lt;br /&gt;
&lt;br /&gt;
===Table Name Case Sensitivity===&lt;br /&gt;
&lt;br /&gt;
If you use Linux or Unix for your MySQL server, the table names may be case sensitive, so PRODUCT and product are not the same table.  You can turn this off by configuring mysqld on startup to ignore table names with the lower-case-table-names flag, such as this example from /etc/init.d/mysql:&lt;br /&gt;
  $bindir/mysqld_safe --datadir=$datadir --lower-case-table-names=1 --pid-file=$server_pid_file $other_args &amp;gt;/dev/null 2&amp;gt;&amp;amp;1 &amp;amp;&lt;br /&gt;
      &lt;br /&gt;
See [http://dev.mysql.com/doc/refman/5.0/en/identifier-case-sensitivity.html MySQL manual on identifier case sentivity]&lt;br /&gt;
&lt;br /&gt;
===UTF-8 Support===&lt;br /&gt;
&lt;br /&gt;
By default, MySQL supports the Latin1 character set, which is intended for European languages such as English.  If you wish to use MySQL for other language types, you may need to set up a database or UTF-8 character set encoding.  To do this, you would need to create your database using UTF-8 first:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   mysql&amp;gt; create database opentaps default character set utf8 collate utf8_general_ci;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then you would need to set your framework/entity/config/entityengine.xml file for the MySQL database to use the UTF-8 character set:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            character-set=&amp;quot;utf8&amp;quot;&lt;br /&gt;
            collate=&amp;quot;utf8_general_ci&amp;quot; &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that it is not clear that my SQL supports case sensitive UTF-8 coalition at this point, although you may be able to [http://forums.mysql.com/read.php?103,156527,198794#msg-198794 use UTF-8 binary collation].&lt;br /&gt;
&lt;br /&gt;
===Lock Timeout===&lt;br /&gt;
&lt;br /&gt;
==DB2 Tips==&lt;br /&gt;
&lt;br /&gt;
===DB2 Basics===&lt;br /&gt;
&lt;br /&gt;
You must configure DB2 to have tablespaces of 8K or more.  This can be done when you create the database from the Control Center:&lt;br /&gt;
[[Image:DB2_tablespace.PNG]]&lt;br /&gt;
&lt;br /&gt;
If you get an error message from DB2, you will get a SQLCODE like below:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
DB2 SQL Error: SQLCODE=-270, SQLSTATE=42997, SQLERRMC=63, DRIVER=3.50.152&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To figure out what it is, you have to run db2 from the command line:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ db2 ? sql-270&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Some of the more popular codes are:&lt;br /&gt;
* SQL-204: &amp;lt;name&amp;gt; not recognized.  Most likely, you are referencing a table that doesn't exist.&lt;br /&gt;
* SQL-270: Function not supported.  See the SQLERRMC for the message code.  If you get sql-270 with sqlerrmc=63, it means that you are trying to select a CLOB/BLOB type with a scroll insensitive cursor.&lt;br /&gt;
* SQL-286: insufficient page size for CREATE TABLE&lt;br /&gt;
* SQL-530: foreign key violation&lt;br /&gt;
* SQL-803: operation violates a unique value constraint &lt;br /&gt;
&lt;br /&gt;
=== Making DB2 Work ===&lt;br /&gt;
&lt;br /&gt;
There are three issues with using DB2 and opentaps:&lt;br /&gt;
&lt;br /&gt;
# You must define a &amp;lt;tt&amp;gt;fieldtypedb2.xml&amp;lt;/tt&amp;gt; file for your &amp;lt;tt&amp;gt;framework/entity/fieldtype/&amp;lt;/tt&amp;gt; directory.  You can Start with the field type XML from another database, such as MySQL.  Most of the [http://www.informit.com/content/images/0672326132/downloads/appc.pdf valid DB2 field types] are similar, but DB2 does not have a &amp;quot;NUMERIC&amp;quot; type.  It is called &amp;quot;DECIMAL&amp;quot; instead of must be used for floating-point and currency field types.&lt;br /&gt;
# On startup, the ofbiz entity engine does a check of the database against the entity model definitions.  Part of the check is to verify that the primary keys of all the tables are correctly defined, but the entity engine attempts to obtain the primary key information for all the tables of the database at once, which is not supported by DB2.  To make this feature work, you need to modify DatabaseUtil.java to have the entity engine check the primary keys one table at a time.  &lt;br /&gt;
# The biggest problem with DB2 is that it does not support SELECT operations which include CLOB/BLOB fields when the [http://java.sun.com/j2se/1.3/docs/guide/jdbc/spec2/jdbc2.1.frame5.html ResultSet is scroll insensitive]  (See [http://publib.boulder.ibm.com/infocenter/db2luw/v8/index.jsp?topic=/com.ibm.db2.udb.doc/ad/tjvrsush.htm].)  The solution is not as simple as just changing the result set type, because DB2 also does not support (i) SELECT operations on views or with JOIN using scroll sensitive cursor or (ii) moving around with .absolute(i) or .relative(i) operations on a ResultSet of TYPE_FORWARD_ONLY.  This means that the view entities which include CLOB/BLOB types cannot be SELECTED (because you cannot use a scroll insensitive ResultSet), or that the EntityListIterator.getPartialList method will not work (because you cannot use .absolute and .relative), so the ofbiz form widget's list form will not paginate correctly.  There is no solution for this problem, but the following workarounds exist:&lt;br /&gt;
## Since the majority of the large object (LOB) types are CLOB for long character strings, you can redefine the field type for your blob and very-long to be the longest possible VARCHAR instead of using CLOB.&lt;br /&gt;
## You can avoid using the getPartialList feature and instead use findAll or findByAnd to return a Java list, and then use the sublist() method on it.  These queries are done with TYPE_FORWARD_ONLY and return the entire list at once, but the drawback is that a Java list has a limited capacity of about 65,000 records.&lt;br /&gt;
## If neither of these workarounds are acceptable, you would have to rewrite certain features (like surveys with long text responses) to conform to DB2's restrictions.&lt;br /&gt;
&lt;br /&gt;
In practice, most ERP-related uses of opentaps would not require CLOB's, so the first option should suffice.  Only with content management features would such field types be required, and those features would need to be rewritten for DB2 compatibility.&lt;br /&gt;
&lt;br /&gt;
==Mysql Tips==&lt;br /&gt;
&lt;br /&gt;
You must change [http://dev.mysql.com/doc/refman/5.0/en/innodb-parameters.html#sysvar_innodb_lock_wait_timeout innodb_lock_wait_timeout] parameter , else you might get error like these:&lt;br /&gt;
&lt;br /&gt;
  Lock wait timeout exceeded; try restarting transaction&lt;br /&gt;
&lt;br /&gt;
You can add this line in your mysql config (Windows: [MYSQL_HOME]\my.ini, Linux: /etc/my.cnf)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#set lock timeout 300s, default is 50s&lt;br /&gt;
innodb_lock_wait_timeout=300&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Spark</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=Opentaps_Asterisk_Integration&amp;diff=3783</id>
		<title>Opentaps Asterisk Integration</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=Opentaps_Asterisk_Integration&amp;diff=3783"/>
		<updated>2009-03-18T11:17:25Z</updated>

		<summary type="html">&lt;p&gt;Spark: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;opentaps can be integrated with the [http://www.asterisk.org Asterisk open source PBX] which allows to call from opentaps using Asterisk and to be automatically redirected to the inbound caller in opentaps.  This short tutorial teaches you how to configure the opentaps-Asterisk integration and how to use Asterisk from opentaps.&lt;br /&gt;
&lt;br /&gt;
== Configuring the opentaps Asterisk Integration ==&lt;br /&gt;
&lt;br /&gt;
To configure this, first edit the file &amp;lt;tt&amp;gt;/etc/asterisk/manager.conf&amp;lt;/tt&amp;gt; and add follow lines to create an manager account for opentaps connect: &lt;br /&gt;
  ;login account&lt;br /&gt;
  [eventsdaemon]&lt;br /&gt;
  ;login password&lt;br /&gt;
  secret = pa55w0rd321&lt;br /&gt;
  ;permit network area&lt;br /&gt;
  permit = 0.0.0.0/0.0.0.0&lt;br /&gt;
  ;listen events&lt;br /&gt;
  read = system,call,log,verbose,command,agent,user&lt;br /&gt;
  ;write events&lt;br /&gt;
  write = system,call,log,verbose,command,agent,user&lt;br /&gt;
next edit the file &amp;lt;tt&amp;gt;hot-deploy/opentaps-common/config/asterisk.properties&amp;lt;/tt&amp;gt;  and follow these steps:&lt;br /&gt;
* Turn on asterisk integration by changing &amp;lt;tt&amp;gt;asterisk.enabled&amp;lt;/tt&amp;gt; from N to Y&lt;br /&gt;
  asterisk.enabled = Y&lt;br /&gt;
* Set up the asterisk server address and login credentials:&lt;br /&gt;
  asterisk.host = asterisk.host.org&lt;br /&gt;
  asterisk.username = eventsdaemon&lt;br /&gt;
  asterisk.password = password&lt;br /&gt;
* Enter the telephone number associated with your asterisk server.  This should be a Plain Old Telephone System (POTS) phone number that someone from the outside could call you on:&lt;br /&gt;
  asterisk.countryCode = 1&lt;br /&gt;
  asterisk.areaCode = 310&lt;br /&gt;
  asterisk.phoneNumber = 9876543&lt;br /&gt;
* Now configure your outbound dialing prefrences.  You need the outbound dialing prefix and additional prefix for calling long distance and foreign phone numbers:&lt;br /&gt;
  asterisk.outbound.prev = 9&lt;br /&gt;
  asterisk.outbound.area = 1&lt;br /&gt;
  asterisk.outbound.foreign = 011&lt;br /&gt;
* In some places such as Los Angeles, you must always dial the area code, even when the phone number you are calling is in the same area code.  These properties configure whether you must always dial the country or area code:&lt;br /&gt;
  asterisk.alwaysDialCountryCode = Y&lt;br /&gt;
  asterisk.alwaysDialAreaCode = Y&lt;br /&gt;
*  Finally, this property configures how frequently opentaps should check for new inbound calls from the asterisk server.  By default, it's set to every three seconds:&lt;br /&gt;
  asterisk.checkFrequencySeconds = 3&lt;br /&gt;
&lt;br /&gt;
Next, you would need to set up the extensions on the Asterisk PBX server for your opentaps users.   In opentaps, you can assign a different user login to each unique extension.  This can be done by modifying the &amp;lt;tt&amp;gt;AsteriskUser&amp;lt;/tt&amp;gt; entity in Web tools or its equivalent &amp;lt;tt&amp;gt;ASTERISK_USER&amp;lt;/tt&amp;gt; table in your database.  You would need to enter the user login ID, the extension, and the effective dates, like this:&lt;br /&gt;
&lt;br /&gt;
[[Image:AsteriskUser_values.PNG]]&lt;br /&gt;
&lt;br /&gt;
Now you are ready.  Restart opentaps, and let's see what it does!&lt;br /&gt;
&lt;br /&gt;
== Using Asterisk from opentaps ==&lt;br /&gt;
&lt;br /&gt;
=== Outbound Calls ===&lt;br /&gt;
&lt;br /&gt;
Making outbound calls is easy.  Wherever you see a phone number with a link underneath it, you can click on the link, and opentaps will call out from your Asterisk servers using the extension associated with your user login.  This should cause the Asterisk server to ring the handset configured to your extension:&lt;br /&gt;
[[Image:Asterisk_outbound_call_1.PNG]]&lt;br /&gt;
&lt;br /&gt;
All you have to do is pick up your phone, and the call is establish.  If you are in the opentaps CRM application, opentaps will then take you to the screen for logging the call so that you can record this call:&lt;br /&gt;
[[Image:Asterisk_outbound_call_2.PNG]]&lt;br /&gt;
&lt;br /&gt;
=== Inbound Calls ===&lt;br /&gt;
&lt;br /&gt;
When an inbound call rings to your Asterisk extension, an opentaps widget will display in the upper right-hand corner of your screen:&lt;br /&gt;
[[Image:Asterisk_inbound_call_1.PNG]]&lt;br /&gt;
&lt;br /&gt;
Click on the link in the widget, and opentaps will take you to a page with the caller's information:&lt;br /&gt;
[[Image:Asterisk_inbound_call_2.PNG]]&lt;br /&gt;
&lt;br /&gt;
== Configuring Asterisk on Amazon Elastic Computing (EC2) Cloud ==&lt;br /&gt;
&lt;br /&gt;
If you don't have an asterisk server, you can use one of the AMI images from [http://resvoip.com/2009/02/19/resvoip-ec2-build-3/ resvoip].  We used ami-2ec62147.  This image sets up a virtual Linux server with asterisk preinstalled.&lt;br /&gt;
&lt;br /&gt;
The only special configuration we found necessary when using Asterisk on the Amazon EC2 cloud was to edit the &amp;lt;tt&amp;gt;/etc/asterisk/sip_general_custom.conf&amp;lt;/tt&amp;gt; file to configure both the external and internal IP addresses:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# your Amazon EC2 Internet IP&lt;br /&gt;
externip = 174.123.456.789&lt;br /&gt;
# your Amazon EC2 local network setting              &lt;br /&gt;
localnet= 10.254.234.123/255.255.254.0 &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, the following ports need to be opened:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
udp 10000-20000, 4569, 5036, 5060&lt;br /&gt;
tcp 5060, 5038&lt;br /&gt;
tcp 22, 80 &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, your opentaps instance can connect to the Asterisk server on Amazon EC2 through an SSH tunnel, like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ssh -i ~/ec2/asterisktest.pem -L 5038:ec2-174-123-456-789.compute-1.amazonaws.com:5038   root@ec2-174-123-456-789.compute-1.amazonaws.com&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Test your connection with:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ telnet localhost 5038&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If it's successful, then you should set your &amp;lt;tt&amp;gt;asterisk.host&amp;lt;/tt&amp;gt; in &amp;lt;tt&amp;gt;asterisk.properties&amp;lt;/tt&amp;gt; to '''localhost''' when configuring opentaps for Asterisk integration.  (See above.)&lt;/div&gt;</summary>
		<author><name>Spark</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=Opentaps_Asterisk_Integration&amp;diff=3782</id>
		<title>Opentaps Asterisk Integration</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=Opentaps_Asterisk_Integration&amp;diff=3782"/>
		<updated>2009-03-18T11:14:24Z</updated>

		<summary type="html">&lt;p&gt;Spark: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;opentaps can be integrated with the [http://www.asterisk.org Asterisk open source PBX] which allows to call from opentaps using Asterisk and to be automatically redirected to the inbound caller in opentaps.  This short tutorial teaches you how to configure the opentaps-Asterisk integration and how to use Asterisk from opentaps.&lt;br /&gt;
&lt;br /&gt;
== Configuring the opentaps Asterisk Integration ==&lt;br /&gt;
&lt;br /&gt;
To configure this, first edit the file &amp;lt;tt&amp;gt;/etc/asterisk/manager.conf&amp;lt;/tt&amp;gt; and add follow lines: &lt;br /&gt;
  ;login account&lt;br /&gt;
  [eventsdaemon]&lt;br /&gt;
  ;login password&lt;br /&gt;
  secret = pa55w0rd321&lt;br /&gt;
  ;permit network area&lt;br /&gt;
  permit = 0.0.0.0/0.0.0.0&lt;br /&gt;
  ;listen events&lt;br /&gt;
  read = system,call,log,verbose,command,agent,user&lt;br /&gt;
  ;write events&lt;br /&gt;
  write = system,call,log,verbose,command,agent,user&lt;br /&gt;
next edit the file &amp;lt;tt&amp;gt;hot-deploy/opentaps-common/config/asterisk.properties&amp;lt;/tt&amp;gt;  and follow these steps:&lt;br /&gt;
* Turn on asterisk integration by changing &amp;lt;tt&amp;gt;asterisk.enabled&amp;lt;/tt&amp;gt; from N to Y&lt;br /&gt;
  asterisk.enabled = Y&lt;br /&gt;
* Set up the asterisk server address and login credentials:&lt;br /&gt;
  asterisk.host = asterisk.host.org&lt;br /&gt;
  asterisk.username = eventsdaemon&lt;br /&gt;
  asterisk.password = password&lt;br /&gt;
* Enter the telephone number associated with your asterisk server.  This should be a Plain Old Telephone System (POTS) phone number that someone from the outside could call you on:&lt;br /&gt;
  asterisk.countryCode = 1&lt;br /&gt;
  asterisk.areaCode = 310&lt;br /&gt;
  asterisk.phoneNumber = 9876543&lt;br /&gt;
* Now configure your outbound dialing prefrences.  You need the outbound dialing prefix and additional prefix for calling long distance and foreign phone numbers:&lt;br /&gt;
  asterisk.outbound.prev = 9&lt;br /&gt;
  asterisk.outbound.area = 1&lt;br /&gt;
  asterisk.outbound.foreign = 011&lt;br /&gt;
* In some places such as Los Angeles, you must always dial the area code, even when the phone number you are calling is in the same area code.  These properties configure whether you must always dial the country or area code:&lt;br /&gt;
  asterisk.alwaysDialCountryCode = Y&lt;br /&gt;
  asterisk.alwaysDialAreaCode = Y&lt;br /&gt;
*  Finally, this property configures how frequently opentaps should check for new inbound calls from the asterisk server.  By default, it's set to every three seconds:&lt;br /&gt;
  asterisk.checkFrequencySeconds = 3&lt;br /&gt;
&lt;br /&gt;
Next, you would need to set up the extensions on the Asterisk PBX server for your opentaps users.   In opentaps, you can assign a different user login to each unique extension.  This can be done by modifying the &amp;lt;tt&amp;gt;AsteriskUser&amp;lt;/tt&amp;gt; entity in Web tools or its equivalent &amp;lt;tt&amp;gt;ASTERISK_USER&amp;lt;/tt&amp;gt; table in your database.  You would need to enter the user login ID, the extension, and the effective dates, like this:&lt;br /&gt;
&lt;br /&gt;
[[Image:AsteriskUser_values.PNG]]&lt;br /&gt;
&lt;br /&gt;
Now you are ready.  Restart opentaps, and let's see what it does!&lt;br /&gt;
&lt;br /&gt;
== Using Asterisk from opentaps ==&lt;br /&gt;
&lt;br /&gt;
=== Outbound Calls ===&lt;br /&gt;
&lt;br /&gt;
Making outbound calls is easy.  Wherever you see a phone number with a link underneath it, you can click on the link, and opentaps will call out from your Asterisk servers using the extension associated with your user login.  This should cause the Asterisk server to ring the handset configured to your extension:&lt;br /&gt;
[[Image:Asterisk_outbound_call_1.PNG]]&lt;br /&gt;
&lt;br /&gt;
All you have to do is pick up your phone, and the call is establish.  If you are in the opentaps CRM application, opentaps will then take you to the screen for logging the call so that you can record this call:&lt;br /&gt;
[[Image:Asterisk_outbound_call_2.PNG]]&lt;br /&gt;
&lt;br /&gt;
=== Inbound Calls ===&lt;br /&gt;
&lt;br /&gt;
When an inbound call rings to your Asterisk extension, an opentaps widget will display in the upper right-hand corner of your screen:&lt;br /&gt;
[[Image:Asterisk_inbound_call_1.PNG]]&lt;br /&gt;
&lt;br /&gt;
Click on the link in the widget, and opentaps will take you to a page with the caller's information:&lt;br /&gt;
[[Image:Asterisk_inbound_call_2.PNG]]&lt;br /&gt;
&lt;br /&gt;
== Configuring Asterisk on Amazon Elastic Computing (EC2) Cloud ==&lt;br /&gt;
&lt;br /&gt;
If you don't have an asterisk server, you can use one of the AMI images from [http://resvoip.com/2009/02/19/resvoip-ec2-build-3/ resvoip].  We used ami-2ec62147.  This image sets up a virtual Linux server with asterisk preinstalled.&lt;br /&gt;
&lt;br /&gt;
The only special configuration we found necessary when using Asterisk on the Amazon EC2 cloud was to edit the &amp;lt;tt&amp;gt;/etc/asterisk/sip_general_custom.conf&amp;lt;/tt&amp;gt; file to configure both the external and internal IP addresses:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# your Amazon EC2 Internet IP&lt;br /&gt;
externip = 174.123.456.789&lt;br /&gt;
# your Amazon EC2 local network setting              &lt;br /&gt;
localnet= 10.254.234.123/255.255.254.0 &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, the following ports need to be opened:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
udp 10000-20000, 4569, 5036, 5060&lt;br /&gt;
tcp 5060, 5038&lt;br /&gt;
tcp 22, 80 &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, your opentaps instance can connect to the Asterisk server on Amazon EC2 through an SSH tunnel, like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ssh -i ~/ec2/asterisktest.pem -L 5038:ec2-174-123-456-789.compute-1.amazonaws.com:5038   root@ec2-174-123-456-789.compute-1.amazonaws.com&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Test your connection with:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ telnet localhost 5038&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If it's successful, then you should set your &amp;lt;tt&amp;gt;asterisk.host&amp;lt;/tt&amp;gt; in &amp;lt;tt&amp;gt;asterisk.properties&amp;lt;/tt&amp;gt; to '''localhost''' when configuring opentaps for Asterisk integration.  (See above.)&lt;/div&gt;</summary>
		<author><name>Spark</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=Opentaps_Asterisk_Integration&amp;diff=3563</id>
		<title>Opentaps Asterisk Integration</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=Opentaps_Asterisk_Integration&amp;diff=3563"/>
		<updated>2008-11-26T10:58:37Z</updated>

		<summary type="html">&lt;p&gt;Spark: Protected &amp;quot;Asterisk Integration&amp;quot;: Sysop page [edit=sysop:move=sysop]&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;opentaps can integrate [http://www.asterisk.org asterisk system] which allows your users to click-to-call or pop customer inforamtion on calling in. If you would like to use this feature, edit the file hot-deploy/opentaps-common/config/asterisk.properties and change the settings to the following fields:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# if enable asterisk support&lt;br /&gt;
asterisk.enabled = N&lt;br /&gt;
# asterisk server host ip&lt;br /&gt;
asterisk.host = 192.168.0.99&lt;br /&gt;
# asterisk manager username,defined in /etc/asterisk/manager.conf&lt;br /&gt;
asterisk.username = asteriskuser&lt;br /&gt;
# asterisk manager password&lt;br /&gt;
asterisk.password = password&lt;br /&gt;
# out dial prev code&lt;br /&gt;
asterisk.outbound.prev = 9&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Spark</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=Opentaps_Asterisk_Integration&amp;diff=3562</id>
		<title>Opentaps Asterisk Integration</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=Opentaps_Asterisk_Integration&amp;diff=3562"/>
		<updated>2008-11-26T10:58:35Z</updated>

		<summary type="html">&lt;p&gt;Spark: New page: opentaps can integrate [http://www.asterisk.org asterisk system] which allows your users to click-to-call or pop customer inforamtion on calling in. If you would like to use this feature, ...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;opentaps can integrate [http://www.asterisk.org asterisk system] which allows your users to click-to-call or pop customer inforamtion on calling in. If you would like to use this feature, edit the file hot-deploy/opentaps-common/config/asterisk.properties and change the settings to the following fields:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# if enable asterisk support&lt;br /&gt;
asterisk.enabled = N&lt;br /&gt;
# asterisk server host ip&lt;br /&gt;
asterisk.host = 192.168.0.99&lt;br /&gt;
# asterisk manager username,defined in /etc/asterisk/manager.conf&lt;br /&gt;
asterisk.username = asteriskuser&lt;br /&gt;
# asterisk manager password&lt;br /&gt;
asterisk.password = password&lt;br /&gt;
# out dial prev code&lt;br /&gt;
asterisk.outbound.prev = 9&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Spark</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=Opentaps_VoIP_Setup&amp;diff=3554</id>
		<title>Opentaps VoIP Setup</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=Opentaps_VoIP_Setup&amp;diff=3554"/>
		<updated>2008-11-24T06:09:50Z</updated>

		<summary type="html">&lt;p&gt;Spark: /* VoIP Integration */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==VoIP Integration==&lt;br /&gt;
* [[Asterisk Integration]]&lt;br /&gt;
* [[FacetPhone Integration]]&lt;/div&gt;</summary>
		<author><name>Spark</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=Asteriks_Integration&amp;diff=3553</id>
		<title>Asteriks Integration</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=Asteriks_Integration&amp;diff=3553"/>
		<updated>2008-11-24T06:08:15Z</updated>

		<summary type="html">&lt;p&gt;Spark: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;opentaps can integrate [http://www.asterisk.org asterisk system] which allows your users to click-to-call or pop customer inforamtion on calling in. If you would like to use this feature, edit the file hot-deploy/opentaps-common/config/asterisk.properties and change the settings to the following fields:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# if enable asterisk support&lt;br /&gt;
asterisk.enabled = N&lt;br /&gt;
# asterisk server host ip&lt;br /&gt;
asterisk.host = 192.168.0.99&lt;br /&gt;
# asterisk manager username,defined in /etc/asterisk/manager.conf&lt;br /&gt;
asterisk.username = asteriskuser&lt;br /&gt;
# asterisk manager password&lt;br /&gt;
asterisk.password = password&lt;br /&gt;
# out dial prev code&lt;br /&gt;
asterisk.outbound.prev = 9&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Spark</name></author>
		
	</entry>
</feed>