<?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=Danutc</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=Danutc"/>
	<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=Special:Contributions/Danutc"/>
	<updated>2026-05-15T16:43:27Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.32.1</generator>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=PHP_SCA&amp;diff=5374</id>
		<title>PHP SCA</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=PHP_SCA&amp;diff=5374"/>
		<updated>2010-01-25T23:04:23Z</updated>

		<summary type="html">&lt;p&gt;Danutc: New page: This prototype will SCA enable both opentaps and magento. Opentaps calls magento and magento fires back events. SCA has the concept of bi-directional interfaces one end being the Call and ...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This prototype will SCA enable both opentaps and magento. Opentaps calls magento and magento fires back events. SCA has the concept of bi-directional interfaces one end being the Call and the other end the CallBack. The caller is responsible to initiate the conversation and after that the communication is peer-to-peer.&lt;br /&gt;
&lt;br /&gt;
Relevant information can be found at:&lt;br /&gt;
&lt;br /&gt;
* [http://tuscany.apache.org/ Apache Tuscany SCA / ESB]&lt;br /&gt;
* [http://tuscany.apache.org/php-sca.html Tuscany PHP]&lt;br /&gt;
* [http://www.davidchappell.com/articles/Introducing_SCA.pdf INTRODUCING SCA]&lt;br /&gt;
* [http://www.osoa.org/display/PHP/SOA+PHP+Homepage SOA PHP Homepage at OSOA]&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
== The Prototype ==&lt;br /&gt;
&lt;br /&gt;
[[Image:magento.1,3_opentaps.1.4_Integration.png]]&lt;br /&gt;
&lt;br /&gt;
Details about my investigations are coming soon ...&lt;/div&gt;</summary>
		<author><name>Danutc</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=PHP_SCA&amp;diff=5375</id>
		<title>PHP SCA</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=PHP_SCA&amp;diff=5375"/>
		<updated>2010-01-25T23:04:23Z</updated>

		<summary type="html">&lt;p&gt;Danutc: Protected &amp;quot;PHP SCA&amp;quot;: Sysop page [edit=sysop:move=sysop]&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This prototype will SCA enable both opentaps and magento. Opentaps calls magento and magento fires back events. SCA has the concept of bi-directional interfaces one end being the Call and the other end the CallBack. The caller is responsible to initiate the conversation and after that the communication is peer-to-peer.&lt;br /&gt;
&lt;br /&gt;
Relevant information can be found at:&lt;br /&gt;
&lt;br /&gt;
* [http://tuscany.apache.org/ Apache Tuscany SCA / ESB]&lt;br /&gt;
* [http://tuscany.apache.org/php-sca.html Tuscany PHP]&lt;br /&gt;
* [http://www.davidchappell.com/articles/Introducing_SCA.pdf INTRODUCING SCA]&lt;br /&gt;
* [http://www.osoa.org/display/PHP/SOA+PHP+Homepage SOA PHP Homepage at OSOA]&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
== The Prototype ==&lt;br /&gt;
&lt;br /&gt;
[[Image:magento.1,3_opentaps.1.4_Integration.png]]&lt;br /&gt;
&lt;br /&gt;
Details about my investigations are coming soon ...&lt;/div&gt;</summary>
		<author><name>Danutc</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=User_talk:Danutc&amp;diff=5373</id>
		<title>User talk:Danutc</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=User_talk:Danutc&amp;diff=5373"/>
		<updated>2010-01-25T23:03:10Z</updated>

		<summary type="html">&lt;p&gt;Danutc: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* [[BPM Integration]]&lt;br /&gt;
* [[BPM - Getting Started]]&lt;br /&gt;
* [[jBPM - Opentaps 1.x Integration Prototype]]&lt;br /&gt;
* [[Magento 1.x - Opentaps 1.x Integration Prototype]]&lt;br /&gt;
* [[PHP SCA]]&lt;br /&gt;
* [[opentaps-osgi]]&lt;br /&gt;
* [[ofbiz-osgi-prototype]]&lt;br /&gt;
* [[danc - temp]]&lt;/div&gt;</summary>
		<author><name>Danutc</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=Magento_1.x_-_Opentaps_1.x_Integration_Prototype&amp;diff=5371</id>
		<title>Magento 1.x - Opentaps 1.x Integration Prototype</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=Magento_1.x_-_Opentaps_1.x_Integration_Prototype&amp;diff=5371"/>
		<updated>2010-01-25T23:01:12Z</updated>

		<summary type="html">&lt;p&gt;Danutc: Magento 1.x - Opentaps 1.x Integration Prototype moved to Private page: PHP SCA: the page title is not relevant anymore&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[Private page: PHP SCA]]&lt;/div&gt;</summary>
		<author><name>Danutc</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=Ofbiz-osgi-prototype&amp;diff=4849</id>
		<title>Ofbiz-osgi-prototype</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=Ofbiz-osgi-prototype&amp;diff=4849"/>
		<updated>2009-11-05T22:00:26Z</updated>

		<summary type="html">&lt;p&gt;Danutc: /* What is ofbiz-osgi prototype? */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page provides information about running ofbiz as an OSGi bundle; this prototype has been hand-crafted.&lt;br /&gt;
&lt;br /&gt;
== What is ofbiz-osgi prototype? ==&lt;br /&gt;
It consists of two eclipse projects and a set of bundles for third party dependencies. One eclipse project is the ofbiz bundle and the other project is a bundle that calls ofbiz start.&lt;br /&gt;
&lt;br /&gt;
The ofbiz bundle and many dependencies were manually created so there is no build. Also the web applications do not work as Tomcat is not started. However the ofbiz services are available and can be tested.&lt;br /&gt;
&lt;br /&gt;
== Download the binaries ==&lt;br /&gt;
Please download the binaries from:&lt;br /&gt;
&lt;br /&gt;
[https://sourceforge.net/projects/ofbiz-osgi/files/ ofbiz-osgi files]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;ofbiz-osgi-prototype-bundles.zip&amp;lt;/b&amp;gt; (size is 38 MB)&lt;br /&gt;
&lt;br /&gt;
Unzip the archive in a folder; let's call it &amp;quot;base&amp;quot;. Under base folder there are 3 folders:&lt;br /&gt;
&lt;br /&gt;
* bundles (includes required dependencies packaged as OSGi bundles)&lt;br /&gt;
* com.viithiisys.ofbiz.service (OSGi bundle that activates the ofbiz bundle)&lt;br /&gt;
* org.apache.ofbiz (ofbiz as OSGi bundle)&lt;br /&gt;
&lt;br /&gt;
== Create the OSGi platform in eclipse ==&lt;br /&gt;
&lt;br /&gt;
* create a new eclipse workspace to start fresh&lt;br /&gt;
* go to Windows -&amp;gt; Preferences&lt;br /&gt;
** in the filter text box type &amp;quot;console&amp;quot;&lt;br /&gt;
** in the Run/Debug Console section un-check &amp;quot;Limit console output&amp;quot;&lt;br /&gt;
** clear the filter and select &amp;quot;Plug-in Development&amp;quot; -&amp;gt; &amp;quot;Target Platform&amp;quot;&lt;br /&gt;
** click Add button to add a new OSGi platform&lt;br /&gt;
** select Template -&amp;gt; Base RCP (Binary Only) then click Next; this option adds the core equinox OSGi components&lt;br /&gt;
** click Add button; select Directory; and select location &amp;quot;base/bundles&amp;quot;; click Finish; (this adds the ofbiz dependencies)&lt;br /&gt;
** click Finish to complete the platform creation&lt;br /&gt;
** select the new platform (by default is called &amp;quot;Base RCP (Binary Only)&amp;quot;); click Apply so it becomes the default platform&lt;br /&gt;
** you can click Reload button to make sure that it is all loaded and fresh&lt;br /&gt;
&lt;br /&gt;
== Add projects to eclipse ==&lt;br /&gt;
&lt;br /&gt;
* File -&amp;gt; Import -&amp;gt; General -&amp;gt; Existing Projects into Workspace&lt;br /&gt;
* select folder &amp;quot;com.viithiisys.ofbiz.service&amp;quot; under base and click Finish&lt;br /&gt;
* File -&amp;gt; Import -&amp;gt; General -&amp;gt; Existing Projects into Workspace&lt;br /&gt;
* select folder &amp;quot;org.apache.ofbiz&amp;quot; under base and click Finish&lt;br /&gt;
* Project -&amp;gt; Clean -&amp;gt; Clean All Projects&lt;br /&gt;
* there should be no errors after clen&lt;br /&gt;
* open the Problems window to check (Window -&amp;gt; Show View -&amp;gt; Other -&amp;gt; General -&amp;gt; Problems)&lt;br /&gt;
&lt;br /&gt;
== Create a running configuration and run the platform ==&lt;br /&gt;
&lt;br /&gt;
* point ofbiz to your database (check under folder base/org.apache.ofbiz)&lt;br /&gt;
* Run -&amp;gt; Run Configurations -&amp;gt; OSGi Framework -&amp;gt; New&lt;br /&gt;
* give it a name (ofbiz-osgi)&lt;br /&gt;
* click &amp;quot;Add Required Bundles&amp;quot; button&lt;br /&gt;
* click &amp;quot;Validate Bundles&amp;quot;; there is reported one problem with groovy missing javax.management; this error can be ignored&lt;br /&gt;
* select checkbox &amp;quot;Validate bundles automatically prior to launching&amp;quot;&lt;br /&gt;
* go to Arguments tab&lt;br /&gt;
* change VM arguments; add parameter:  -Dofbiz.home=....\base\org.apache.ofbiz so ofbiz finds its configuration&lt;br /&gt;
* click Apply button&lt;br /&gt;
* click Run button&lt;br /&gt;
&lt;br /&gt;
Watching the console you see a trace similar to:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;ofbiz-osgi-prototype-sample-log.log&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Please download ofbiz-osgi-prototype-sample-log.log from:&lt;br /&gt;
&lt;br /&gt;
[https://sourceforge.net/projects/ofbiz-osgi/files/ ofbiz-osgi files]&lt;/div&gt;</summary>
		<author><name>Danutc</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=Ofbiz-osgi-prototype&amp;diff=4766</id>
		<title>Ofbiz-osgi-prototype</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=Ofbiz-osgi-prototype&amp;diff=4766"/>
		<updated>2009-10-27T22:29:04Z</updated>

		<summary type="html">&lt;p&gt;Danutc: /* Create a running configuration and run the platform */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page provides information about running ofbiz as an OSGi bundle; this prototype has been hand-crafted.&lt;br /&gt;
&lt;br /&gt;
== What is ofbiz-osgi prototype? ==&lt;br /&gt;
I worked with Raj to get a working ofbiz bundle. The ofbiz bundle and many dependencies were manually created so there is no build. Also the web applications do not work as Tomcat is not started. However the ofbiz services are available and can be tested.&lt;br /&gt;
&lt;br /&gt;
== Download the binaries ==&lt;br /&gt;
Please download the binaries from:&lt;br /&gt;
&lt;br /&gt;
[https://sourceforge.net/projects/ofbiz-osgi/files/ ofbiz-osgi files]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;ofbiz-osgi-prototype-bundles.zip&amp;lt;/b&amp;gt; (size is 38 MB)&lt;br /&gt;
&lt;br /&gt;
Unzip the archive in a folder; let's call it &amp;quot;base&amp;quot;. Under base folder there are 3 folders:&lt;br /&gt;
&lt;br /&gt;
* bundles (includes required dependencies packaged as OSGi bundles)&lt;br /&gt;
* com.viithiisys.ofbiz.service (OSGi bundle that activates the ofbiz bundle)&lt;br /&gt;
* org.apache.ofbiz (ofbiz as OSGi bundle)&lt;br /&gt;
&lt;br /&gt;
== Create the OSGi platform in eclipse ==&lt;br /&gt;
&lt;br /&gt;
* create a new eclipse workspace to start fresh&lt;br /&gt;
* go to Windows -&amp;gt; Preferences&lt;br /&gt;
** in the filter text box type &amp;quot;console&amp;quot;&lt;br /&gt;
** in the Run/Debug Console section un-check &amp;quot;Limit console output&amp;quot;&lt;br /&gt;
** clear the filter and select &amp;quot;Plug-in Development&amp;quot; -&amp;gt; &amp;quot;Target Platform&amp;quot;&lt;br /&gt;
** click Add button to add a new OSGi platform&lt;br /&gt;
** select Template -&amp;gt; Base RCP (Binary Only) then click Next; this option adds the core equinox OSGi components&lt;br /&gt;
** click Add button; select Directory; and select location &amp;quot;base/bundles&amp;quot;; click Finish; (this adds the ofbiz dependencies)&lt;br /&gt;
** click Finish to complete the platform creation&lt;br /&gt;
** select the new platform (by default is called &amp;quot;Base RCP (Binary Only)&amp;quot;); click Apply so it becomes the default platform&lt;br /&gt;
** you can click Reload button to make sure that it is all loaded and fresh&lt;br /&gt;
&lt;br /&gt;
== Add projects to eclipse ==&lt;br /&gt;
&lt;br /&gt;
* File -&amp;gt; Import -&amp;gt; General -&amp;gt; Existing Projects into Workspace&lt;br /&gt;
* select folder &amp;quot;com.viithiisys.ofbiz.service&amp;quot; under base and click Finish&lt;br /&gt;
* File -&amp;gt; Import -&amp;gt; General -&amp;gt; Existing Projects into Workspace&lt;br /&gt;
* select folder &amp;quot;org.apache.ofbiz&amp;quot; under base and click Finish&lt;br /&gt;
* Project -&amp;gt; Clean -&amp;gt; Clean All Projects&lt;br /&gt;
* there should be no errors after clen&lt;br /&gt;
* open the Problems window to check (Window -&amp;gt; Show View -&amp;gt; Other -&amp;gt; General -&amp;gt; Problems)&lt;br /&gt;
&lt;br /&gt;
== Create a running configuration and run the platform ==&lt;br /&gt;
&lt;br /&gt;
* point ofbiz to your database (check under folder base/org.apache.ofbiz)&lt;br /&gt;
* Run -&amp;gt; Run Configurations -&amp;gt; OSGi Framework -&amp;gt; New&lt;br /&gt;
* give it a name (ofbiz-osgi)&lt;br /&gt;
* click &amp;quot;Add Required Bundles&amp;quot; button&lt;br /&gt;
* click &amp;quot;Validate Bundles&amp;quot;; there is reported one problem with groovy missing javax.management; this error can be ignored&lt;br /&gt;
* select checkbox &amp;quot;Validate bundles automatically prior to launching&amp;quot;&lt;br /&gt;
* go to Arguments tab&lt;br /&gt;
* change VM arguments; add parameter:  -Dofbiz.home=....\base\org.apache.ofbiz so ofbiz finds its configuration&lt;br /&gt;
* click Apply button&lt;br /&gt;
* click Run button&lt;br /&gt;
&lt;br /&gt;
Watching the console you see a trace similar to:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;ofbiz-osgi-prototype-sample-log.log&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Please download ofbiz-osgi-prototype-sample-log.log from:&lt;br /&gt;
&lt;br /&gt;
[https://sourceforge.net/projects/ofbiz-osgi/files/ ofbiz-osgi files]&lt;/div&gt;</summary>
		<author><name>Danutc</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=Ofbiz-osgi-prototype&amp;diff=4765</id>
		<title>Ofbiz-osgi-prototype</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=Ofbiz-osgi-prototype&amp;diff=4765"/>
		<updated>2009-10-27T22:24:36Z</updated>

		<summary type="html">&lt;p&gt;Danutc: /* Download the binaries */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page provides information about running ofbiz as an OSGi bundle; this prototype has been hand-crafted.&lt;br /&gt;
&lt;br /&gt;
== What is ofbiz-osgi prototype? ==&lt;br /&gt;
I worked with Raj to get a working ofbiz bundle. The ofbiz bundle and many dependencies were manually created so there is no build. Also the web applications do not work as Tomcat is not started. However the ofbiz services are available and can be tested.&lt;br /&gt;
&lt;br /&gt;
== Download the binaries ==&lt;br /&gt;
Please download the binaries from:&lt;br /&gt;
&lt;br /&gt;
[https://sourceforge.net/projects/ofbiz-osgi/files/ ofbiz-osgi files]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;ofbiz-osgi-prototype-bundles.zip&amp;lt;/b&amp;gt; (size is 38 MB)&lt;br /&gt;
&lt;br /&gt;
Unzip the archive in a folder; let's call it &amp;quot;base&amp;quot;. Under base folder there are 3 folders:&lt;br /&gt;
&lt;br /&gt;
* bundles (includes required dependencies packaged as OSGi bundles)&lt;br /&gt;
* com.viithiisys.ofbiz.service (OSGi bundle that activates the ofbiz bundle)&lt;br /&gt;
* org.apache.ofbiz (ofbiz as OSGi bundle)&lt;br /&gt;
&lt;br /&gt;
== Create the OSGi platform in eclipse ==&lt;br /&gt;
&lt;br /&gt;
* create a new eclipse workspace to start fresh&lt;br /&gt;
* go to Windows -&amp;gt; Preferences&lt;br /&gt;
** in the filter text box type &amp;quot;console&amp;quot;&lt;br /&gt;
** in the Run/Debug Console section un-check &amp;quot;Limit console output&amp;quot;&lt;br /&gt;
** clear the filter and select &amp;quot;Plug-in Development&amp;quot; -&amp;gt; &amp;quot;Target Platform&amp;quot;&lt;br /&gt;
** click Add button to add a new OSGi platform&lt;br /&gt;
** select Template -&amp;gt; Base RCP (Binary Only) then click Next; this option adds the core equinox OSGi components&lt;br /&gt;
** click Add button; select Directory; and select location &amp;quot;base/bundles&amp;quot;; click Finish; (this adds the ofbiz dependencies)&lt;br /&gt;
** click Finish to complete the platform creation&lt;br /&gt;
** select the new platform (by default is called &amp;quot;Base RCP (Binary Only)&amp;quot;); click Apply so it becomes the default platform&lt;br /&gt;
** you can click Reload button to make sure that it is all loaded and fresh&lt;br /&gt;
&lt;br /&gt;
== Add projects to eclipse ==&lt;br /&gt;
&lt;br /&gt;
* File -&amp;gt; Import -&amp;gt; General -&amp;gt; Existing Projects into Workspace&lt;br /&gt;
* select folder &amp;quot;com.viithiisys.ofbiz.service&amp;quot; under base and click Finish&lt;br /&gt;
* File -&amp;gt; Import -&amp;gt; General -&amp;gt; Existing Projects into Workspace&lt;br /&gt;
* select folder &amp;quot;org.apache.ofbiz&amp;quot; under base and click Finish&lt;br /&gt;
* Project -&amp;gt; Clean -&amp;gt; Clean All Projects&lt;br /&gt;
* there should be no errors after clen&lt;br /&gt;
* open the Problems window to check (Window -&amp;gt; Show View -&amp;gt; Other -&amp;gt; General -&amp;gt; Problems)&lt;br /&gt;
&lt;br /&gt;
== Create a running configuration and run the platform ==&lt;br /&gt;
&lt;br /&gt;
* point ofbiz to your database (check under folder base/org.apache.ofbiz)&lt;br /&gt;
* Run -&amp;gt; Run Configurations -&amp;gt; OSGi Framework -&amp;gt; New&lt;br /&gt;
* give it a name (ofbiz-osgi)&lt;br /&gt;
* click &amp;quot;Add Required Bundles&amp;quot; button&lt;br /&gt;
* click &amp;quot;Validate Bundles&amp;quot;; there is reported one problem with groovy missing javax.management; this error can be ignored&lt;br /&gt;
* select checkbox &amp;quot;Validate bundles automatically prior to launching&amp;quot;&lt;br /&gt;
* go to Arguments tab&lt;br /&gt;
* change VM arguments; add parameter:  -Dofbiz.home=....\base\org.apache.ofbiz so ofbiz finds its configuration&lt;br /&gt;
* click Apply button&lt;br /&gt;
* click Run button&lt;br /&gt;
&lt;br /&gt;
Watching the console you see a trace similar to:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;ofbiz-osgi-proto.log&amp;lt;/b&amp;gt; (.log extension is not allowed for upload on wiki; please advice where to upload this file)&lt;/div&gt;</summary>
		<author><name>Danutc</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=Ofbiz-osgi-prototype&amp;diff=4751</id>
		<title>Ofbiz-osgi-prototype</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=Ofbiz-osgi-prototype&amp;diff=4751"/>
		<updated>2009-10-26T23:25:05Z</updated>

		<summary type="html">&lt;p&gt;Danutc: /* Create a running configuration and run the platform */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page provides information about running ofbiz as an OSGi bundle; this prototype has been hand-crafted.&lt;br /&gt;
&lt;br /&gt;
== What is ofbiz-osgi prototype? ==&lt;br /&gt;
I worked with Raj to get a working ofbiz bundle. The ofbiz bundle and many dependencies were manually created so there is no build. Also the web applications do not work as Tomcat is not started. However the ofbiz services are available and can be tested.&lt;br /&gt;
&lt;br /&gt;
== Download the binaries ==&lt;br /&gt;
Please download the binaries from this link:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;ofbiz-osgi-proto-wiki.zip&amp;lt;/b&amp;gt; (size is 38 MB; please advise where to upload)&lt;br /&gt;
&lt;br /&gt;
Unzip the archive in a folder; let's call it &amp;quot;base&amp;quot;. Under base folder there are 3 folders:&lt;br /&gt;
&lt;br /&gt;
* bundles (includes required dependencies packaged as OSGi bundles)&lt;br /&gt;
* com.viithiisys.ofbiz.service (OSGi bundle that activates the ofbiz bundle)&lt;br /&gt;
* org.apache.ofbiz (ofbiz as OSGi bundle)&lt;br /&gt;
&lt;br /&gt;
== Create the OSGi platform in eclipse ==&lt;br /&gt;
&lt;br /&gt;
* create a new eclipse workspace to start fresh&lt;br /&gt;
* go to Windows -&amp;gt; Preferences&lt;br /&gt;
** in the filter text box type &amp;quot;console&amp;quot;&lt;br /&gt;
** in the Run/Debug Console section un-check &amp;quot;Limit console output&amp;quot;&lt;br /&gt;
** clear the filter and select &amp;quot;Plug-in Development&amp;quot; -&amp;gt; &amp;quot;Target Platform&amp;quot;&lt;br /&gt;
** click Add button to add a new OSGi platform&lt;br /&gt;
** select Template -&amp;gt; Base RCP (Binary Only) then click Next; this option adds the core equinox OSGi components&lt;br /&gt;
** click Add button; select Directory; and select location &amp;quot;base/bundles&amp;quot;; click Finish; (this adds the ofbiz dependencies)&lt;br /&gt;
** click Finish to complete the platform creation&lt;br /&gt;
** select the new platform (by default is called &amp;quot;Base RCP (Binary Only)&amp;quot;); click Apply so it becomes the default platform&lt;br /&gt;
** you can click Reload button to make sure that it is all loaded and fresh&lt;br /&gt;
&lt;br /&gt;
== Add projects to eclipse ==&lt;br /&gt;
&lt;br /&gt;
* File -&amp;gt; Import -&amp;gt; General -&amp;gt; Existing Projects into Workspace&lt;br /&gt;
* select folder &amp;quot;com.viithiisys.ofbiz.service&amp;quot; under base and click Finish&lt;br /&gt;
* File -&amp;gt; Import -&amp;gt; General -&amp;gt; Existing Projects into Workspace&lt;br /&gt;
* select folder &amp;quot;org.apache.ofbiz&amp;quot; under base and click Finish&lt;br /&gt;
* Project -&amp;gt; Clean -&amp;gt; Clean All Projects&lt;br /&gt;
* there should be no errors after clen&lt;br /&gt;
* open the Problems window to check (Window -&amp;gt; Show View -&amp;gt; Other -&amp;gt; General -&amp;gt; Problems)&lt;br /&gt;
&lt;br /&gt;
== Create a running configuration and run the platform ==&lt;br /&gt;
&lt;br /&gt;
* point ofbiz to your database (check under folder base/org.apache.ofbiz)&lt;br /&gt;
* Run -&amp;gt; Run Configurations -&amp;gt; OSGi Framework -&amp;gt; New&lt;br /&gt;
* give it a name (ofbiz-osgi)&lt;br /&gt;
* click &amp;quot;Add Required Bundles&amp;quot; button&lt;br /&gt;
* click &amp;quot;Validate Bundles&amp;quot;; there is reported one problem with groovy missing javax.management; this error can be ignored&lt;br /&gt;
* select checkbox &amp;quot;Validate bundles automatically prior to launching&amp;quot;&lt;br /&gt;
* go to Arguments tab&lt;br /&gt;
* change VM arguments; add parameter:  -Dofbiz.home=....\base\org.apache.ofbiz so ofbiz finds its configuration&lt;br /&gt;
* click Apply button&lt;br /&gt;
* click Run button&lt;br /&gt;
&lt;br /&gt;
Watching the console you see a trace similar to:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;ofbiz-osgi-proto.log&amp;lt;/b&amp;gt; (.log extension is not allowed for upload on wiki; please advice where to upload this file)&lt;/div&gt;</summary>
		<author><name>Danutc</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=Ofbiz-osgi-prototype&amp;diff=4750</id>
		<title>Ofbiz-osgi-prototype</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=Ofbiz-osgi-prototype&amp;diff=4750"/>
		<updated>2009-10-26T23:23:29Z</updated>

		<summary type="html">&lt;p&gt;Danutc: /* Download the binaries */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page provides information about running ofbiz as an OSGi bundle; this prototype has been hand-crafted.&lt;br /&gt;
&lt;br /&gt;
== What is ofbiz-osgi prototype? ==&lt;br /&gt;
I worked with Raj to get a working ofbiz bundle. The ofbiz bundle and many dependencies were manually created so there is no build. Also the web applications do not work as Tomcat is not started. However the ofbiz services are available and can be tested.&lt;br /&gt;
&lt;br /&gt;
== Download the binaries ==&lt;br /&gt;
Please download the binaries from this link:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;ofbiz-osgi-proto-wiki.zip&amp;lt;/b&amp;gt; (size is 38 MB; please advise where to upload)&lt;br /&gt;
&lt;br /&gt;
Unzip the archive in a folder; let's call it &amp;quot;base&amp;quot;. Under base folder there are 3 folders:&lt;br /&gt;
&lt;br /&gt;
* bundles (includes required dependencies packaged as OSGi bundles)&lt;br /&gt;
* com.viithiisys.ofbiz.service (OSGi bundle that activates the ofbiz bundle)&lt;br /&gt;
* org.apache.ofbiz (ofbiz as OSGi bundle)&lt;br /&gt;
&lt;br /&gt;
== Create the OSGi platform in eclipse ==&lt;br /&gt;
&lt;br /&gt;
* create a new eclipse workspace to start fresh&lt;br /&gt;
* go to Windows -&amp;gt; Preferences&lt;br /&gt;
** in the filter text box type &amp;quot;console&amp;quot;&lt;br /&gt;
** in the Run/Debug Console section un-check &amp;quot;Limit console output&amp;quot;&lt;br /&gt;
** clear the filter and select &amp;quot;Plug-in Development&amp;quot; -&amp;gt; &amp;quot;Target Platform&amp;quot;&lt;br /&gt;
** click Add button to add a new OSGi platform&lt;br /&gt;
** select Template -&amp;gt; Base RCP (Binary Only) then click Next; this option adds the core equinox OSGi components&lt;br /&gt;
** click Add button; select Directory; and select location &amp;quot;base/bundles&amp;quot;; click Finish; (this adds the ofbiz dependencies)&lt;br /&gt;
** click Finish to complete the platform creation&lt;br /&gt;
** select the new platform (by default is called &amp;quot;Base RCP (Binary Only)&amp;quot;); click Apply so it becomes the default platform&lt;br /&gt;
** you can click Reload button to make sure that it is all loaded and fresh&lt;br /&gt;
&lt;br /&gt;
== Add projects to eclipse ==&lt;br /&gt;
&lt;br /&gt;
* File -&amp;gt; Import -&amp;gt; General -&amp;gt; Existing Projects into Workspace&lt;br /&gt;
* select folder &amp;quot;com.viithiisys.ofbiz.service&amp;quot; under base and click Finish&lt;br /&gt;
* File -&amp;gt; Import -&amp;gt; General -&amp;gt; Existing Projects into Workspace&lt;br /&gt;
* select folder &amp;quot;org.apache.ofbiz&amp;quot; under base and click Finish&lt;br /&gt;
* Project -&amp;gt; Clean -&amp;gt; Clean All Projects&lt;br /&gt;
* there should be no errors after clen&lt;br /&gt;
* open the Problems window to check (Window -&amp;gt; Show View -&amp;gt; Other -&amp;gt; General -&amp;gt; Problems)&lt;br /&gt;
&lt;br /&gt;
== Create a running configuration and run the platform ==&lt;br /&gt;
&lt;br /&gt;
* point ofbiz to your database (check under folder base/org.apache.ofbiz)&lt;br /&gt;
* Run -&amp;gt; Run Configurations -&amp;gt; OSGi Framework -&amp;gt; New&lt;br /&gt;
* give it a name (ofbiz-osgi)&lt;br /&gt;
* click &amp;quot;Add Required Bundles&amp;quot; button&lt;br /&gt;
* click &amp;quot;Validate Bundles&amp;quot;; there is reported one problem with groovy missing javax.management; this error can be ignored&lt;br /&gt;
* select checkbox &amp;quot;Validate bundles automatically prior to launching&amp;quot;&lt;br /&gt;
* go to Arguments tab&lt;br /&gt;
* change VM arguments; add parameter:  -Dofbiz.home=....\base\org.apache.ofbiz so ofbiz finds its configuration&lt;br /&gt;
* click Apply button&lt;br /&gt;
* click Run button&lt;br /&gt;
&lt;br /&gt;
Watching the console you see a trace similar to:&lt;br /&gt;
&lt;br /&gt;
ofbiz-osgi-proto.log&lt;/div&gt;</summary>
		<author><name>Danutc</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=Ofbiz-osgi-prototype&amp;diff=4734</id>
		<title>Ofbiz-osgi-prototype</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=Ofbiz-osgi-prototype&amp;diff=4734"/>
		<updated>2009-10-26T07:49:23Z</updated>

		<summary type="html">&lt;p&gt;Danutc: /* Create the OSGi platform in eclipse */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page provides information about running ofbiz as an OSGi bundle; this prototype has been hand-crafted.&lt;br /&gt;
&lt;br /&gt;
== What is ofbiz-osgi prototype? ==&lt;br /&gt;
I worked with Raj to get a working ofbiz bundle. The ofbiz bundle and many dependencies were manually created so there is no build. Also the web applications do not work as Tomcat is not started. However the ofbiz services are available and can be tested.&lt;br /&gt;
&lt;br /&gt;
== Download the binaries ==&lt;br /&gt;
Please download the binaries from this link:&lt;br /&gt;
&lt;br /&gt;
ofbiz-osgi-proto-wiki.zip&lt;br /&gt;
&lt;br /&gt;
Unzip the archive in a folder; let's call it &amp;quot;base&amp;quot;. Under base folder there are 3 folders:&lt;br /&gt;
&lt;br /&gt;
* bundles (includes required dependencies packaged as OSGi bundles)&lt;br /&gt;
* com.viithiisys.ofbiz.service (OSGi bundle that activates the ofbiz bundle)&lt;br /&gt;
* org.apache.ofbiz (ofbiz as OSGi bundle)&lt;br /&gt;
&lt;br /&gt;
== Create the OSGi platform in eclipse ==&lt;br /&gt;
&lt;br /&gt;
* create a new eclipse workspace to start fresh&lt;br /&gt;
* go to Windows -&amp;gt; Preferences&lt;br /&gt;
** in the filter text box type &amp;quot;console&amp;quot;&lt;br /&gt;
** in the Run/Debug Console section un-check &amp;quot;Limit console output&amp;quot;&lt;br /&gt;
** clear the filter and select &amp;quot;Plug-in Development&amp;quot; -&amp;gt; &amp;quot;Target Platform&amp;quot;&lt;br /&gt;
** click Add button to add a new OSGi platform&lt;br /&gt;
** select Template -&amp;gt; Base RCP (Binary Only) then click Next; this option adds the core equinox OSGi components&lt;br /&gt;
** click Add button; select Directory; and select location &amp;quot;base/bundles&amp;quot;; click Finish; (this adds the ofbiz dependencies)&lt;br /&gt;
** click Finish to complete the platform creation&lt;br /&gt;
** select the new platform (by default is called &amp;quot;Base RCP (Binary Only)&amp;quot;); click Apply so it becomes the default platform&lt;br /&gt;
** you can click Reload button to make sure that it is all loaded and fresh&lt;br /&gt;
&lt;br /&gt;
== Add projects to eclipse ==&lt;br /&gt;
&lt;br /&gt;
* File -&amp;gt; Import -&amp;gt; General -&amp;gt; Existing Projects into Workspace&lt;br /&gt;
* select folder &amp;quot;com.viithiisys.ofbiz.service&amp;quot; under base and click Finish&lt;br /&gt;
* File -&amp;gt; Import -&amp;gt; General -&amp;gt; Existing Projects into Workspace&lt;br /&gt;
* select folder &amp;quot;org.apache.ofbiz&amp;quot; under base and click Finish&lt;br /&gt;
* Project -&amp;gt; Clean -&amp;gt; Clean All Projects&lt;br /&gt;
* there should be no errors after clen&lt;br /&gt;
* open the Problems window to check (Window -&amp;gt; Show View -&amp;gt; Other -&amp;gt; General -&amp;gt; Problems)&lt;br /&gt;
&lt;br /&gt;
== Create a running configuration and run the platform ==&lt;br /&gt;
&lt;br /&gt;
* point ofbiz to your database (check under folder base/org.apache.ofbiz)&lt;br /&gt;
* Run -&amp;gt; Run Configurations -&amp;gt; OSGi Framework -&amp;gt; New&lt;br /&gt;
* give it a name (ofbiz-osgi)&lt;br /&gt;
* click &amp;quot;Add Required Bundles&amp;quot; button&lt;br /&gt;
* click &amp;quot;Validate Bundles&amp;quot;; there is reported one problem with groovy missing javax.management; this error can be ignored&lt;br /&gt;
* select checkbox &amp;quot;Validate bundles automatically prior to launching&amp;quot;&lt;br /&gt;
* go to Arguments tab&lt;br /&gt;
* change VM arguments; add parameter:  -Dofbiz.home=....\base\org.apache.ofbiz so ofbiz finds its configuration&lt;br /&gt;
* click Apply button&lt;br /&gt;
* click Run button&lt;br /&gt;
&lt;br /&gt;
Watching the console you see a trace similar to:&lt;br /&gt;
&lt;br /&gt;
ofbiz-osgi-proto.log&lt;/div&gt;</summary>
		<author><name>Danutc</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=Ofbiz-osgi-prototype&amp;diff=4733</id>
		<title>Ofbiz-osgi-prototype</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=Ofbiz-osgi-prototype&amp;diff=4733"/>
		<updated>2009-10-26T07:06:47Z</updated>

		<summary type="html">&lt;p&gt;Danutc: /* What is opentaps-osgi? */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page provides information about running ofbiz as an OSGi bundle; this prototype has been hand-crafted.&lt;br /&gt;
&lt;br /&gt;
== What is ofbiz-osgi prototype? ==&lt;br /&gt;
I worked with Raj to get a working ofbiz bundle. The ofbiz bundle and many dependencies were manually created so there is no build. Also the web applications do not work as Tomcat is not started. However the ofbiz services are available and can be tested.&lt;br /&gt;
&lt;br /&gt;
== Download the binaries ==&lt;br /&gt;
Please download the binaries from this link:&lt;br /&gt;
&lt;br /&gt;
ofbiz-osgi-proto-wiki.zip&lt;br /&gt;
&lt;br /&gt;
Unzip the archive in a folder; let's call it &amp;quot;base&amp;quot;. Under base folder there are 3 folders:&lt;br /&gt;
&lt;br /&gt;
* bundles (includes required dependencies packaged as OSGi bundles)&lt;br /&gt;
* com.viithiisys.ofbiz.service (OSGi bundle that activates the ofbiz bundle)&lt;br /&gt;
* org.apache.ofbiz (ofbiz as OSGi bundle)&lt;br /&gt;
&lt;br /&gt;
== Create the OSGi platform in eclipse ==&lt;br /&gt;
&lt;br /&gt;
* create a new eclipse workspace to start fresh&lt;br /&gt;
* go to Windows -&amp;gt; Preferences&lt;br /&gt;
** in the filter text box type &amp;quot;console&amp;quot;&lt;br /&gt;
** in the Run/Debug Console section un-check &amp;quot;Limit console output&amp;quot;&lt;br /&gt;
** clear the filter and select &amp;quot;Plug-in Development&amp;quot; -&amp;gt; &amp;quot;Target Platform&amp;quot;&lt;br /&gt;
** click Add button to add a new OSGi platform&lt;br /&gt;
** select Template -&amp;gt; Base RCP (Binary Only) then click Next; this option adds the core equinox OSGi components&lt;br /&gt;
** click Add button; select Directory; and select location &amp;quot;base/bundles&amp;quot;; click Finis; (this adds the ofbiz dependencies)&lt;br /&gt;
** click Finish to complete the platform creation&lt;br /&gt;
** select the new platform (by default is called &amp;quot;Base RCP (Binary Only)&amp;quot;); click Apply so it becomes the default platform&lt;br /&gt;
** you can click Reload button to make sure that it is all loaded and fresh&lt;br /&gt;
&lt;br /&gt;
== Add projects to eclipse ==&lt;br /&gt;
&lt;br /&gt;
* File -&amp;gt; Import -&amp;gt; General -&amp;gt; Existing Projects into Workspace&lt;br /&gt;
* select folder &amp;quot;com.viithiisys.ofbiz.service&amp;quot; under base and click Finish&lt;br /&gt;
* File -&amp;gt; Import -&amp;gt; General -&amp;gt; Existing Projects into Workspace&lt;br /&gt;
* select folder &amp;quot;org.apache.ofbiz&amp;quot; under base and click Finish&lt;br /&gt;
* Project -&amp;gt; Clean -&amp;gt; Clean All Projects&lt;br /&gt;
* there should be no errors after clen&lt;br /&gt;
* open the Problems window to check (Window -&amp;gt; Show View -&amp;gt; Other -&amp;gt; General -&amp;gt; Problems)&lt;br /&gt;
&lt;br /&gt;
== Create a running configuration and run the platform ==&lt;br /&gt;
&lt;br /&gt;
* point ofbiz to your database (check under folder base/org.apache.ofbiz)&lt;br /&gt;
* Run -&amp;gt; Run Configurations -&amp;gt; OSGi Framework -&amp;gt; New&lt;br /&gt;
* give it a name (ofbiz-osgi)&lt;br /&gt;
* click &amp;quot;Add Required Bundles&amp;quot; button&lt;br /&gt;
* click &amp;quot;Validate Bundles&amp;quot;; there is reported one problem with groovy missing javax.management; this error can be ignored&lt;br /&gt;
* select checkbox &amp;quot;Validate bundles automatically prior to launching&amp;quot;&lt;br /&gt;
* go to Arguments tab&lt;br /&gt;
* change VM arguments; add parameter:  -Dofbiz.home=....\base\org.apache.ofbiz so ofbiz finds its configuration&lt;br /&gt;
* click Apply button&lt;br /&gt;
* click Run button&lt;br /&gt;
&lt;br /&gt;
Watching the console you see a trace similar to:&lt;br /&gt;
&lt;br /&gt;
ofbiz-osgi-proto.log&lt;/div&gt;</summary>
		<author><name>Danutc</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=Ofbiz-osgi-prototype&amp;diff=4732</id>
		<title>Ofbiz-osgi-prototype</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=Ofbiz-osgi-prototype&amp;diff=4732"/>
		<updated>2009-10-26T07:05:47Z</updated>

		<summary type="html">&lt;p&gt;Danutc: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page provides information about running ofbiz as an OSGi bundle; this prototype has been hand-crafted.&lt;br /&gt;
&lt;br /&gt;
== What is opentaps-osgi? ==&lt;br /&gt;
I worked with Raj to get a working ofbiz bundle. The ofbiz bundle and many dependencies were manually created so there is no build. Also the web applications do not work as Tomcat is not started. However the ofbiz services are available and can be tested.&lt;br /&gt;
&lt;br /&gt;
== Download the binaries ==&lt;br /&gt;
Please download the binaries from this link:&lt;br /&gt;
&lt;br /&gt;
ofbiz-osgi-proto-wiki.zip&lt;br /&gt;
&lt;br /&gt;
Unzip the archive in a folder; let's call it &amp;quot;base&amp;quot;. Under base folder there are 3 folders:&lt;br /&gt;
&lt;br /&gt;
* bundles (includes required dependencies packaged as OSGi bundles)&lt;br /&gt;
* com.viithiisys.ofbiz.service (OSGi bundle that activates the ofbiz bundle)&lt;br /&gt;
* org.apache.ofbiz (ofbiz as OSGi bundle)&lt;br /&gt;
&lt;br /&gt;
== Create the OSGi platform in eclipse ==&lt;br /&gt;
&lt;br /&gt;
* create a new eclipse workspace to start fresh&lt;br /&gt;
* go to Windows -&amp;gt; Preferences&lt;br /&gt;
** in the filter text box type &amp;quot;console&amp;quot;&lt;br /&gt;
** in the Run/Debug Console section un-check &amp;quot;Limit console output&amp;quot;&lt;br /&gt;
** clear the filter and select &amp;quot;Plug-in Development&amp;quot; -&amp;gt; &amp;quot;Target Platform&amp;quot;&lt;br /&gt;
** click Add button to add a new OSGi platform&lt;br /&gt;
** select Template -&amp;gt; Base RCP (Binary Only) then click Next; this option adds the core equinox OSGi components&lt;br /&gt;
** click Add button; select Directory; and select location &amp;quot;base/bundles&amp;quot;; click Finis; (this adds the ofbiz dependencies)&lt;br /&gt;
** click Finish to complete the platform creation&lt;br /&gt;
** select the new platform (by default is called &amp;quot;Base RCP (Binary Only)&amp;quot;); click Apply so it becomes the default platform&lt;br /&gt;
** you can click Reload button to make sure that it is all loaded and fresh&lt;br /&gt;
&lt;br /&gt;
== Add projects to eclipse ==&lt;br /&gt;
&lt;br /&gt;
* File -&amp;gt; Import -&amp;gt; General -&amp;gt; Existing Projects into Workspace&lt;br /&gt;
* select folder &amp;quot;com.viithiisys.ofbiz.service&amp;quot; under base and click Finish&lt;br /&gt;
* File -&amp;gt; Import -&amp;gt; General -&amp;gt; Existing Projects into Workspace&lt;br /&gt;
* select folder &amp;quot;org.apache.ofbiz&amp;quot; under base and click Finish&lt;br /&gt;
* Project -&amp;gt; Clean -&amp;gt; Clean All Projects&lt;br /&gt;
* there should be no errors after clen&lt;br /&gt;
* open the Problems window to check (Window -&amp;gt; Show View -&amp;gt; Other -&amp;gt; General -&amp;gt; Problems)&lt;br /&gt;
&lt;br /&gt;
== Create a running configuration and run the platform ==&lt;br /&gt;
&lt;br /&gt;
* point ofbiz to your database (check under folder base/org.apache.ofbiz)&lt;br /&gt;
* Run -&amp;gt; Run Configurations -&amp;gt; OSGi Framework -&amp;gt; New&lt;br /&gt;
* give it a name (ofbiz-osgi)&lt;br /&gt;
* click &amp;quot;Add Required Bundles&amp;quot; button&lt;br /&gt;
* click &amp;quot;Validate Bundles&amp;quot;; there is reported one problem with groovy missing javax.management; this error can be ignored&lt;br /&gt;
* select checkbox &amp;quot;Validate bundles automatically prior to launching&amp;quot;&lt;br /&gt;
* go to Arguments tab&lt;br /&gt;
* change VM arguments; add parameter:  -Dofbiz.home=....\base\org.apache.ofbiz so ofbiz finds its configuration&lt;br /&gt;
* click Apply button&lt;br /&gt;
* click Run button&lt;br /&gt;
&lt;br /&gt;
Watching the console you see a trace similar to:&lt;br /&gt;
&lt;br /&gt;
ofbiz-osgi-proto.log&lt;/div&gt;</summary>
		<author><name>Danutc</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=Ofbiz-osgi-prototype&amp;diff=4731</id>
		<title>Ofbiz-osgi-prototype</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=Ofbiz-osgi-prototype&amp;diff=4731"/>
		<updated>2009-10-26T06:58:02Z</updated>

		<summary type="html">&lt;p&gt;Danutc: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page provides information about running ofbiz as an OSGi bundle; this prototype has been hand-crafted.&lt;br /&gt;
&lt;br /&gt;
== What is opentaps-osgi? ==&lt;br /&gt;
I worked with Raj to get a working ofbiz bundle. The ofbiz bundle and many dependencies were manually created so there is no build. Also the web applications do not work as Tomcat is not started. However the ofbiz services are available and can be tested.&lt;br /&gt;
&lt;br /&gt;
== Download the binaries ==&lt;br /&gt;
Please download the binaries from this link:&lt;br /&gt;
&lt;br /&gt;
ofbiz-osgi-proto-wiki.zip&lt;br /&gt;
&lt;br /&gt;
Unzip the archive in a folder; let's call it &amp;quot;base&amp;quot;. Under base folder there are 3 folders:&lt;br /&gt;
&lt;br /&gt;
* bundles (includes required dependencies packaged as OSGi bundles)&lt;br /&gt;
* com.viithiisys.ofbiz.service (OSGi bundle that activates the ofbiz bundle)&lt;br /&gt;
* org.apache.ofbiz (ofbiz as OSGi bundle)&lt;br /&gt;
&lt;br /&gt;
== Create the OSGi platform in eclipse ==&lt;br /&gt;
&lt;br /&gt;
* create a new eclipse workspace to start fresh&lt;br /&gt;
* go to Windows -&amp;gt; Preferences&lt;br /&gt;
** in the filter text box type &amp;quot;console&amp;quot;&lt;br /&gt;
** in the Run/Debug Console section un-check &amp;quot;Limit console output&amp;quot;&lt;br /&gt;
** clear the filter and select &amp;quot;Plug-in Development&amp;quot; -&amp;gt; &amp;quot;Target Platform&amp;quot;&lt;br /&gt;
** click Add button to add a new OSGi platform&lt;br /&gt;
** select Template -&amp;gt; Base RCP (Binary Only) then click Next; this option adds the core equinox OSGi components&lt;br /&gt;
** click Add button; select Directory; and select location &amp;quot;base/bundles&amp;quot;; click Finis; (this adds the ofbiz dependencies)&lt;br /&gt;
** click Finish to complete the platform creation&lt;br /&gt;
** select the new platform (by default is called &amp;quot;Base RCP (Binary Only)&amp;quot;); click Apply so it becomes the default platform&lt;br /&gt;
** you can click Reload button to make sure that it is all loaded and fresh&lt;br /&gt;
&lt;br /&gt;
== Add projects to eclipse ==&lt;br /&gt;
&lt;br /&gt;
* File -&amp;gt; Import -&amp;gt; General -&amp;gt; Existing Projects into Workspace&lt;br /&gt;
* select folder &amp;quot;com.viithiisys.ofbiz.service&amp;quot; under base and click Finish&lt;br /&gt;
* File -&amp;gt; Import -&amp;gt; General -&amp;gt; Existing Projects into Workspace&lt;br /&gt;
* select folder &amp;quot;org.apache.ofbiz&amp;quot; under base and click Finish&lt;br /&gt;
* Project -&amp;gt; Clean -&amp;gt; Clean All Projects&lt;br /&gt;
* there should be no errors after clen&lt;br /&gt;
* open the Problems window to check (Window -&amp;gt; Show View -&amp;gt; Other -&amp;gt; General -&amp;gt; Problems)&lt;br /&gt;
&lt;br /&gt;
== Create a running configuration and run the platform ==&lt;br /&gt;
&lt;br /&gt;
* Run -&amp;gt; Run Configurations -&amp;gt; OSGi Framework -&amp;gt; New&lt;br /&gt;
* give it a name (ofbiz-osgi)&lt;br /&gt;
* click &amp;quot;Add Required Bundles&amp;quot; button&lt;br /&gt;
* click &amp;quot;Validate Bundles&amp;quot;; there is reported one problem with groovy missing javax.management; this error can be ignored&lt;br /&gt;
* select checkbox &amp;quot;Validate bundles automatically prior to launching&amp;quot;&lt;br /&gt;
* go to Arguments tab&lt;br /&gt;
* to VM arguments add the path to &lt;br /&gt;
* click Apply button&lt;br /&gt;
* click Run button&lt;/div&gt;</summary>
		<author><name>Danutc</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=Ofbiz-osgi-prototype&amp;diff=4730</id>
		<title>Ofbiz-osgi-prototype</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=Ofbiz-osgi-prototype&amp;diff=4730"/>
		<updated>2009-10-26T06:24:22Z</updated>

		<summary type="html">&lt;p&gt;Danutc: /* What is opentaps-osgi? */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page provides information about running ofbiz as an OSGi bundle; this prototype has been hand-crafted.&lt;br /&gt;
&lt;br /&gt;
== What is opentaps-osgi? ==&lt;br /&gt;
I worked with Raj to get a working ofbiz bundle. The ofbiz bundle and many dependencies were manually created so there is no build. Also the web applications do not work as Tomcat is not started. However the ofbiz services are available and can be tested.&lt;br /&gt;
&lt;br /&gt;
== Download the binaries ==&lt;br /&gt;
Please download the binaries from this link:&lt;br /&gt;
&lt;br /&gt;
ofbiz-osgi-proto-wiki.zip&lt;br /&gt;
&lt;br /&gt;
Unzip the archive in a folder; let's call it &amp;quot;base&amp;quot;. Under base folder there are 3 folders:&lt;br /&gt;
&lt;br /&gt;
* bundles (includes required dependencies packaged as OSGi bundles)&lt;br /&gt;
* com.viithiisys.ofbiz.service (OSGi bundle that activates the ofbiz bundle)&lt;br /&gt;
* org.apache.ofbiz (ofbiz as OSGi bundle)&lt;/div&gt;</summary>
		<author><name>Danutc</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=Ofbiz-osgi-prototype&amp;diff=4729</id>
		<title>Ofbiz-osgi-prototype</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=Ofbiz-osgi-prototype&amp;diff=4729"/>
		<updated>2009-10-26T06:20:27Z</updated>

		<summary type="html">&lt;p&gt;Danutc: Protected &amp;quot;Ofbiz-osgi-prototype&amp;quot;: Sysop page [edit=sysop:move=sysop]&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page provides information about running ofbiz as an OSGi bundle; this prototype has been hand-crafted.&lt;br /&gt;
&lt;br /&gt;
== What is opentaps-osgi? ==&lt;br /&gt;
I worked with Raj to get a working ofbiz bundle. The ofbiz bundle and many dependencies were manually created so there is not build. Also the web applications do not work as Tomcat is not started. However the ofbiz services are available and can be tested.&lt;br /&gt;
&lt;br /&gt;
== Download the binaries ==&lt;br /&gt;
Please download the binaries from this link:&lt;br /&gt;
&lt;br /&gt;
ofbiz-osgi-proto-wiki.zip&lt;br /&gt;
&lt;br /&gt;
Unzip the archive in a folder; let's call it &amp;quot;base&amp;quot;. Under base folder there are 3 folders:&lt;br /&gt;
&lt;br /&gt;
* bundles (includes required dependencies packaged as OSGi bundles)&lt;br /&gt;
* com.viithiisys.ofbiz.service (OSGi bundle that activates the ofbiz bundle)&lt;br /&gt;
* org.apache.ofbiz (ofbiz as OSGi bundle)&lt;/div&gt;</summary>
		<author><name>Danutc</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=Ofbiz-osgi-prototype&amp;diff=4728</id>
		<title>Ofbiz-osgi-prototype</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=Ofbiz-osgi-prototype&amp;diff=4728"/>
		<updated>2009-10-26T06:20:26Z</updated>

		<summary type="html">&lt;p&gt;Danutc: New page: This page provides information about running ofbiz as an OSGi bundle; this prototype has been hand-crafted.  == What is opentaps-osgi? == I worked with Raj to get a working ofbiz bundle. T...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page provides information about running ofbiz as an OSGi bundle; this prototype has been hand-crafted.&lt;br /&gt;
&lt;br /&gt;
== What is opentaps-osgi? ==&lt;br /&gt;
I worked with Raj to get a working ofbiz bundle. The ofbiz bundle and many dependencies were manually created so there is not build. Also the web applications do not work as Tomcat is not started. However the ofbiz services are available and can be tested.&lt;br /&gt;
&lt;br /&gt;
== Download the binaries ==&lt;br /&gt;
Please download the binaries from this link:&lt;br /&gt;
&lt;br /&gt;
ofbiz-osgi-proto-wiki.zip&lt;br /&gt;
&lt;br /&gt;
Unzip the archive in a folder; let's call it &amp;quot;base&amp;quot;. Under base folder there are 3 folders:&lt;br /&gt;
&lt;br /&gt;
* bundles (includes required dependencies packaged as OSGi bundles)&lt;br /&gt;
* com.viithiisys.ofbiz.service (OSGi bundle that activates the ofbiz bundle)&lt;br /&gt;
* org.apache.ofbiz (ofbiz as OSGi bundle)&lt;/div&gt;</summary>
		<author><name>Danutc</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=User_talk:Danutc&amp;diff=4727</id>
		<title>User talk:Danutc</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=User_talk:Danutc&amp;diff=4727"/>
		<updated>2009-10-26T05:51:43Z</updated>

		<summary type="html">&lt;p&gt;Danutc: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* [[BPM Integration]]&lt;br /&gt;
* [[BPM - Getting Started]]&lt;br /&gt;
* [[jBPM - Opentaps 1.x Integration Prototype]]&lt;br /&gt;
* [[Magento 1.x - Opentaps 1.x Integration Prototype]]&lt;br /&gt;
* [[opentaps-osgi]]&lt;br /&gt;
* [[ofbiz-osgi-prototype]]&lt;br /&gt;
* [[danc - temp]]&lt;/div&gt;</summary>
		<author><name>Danutc</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=Opentaps-osgi&amp;diff=4639</id>
		<title>Opentaps-osgi</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=Opentaps-osgi&amp;diff=4639"/>
		<updated>2009-10-18T21:34:09Z</updated>

		<summary type="html">&lt;p&gt;Danutc: /* Get Started Quickly */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page provides information about projects at:&lt;br /&gt;
&lt;br /&gt;
svn://svn.opentaps.org/opentaps/branches/danutc-2.0/org.opentaps.osgi&lt;br /&gt;
&lt;br /&gt;
== What is opentaps-osgi? ==&lt;br /&gt;
&lt;br /&gt;
We aim to migrate ofbiz and opentaps to a more modern architecture based on:&lt;br /&gt;
&lt;br /&gt;
* OSGi&lt;br /&gt;
* BPM&lt;br /&gt;
* ESB&lt;br /&gt;
* SCA&lt;br /&gt;
&lt;br /&gt;
It appears that many open source products have been migrated to OSGi. To take full advantage of these products would be desirable to have opentaps and ofbiz restructured as OSGi modules.&lt;br /&gt;
&lt;br /&gt;
Also migration to OSGi enables better architecture and more agile development. I make these statements based on information available on Internet.&lt;br /&gt;
&lt;br /&gt;
In current build the following features are deployed and illustrated:&lt;br /&gt;
&lt;br /&gt;
* Eclipse Equinox OSGi&lt;br /&gt;
* Spring DM (Dynamic Modules for OSGi development) and Spring Core&lt;br /&gt;
* Tomcat&lt;br /&gt;
* full maven build&lt;br /&gt;
* Eclipse PDE development&lt;br /&gt;
* OSGi Platform maven project build&lt;br /&gt;
* OSGi Extension Projects: log4j configuration, catalina configuration, catalina.start.osgi configuration&lt;br /&gt;
* Sample OSGi Service using Spring DM&lt;br /&gt;
* Sample Web Application that uses the service above&lt;br /&gt;
&lt;br /&gt;
== Get Started Quickly ==&lt;br /&gt;
This quick start section is based on ( http://springosgi.googlepages.com/ ) article.&lt;br /&gt;
&lt;br /&gt;
To get you started please take the following steps:&lt;br /&gt;
&lt;br /&gt;
=== Get your environment ready ===&lt;br /&gt;
I use the following tools:&lt;br /&gt;
&lt;br /&gt;
* eclipse JEE 3.5 Galileo&lt;br /&gt;
* subclipse SVN eclipse plugin that works with m2eclipse maven eclipse plugin ( http://subclipse.tigris.org/update_1.6.x )&lt;br /&gt;
* m2eclipse maven eclipse plugin ( http://m2eclipse.sonatype.org/update/ )&lt;br /&gt;
* java sdk 1.6.0_14&lt;br /&gt;
&lt;br /&gt;
=== Checkout the code ===&lt;br /&gt;
&lt;br /&gt;
* start eclipse and create a new workspace&lt;br /&gt;
* open SVN Repository Exploring perspective&lt;br /&gt;
* Add SVN Repository: svn://svn.opentaps.org/opentaps&lt;br /&gt;
* File -&amp;gt; Import -&amp;gt; Maven -&amp;gt; Checkout as Maven project from SCM&amp;lt;br /&amp;gt;&lt;br /&gt;
- SCM URL: svn&amp;lt;br /&amp;gt;&lt;br /&gt;
- svn://svn.opentaps.org/opentaps/branches/danutc-2.0/org.opentaps.osgi/trunk&lt;br /&gt;
* click Finish button&lt;br /&gt;
* after the import is finished switch to JEE perspective; you should see the following projects:&lt;br /&gt;
apps&amp;lt;br /&amp;gt;&lt;br /&gt;
catalina.config&amp;lt;br /&amp;gt;&lt;br /&gt;
catalina.start.osgi.config&amp;lt;br /&amp;gt;&lt;br /&gt;
lib&amp;lt;br /&amp;gt;&lt;br /&gt;
log4j.config&amp;lt;br /&amp;gt;&lt;br /&gt;
opentaps-erp-crm&amp;lt;br /&amp;gt;&lt;br /&gt;
platform&amp;lt;br /&amp;gt;&lt;br /&gt;
reverser&amp;lt;br /&amp;gt;&lt;br /&gt;
reverser-client.war&amp;lt;br /&amp;gt;&lt;br /&gt;
sample&lt;br /&gt;
* the projects are already connected to svn&lt;br /&gt;
&lt;br /&gt;
=== Build the Projects ===&lt;br /&gt;
&lt;br /&gt;
* open opentaps-erp-crm&lt;br /&gt;
* right click on pom.xml and select Run As Maven build ...&lt;br /&gt;
* Goals: clean compile package install&lt;br /&gt;
* click Apply then Run buttons&lt;br /&gt;
* the first time the build will take long time as it downloads all dependencies from Internet&lt;br /&gt;
* after BUILD SUCCESSFUL message on console select all projects and refresh them to be in synch with the build&lt;br /&gt;
* in the problem window eclipse reports errors that will be fixed as soon as we configure the environment&lt;br /&gt;
&lt;br /&gt;
=== Configure the OSGi Environment ===&lt;br /&gt;
&lt;br /&gt;
We need to install the OSGi Platform in PDE.&lt;br /&gt;
* Window -&amp;gt; Preferences -&amp;gt; Plug-in Development -&amp;gt; Target Platform click Add... button&lt;br /&gt;
* Nothing: Start with empty target definition the click Next button&lt;br /&gt;
* click Add button to add a new location&lt;br /&gt;
* select Installation then click Next&lt;br /&gt;
* location: ${workspace_loc}/opentaps-erp-crm/platform/target/platform and click Next&lt;br /&gt;
* You should see a list of 49 plug-ins that are loaded from platform project; click Finish and Finish&lt;br /&gt;
* Select New Target Platform check box and click Apply button then OK button&lt;br /&gt;
* Now in the Problems window all compilation errors should be gone; there are some XML errors that are not important&lt;br /&gt;
&lt;br /&gt;
=== Run the Platform ===&lt;br /&gt;
&lt;br /&gt;
* click on Run Configurations... drop down menu&lt;br /&gt;
* select OSGi Framework and click New&lt;br /&gt;
* Name: opentaps-osgi&lt;br /&gt;
* there are 5 workspace projects and 49 Target Platform plug-ins selected&lt;br /&gt;
* click Validate Bundles button and there should be no problems found (make sure all bundles are selected)&lt;br /&gt;
* select the start level 5 for org.springframework.osgi.web.extender; this ensures that the extender starts after Tomcat is started (the default start level is 4)&lt;br /&gt;
* click Run button and watch the console window for logs&lt;br /&gt;
* focus on console window and type ss to see the list of active bundles (notice catalina, reverser and reverser-client)&lt;br /&gt;
* type status to see more comprehensive information&lt;br /&gt;
* in browser go to http://localhost:8888/reverser-client/&lt;br /&gt;
* enter a string and click Reverse String button&lt;br /&gt;
* it displays the reversed string (also watch the console window)&lt;br /&gt;
* click on browser back button and enter a new string&lt;br /&gt;
&lt;br /&gt;
=== Software Maintenance ===&lt;br /&gt;
&lt;br /&gt;
==== Change the reverser OSGi Service ====&lt;br /&gt;
&lt;br /&gt;
* type ss in console window and note the bundle numbers for reverser and reverser-client bundles (4 and 25 in my current run)&lt;br /&gt;
* in reverser project go and modify reverse method in org.springframework.osgi.sample.service.impl.StringReverserImpl&amp;lt;br /&amp;gt;&lt;br /&gt;
return &amp;quot; &amp;gt;&amp;gt;&amp;gt; &amp;quot; + reveresed;&lt;br /&gt;
* save the file&lt;br /&gt;
* notice that the web application did not pick the change yet (try to reverse more strings)&lt;br /&gt;
* in console window type &amp;quot;refresh 4&amp;quot; where 4 in my case is the bundle number for reverser OSGi service&lt;br /&gt;
* try to reverse more strings and notice that the message on screen reflects your change&lt;br /&gt;
&lt;br /&gt;
==== Change the reverser-client Web Application ====&lt;br /&gt;
&lt;br /&gt;
* do a change in file reverser-client.war\src\main\webapp\index.jsp&lt;br /&gt;
* please note that the change is not activated yet&lt;br /&gt;
* right click on reverser-client.war/pom.xml and select Run As... -&amp;gt; Maven Build ...&lt;br /&gt;
* Goals: clean compile package install&lt;br /&gt;
* click Apply and Run buttons&lt;br /&gt;
* in osgi console window type &amp;quot;refresh 25&amp;quot; where 25 in my case is the bundle number for reverser-client web application&lt;br /&gt;
* note that your change is now reflected on page in browser (refresh the page as it may be cached)&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
&lt;br /&gt;
* we have a full OSGi developmet environment working&lt;br /&gt;
* the roundtrip for sofware maintenance changes is very short as we need to refresh only the component we changed (we do not need to restart the whole platform)&lt;br /&gt;
* we have a solid maven build&lt;br /&gt;
* it works for me and I did not encountered any problems so far&lt;br /&gt;
* I am ready to move forward&lt;/div&gt;</summary>
		<author><name>Danutc</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=Opentaps-osgi&amp;diff=4139</id>
		<title>Opentaps-osgi</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=Opentaps-osgi&amp;diff=4139"/>
		<updated>2009-07-30T06:11:26Z</updated>

		<summary type="html">&lt;p&gt;Danutc: /* Run the Platform */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page provides information about projects at:&lt;br /&gt;
&lt;br /&gt;
svn://svn.opentaps.org/opentaps/branches/danutc-2.0/org.opentaps.osgi&lt;br /&gt;
&lt;br /&gt;
== What is opentaps-osgi? ==&lt;br /&gt;
&lt;br /&gt;
We aim to migrate ofbiz and opentaps to a more modern architecture based on:&lt;br /&gt;
&lt;br /&gt;
* OSGi&lt;br /&gt;
* BPM&lt;br /&gt;
* ESB&lt;br /&gt;
* SCA&lt;br /&gt;
&lt;br /&gt;
It appears that many open source products have been migrated to OSGi. To take full advantage of these products would be desirable to have opentaps and ofbiz restructured as OSGi modules.&lt;br /&gt;
&lt;br /&gt;
Also migration to OSGi enables better architecture and more agile development. I make these statements based on information available on Internet.&lt;br /&gt;
&lt;br /&gt;
In current build the following features are deployed and illustrated:&lt;br /&gt;
&lt;br /&gt;
* Eclipse Equinox OSGi&lt;br /&gt;
* Spring DM (Dynamic Modules for OSGi development) and Spring Core&lt;br /&gt;
* Tomcat&lt;br /&gt;
* full maven build&lt;br /&gt;
* Eclipse PDE development&lt;br /&gt;
* OSGi Platform maven project build&lt;br /&gt;
* OSGi Extension Projects: log4j configuration, catalina configuration, catalina.start.osgi configuration&lt;br /&gt;
* Sample OSGi Service using Spring DM&lt;br /&gt;
* Sample Web Application that uses the service above&lt;br /&gt;
&lt;br /&gt;
== Get Started Quickly ==&lt;br /&gt;
&lt;br /&gt;
To get you started please take the following steps:&lt;br /&gt;
&lt;br /&gt;
=== Get your environment ready ===&lt;br /&gt;
I use the following tools:&lt;br /&gt;
&lt;br /&gt;
* eclipse JEE 3.5 Galileo&lt;br /&gt;
* subclipse SVN eclipse plugin that works with m2eclipse maven eclipse plugin ( http://subclipse.tigris.org/update_1.6.x )&lt;br /&gt;
* m2eclipse maven eclipse plugin ( http://m2eclipse.sonatype.org/update/ )&lt;br /&gt;
* java sdk 1.6.0_14&lt;br /&gt;
&lt;br /&gt;
=== Checkout the code ===&lt;br /&gt;
&lt;br /&gt;
* start eclipse and create a new workspace&lt;br /&gt;
* open SVN Repository Exploring perspective&lt;br /&gt;
* Add SVN Repository: svn://svn.opentaps.org/opentaps&lt;br /&gt;
* File -&amp;gt; Import -&amp;gt; Maven -&amp;gt; Checkout as Maven project from SCM&amp;lt;br /&amp;gt;&lt;br /&gt;
- SCM URL: svn&amp;lt;br /&amp;gt;&lt;br /&gt;
- svn://svn.opentaps.org/opentaps/branches/danutc-2.0/org.opentaps.osgi/trunk&lt;br /&gt;
* click Finish button&lt;br /&gt;
* after the import is finished switch to JEE perspective; you should see the following projects:&lt;br /&gt;
apps&amp;lt;br /&amp;gt;&lt;br /&gt;
catalina.config&amp;lt;br /&amp;gt;&lt;br /&gt;
catalina.start.osgi.config&amp;lt;br /&amp;gt;&lt;br /&gt;
lib&amp;lt;br /&amp;gt;&lt;br /&gt;
log4j.config&amp;lt;br /&amp;gt;&lt;br /&gt;
opentaps-erp-crm&amp;lt;br /&amp;gt;&lt;br /&gt;
platform&amp;lt;br /&amp;gt;&lt;br /&gt;
reverser&amp;lt;br /&amp;gt;&lt;br /&gt;
reverser-client.war&amp;lt;br /&amp;gt;&lt;br /&gt;
sample&lt;br /&gt;
* the projects are already connected to svn&lt;br /&gt;
&lt;br /&gt;
=== Build the Projects ===&lt;br /&gt;
&lt;br /&gt;
* open opentaps-erp-crm&lt;br /&gt;
* right click on pom.xml and select Run As Maven build ...&lt;br /&gt;
* Goals: clean compile package install&lt;br /&gt;
* click Apply then Run buttons&lt;br /&gt;
* the first time the build will take long time as it downloads all dependencies from Internet&lt;br /&gt;
* after BUILD SUCCESSFUL message on console select all projects and refresh them to be in synch with the build&lt;br /&gt;
* in the problem window eclipse reports errors that will be fixed as soon as we configure the environment&lt;br /&gt;
&lt;br /&gt;
=== Configure the OSGi Environment ===&lt;br /&gt;
&lt;br /&gt;
We need to install the OSGi Platform in PDE.&lt;br /&gt;
* Window -&amp;gt; Preferences -&amp;gt; Plug-in Development -&amp;gt; Target Platform click Add... button&lt;br /&gt;
* Nothing: Start with empty target definition the click Next button&lt;br /&gt;
* click Add button to add a new location&lt;br /&gt;
* select Installation then click Next&lt;br /&gt;
* location: ${workspace_loc}/opentaps-erp-crm/platform/target/platform and click Next&lt;br /&gt;
* You should see a list of 49 plug-ins that are loaded from platform project; click Finish and Finish&lt;br /&gt;
* Select New Target Platform check box and click Apply button then OK button&lt;br /&gt;
* Now in the Problems window all compilation errors should be gone; there are some XML errors that are not important&lt;br /&gt;
&lt;br /&gt;
=== Run the Platform ===&lt;br /&gt;
&lt;br /&gt;
* click on Run Configurations... drop down menu&lt;br /&gt;
* select OSGi Framework and click New&lt;br /&gt;
* Name: opentaps-osgi&lt;br /&gt;
* there are 5 workspace projects and 49 Target Platform plug-ins selected&lt;br /&gt;
* click Validate Bundles button and there should be no problems found (make sure all bundles are selected)&lt;br /&gt;
* select the start level 5 for org.springframework.osgi.web.extender; this ensures that the extender starts after Tomcat is started (the default start level is 4)&lt;br /&gt;
* click Run button and watch the console window for logs&lt;br /&gt;
* focus on console window and type ss to see the list of active bundles (notice catalina, reverser and reverser-client)&lt;br /&gt;
* type status to see more comprehensive information&lt;br /&gt;
* in browser go to http://localhost:8888/reverser-client/&lt;br /&gt;
* enter a string and click Reverse String button&lt;br /&gt;
* it displays the reversed string (also watch the console window)&lt;br /&gt;
* click on browser back button and enter a new string&lt;br /&gt;
&lt;br /&gt;
=== Software Maintenance ===&lt;br /&gt;
&lt;br /&gt;
==== Change the reverser OSGi Service ====&lt;br /&gt;
&lt;br /&gt;
* type ss in console window and note the bundle numbers for reverser and reverser-client bundles (4 and 25 in my current run)&lt;br /&gt;
* in reverser project go and modify reverse method in org.springframework.osgi.sample.service.impl.StringReverserImpl&amp;lt;br /&amp;gt;&lt;br /&gt;
return &amp;quot; &amp;gt;&amp;gt;&amp;gt; &amp;quot; + reveresed;&lt;br /&gt;
* save the file&lt;br /&gt;
* notice that the web application did not pick the change yet (try to reverse more strings)&lt;br /&gt;
* in console window type &amp;quot;refresh 4&amp;quot; where 4 in my case is the bundle number for reverser OSGi service&lt;br /&gt;
* try to reverse more strings and notice that the message on screen reflects your change&lt;br /&gt;
&lt;br /&gt;
==== Change the reverser-client Web Application ====&lt;br /&gt;
&lt;br /&gt;
* do a change in file reverser-client.war\src\main\webapp\index.jsp&lt;br /&gt;
* please note that the change is not activated yet&lt;br /&gt;
* right click on reverser-client.war/pom.xml and select Run As... -&amp;gt; Maven Build ...&lt;br /&gt;
* Goals: clean compile package install&lt;br /&gt;
* click Apply and Run buttons&lt;br /&gt;
* in osgi console window type &amp;quot;refresh 25&amp;quot; where 25 in my case is the bundle number for reverser-client web application&lt;br /&gt;
* note that your change is now reflected on page in browser (refresh the page as it may be cached)&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
&lt;br /&gt;
* we have a full OSGi developmet environment working&lt;br /&gt;
* the roundtrip for sofware maintenance changes is very short as we need to refresh only the component we changed (we do not need to restart the whole platform)&lt;br /&gt;
* we have a solid maven build&lt;br /&gt;
* it works for me and I did not encountered any problems so far&lt;br /&gt;
* I am ready to move forward&lt;/div&gt;</summary>
		<author><name>Danutc</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=Opentaps-osgi&amp;diff=4094</id>
		<title>Opentaps-osgi</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=Opentaps-osgi&amp;diff=4094"/>
		<updated>2009-07-21T07:52:51Z</updated>

		<summary type="html">&lt;p&gt;Danutc: /* Conclusion */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page provides information about projects at:&lt;br /&gt;
&lt;br /&gt;
svn://svn.opentaps.org/opentaps/branches/danutc-2.0/org.opentaps.osgi&lt;br /&gt;
&lt;br /&gt;
== What is opentaps-osgi? ==&lt;br /&gt;
&lt;br /&gt;
We aim to migrate ofbiz and opentaps to a more modern architecture based on:&lt;br /&gt;
&lt;br /&gt;
* OSGi&lt;br /&gt;
* BPM&lt;br /&gt;
* ESB&lt;br /&gt;
* SCA&lt;br /&gt;
&lt;br /&gt;
It appears that many open source products have been migrated to OSGi. To take full advantage of these products would be desirable to have opentaps and ofbiz restructured as OSGi modules.&lt;br /&gt;
&lt;br /&gt;
Also migration to OSGi enables better architecture and more agile development. I make these statements based on information available on Internet.&lt;br /&gt;
&lt;br /&gt;
In current build the following features are deployed and illustrated:&lt;br /&gt;
&lt;br /&gt;
* Eclipse Equinox OSGi&lt;br /&gt;
* Spring DM (Dynamic Modules for OSGi development) and Spring Core&lt;br /&gt;
* Tomcat&lt;br /&gt;
* full maven build&lt;br /&gt;
* Eclipse PDE development&lt;br /&gt;
* OSGi Platform maven project build&lt;br /&gt;
* OSGi Extension Projects: log4j configuration, catalina configuration, catalina.start.osgi configuration&lt;br /&gt;
* Sample OSGi Service using Spring DM&lt;br /&gt;
* Sample Web Application that uses the service above&lt;br /&gt;
&lt;br /&gt;
== Get Started Quickly ==&lt;br /&gt;
&lt;br /&gt;
To get you started please take the following steps:&lt;br /&gt;
&lt;br /&gt;
=== Get your environment ready ===&lt;br /&gt;
I use the following tools:&lt;br /&gt;
&lt;br /&gt;
* eclipse JEE 3.5 Galileo&lt;br /&gt;
* subclipse SVN eclipse plugin that works with m2eclipse maven eclipse plugin ( http://subclipse.tigris.org/update_1.6.x )&lt;br /&gt;
* m2eclipse maven eclipse plugin ( http://m2eclipse.sonatype.org/update/ )&lt;br /&gt;
* java sdk 1.6.0_14&lt;br /&gt;
&lt;br /&gt;
=== Checkout the code ===&lt;br /&gt;
&lt;br /&gt;
* start eclipse and create a new workspace&lt;br /&gt;
* open SVN Repository Exploring perspective&lt;br /&gt;
* Add SVN Repository: svn://svn.opentaps.org/opentaps&lt;br /&gt;
* File -&amp;gt; Import -&amp;gt; Maven -&amp;gt; Checkout as Maven project from SCM&amp;lt;br /&amp;gt;&lt;br /&gt;
- SCM URL: svn&amp;lt;br /&amp;gt;&lt;br /&gt;
- svn://svn.opentaps.org/opentaps/branches/danutc-2.0/org.opentaps.osgi/trunk&lt;br /&gt;
* click Finish button&lt;br /&gt;
* after the import is finished switch to JEE perspective; you should see the following projects:&lt;br /&gt;
apps&amp;lt;br /&amp;gt;&lt;br /&gt;
catalina.config&amp;lt;br /&amp;gt;&lt;br /&gt;
catalina.start.osgi.config&amp;lt;br /&amp;gt;&lt;br /&gt;
lib&amp;lt;br /&amp;gt;&lt;br /&gt;
log4j.config&amp;lt;br /&amp;gt;&lt;br /&gt;
opentaps-erp-crm&amp;lt;br /&amp;gt;&lt;br /&gt;
platform&amp;lt;br /&amp;gt;&lt;br /&gt;
reverser&amp;lt;br /&amp;gt;&lt;br /&gt;
reverser-client.war&amp;lt;br /&amp;gt;&lt;br /&gt;
sample&lt;br /&gt;
* the projects are already connected to svn&lt;br /&gt;
&lt;br /&gt;
=== Build the Projects ===&lt;br /&gt;
&lt;br /&gt;
* open opentaps-erp-crm&lt;br /&gt;
* right click on pom.xml and select Run As Maven build ...&lt;br /&gt;
* Goals: clean compile package install&lt;br /&gt;
* click Apply then Run buttons&lt;br /&gt;
* the first time the build will take long time as it downloads all dependencies from Internet&lt;br /&gt;
* after BUILD SUCCESSFUL message on console select all projects and refresh them to be in synch with the build&lt;br /&gt;
* in the problem window eclipse reports errors that will be fixed as soon as we configure the environment&lt;br /&gt;
&lt;br /&gt;
=== Configure the OSGi Environment ===&lt;br /&gt;
&lt;br /&gt;
We need to install the OSGi Platform in PDE.&lt;br /&gt;
* Window -&amp;gt; Preferences -&amp;gt; Plug-in Development -&amp;gt; Target Platform click Add... button&lt;br /&gt;
* Nothing: Start with empty target definition the click Next button&lt;br /&gt;
* click Add button to add a new location&lt;br /&gt;
* select Installation then click Next&lt;br /&gt;
* location: ${workspace_loc}/opentaps-erp-crm/platform/target/platform and click Next&lt;br /&gt;
* You should see a list of 49 plug-ins that are loaded from platform project; click Finish and Finish&lt;br /&gt;
* Select New Target Platform check box and click Apply button then OK button&lt;br /&gt;
* Now in the Problems window all compilation errors should be gone; there are some XML errors that are not important&lt;br /&gt;
&lt;br /&gt;
=== Run the Platform ===&lt;br /&gt;
&lt;br /&gt;
* click on Run Configurations... drop down menu&lt;br /&gt;
* select OSGi Framework and click New&lt;br /&gt;
* Name: opentaps-osgi&lt;br /&gt;
* there are 5 workspace projects and 49 Target Platform plug-ins selected&lt;br /&gt;
* click Validate Bundles button and there should be no problems found (make sure all bundles are selected)&lt;br /&gt;
* click Run button and watch the console window for logs&lt;br /&gt;
* focus on console window and type ss to see the list of active bundles (notice catalina, reverser and reverser-client)&lt;br /&gt;
* type status to see more comprehensive information&lt;br /&gt;
* in browser go to http://localhost:8888/reverser-client/&lt;br /&gt;
* enter a string and click Reverse String button&lt;br /&gt;
* it displays the reversed string (also watch the console window)&lt;br /&gt;
* click on browser back button and enter a new string&lt;br /&gt;
&lt;br /&gt;
=== Software Maintenance ===&lt;br /&gt;
&lt;br /&gt;
==== Change the reverser OSGi Service ====&lt;br /&gt;
&lt;br /&gt;
* type ss in console window and note the bundle numbers for reverser and reverser-client bundles (4 and 25 in my current run)&lt;br /&gt;
* in reverser project go and modify reverse method in org.springframework.osgi.sample.service.impl.StringReverserImpl&amp;lt;br /&amp;gt;&lt;br /&gt;
return &amp;quot; &amp;gt;&amp;gt;&amp;gt; &amp;quot; + reveresed;&lt;br /&gt;
* save the file&lt;br /&gt;
* notice that the web application did not pick the change yet (try to reverse more strings)&lt;br /&gt;
* in console window type &amp;quot;refresh 4&amp;quot; where 4 in my case is the bundle number for reverser OSGi service&lt;br /&gt;
* try to reverse more strings and notice that the message on screen reflects your change&lt;br /&gt;
&lt;br /&gt;
==== Change the reverser-client Web Application ====&lt;br /&gt;
&lt;br /&gt;
* do a change in file reverser-client.war\src\main\webapp\index.jsp&lt;br /&gt;
* please note that the change is not activated yet&lt;br /&gt;
* right click on reverser-client.war/pom.xml and select Run As... -&amp;gt; Maven Build ...&lt;br /&gt;
* Goals: clean compile package install&lt;br /&gt;
* click Apply and Run buttons&lt;br /&gt;
* in osgi console window type &amp;quot;refresh 25&amp;quot; where 25 in my case is the bundle number for reverser-client web application&lt;br /&gt;
* note that your change is now reflected on page in browser (refresh the page as it may be cached)&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
&lt;br /&gt;
* we have a full OSGi developmet environment working&lt;br /&gt;
* the roundtrip for sofware maintenance changes is very short as we need to refresh only the component we changed (we do not need to restart the whole platform)&lt;br /&gt;
* we have a solid maven build&lt;br /&gt;
* it works for me and I did not encountered any problems so far&lt;br /&gt;
* I am ready to move forward&lt;/div&gt;</summary>
		<author><name>Danutc</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=Opentaps-osgi&amp;diff=4093</id>
		<title>Opentaps-osgi</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=Opentaps-osgi&amp;diff=4093"/>
		<updated>2009-07-21T07:50:05Z</updated>

		<summary type="html">&lt;p&gt;Danutc: /* Run the Platform */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page provides information about projects at:&lt;br /&gt;
&lt;br /&gt;
svn://svn.opentaps.org/opentaps/branches/danutc-2.0/org.opentaps.osgi&lt;br /&gt;
&lt;br /&gt;
== What is opentaps-osgi? ==&lt;br /&gt;
&lt;br /&gt;
We aim to migrate ofbiz and opentaps to a more modern architecture based on:&lt;br /&gt;
&lt;br /&gt;
* OSGi&lt;br /&gt;
* BPM&lt;br /&gt;
* ESB&lt;br /&gt;
* SCA&lt;br /&gt;
&lt;br /&gt;
It appears that many open source products have been migrated to OSGi. To take full advantage of these products would be desirable to have opentaps and ofbiz restructured as OSGi modules.&lt;br /&gt;
&lt;br /&gt;
Also migration to OSGi enables better architecture and more agile development. I make these statements based on information available on Internet.&lt;br /&gt;
&lt;br /&gt;
In current build the following features are deployed and illustrated:&lt;br /&gt;
&lt;br /&gt;
* Eclipse Equinox OSGi&lt;br /&gt;
* Spring DM (Dynamic Modules for OSGi development) and Spring Core&lt;br /&gt;
* Tomcat&lt;br /&gt;
* full maven build&lt;br /&gt;
* Eclipse PDE development&lt;br /&gt;
* OSGi Platform maven project build&lt;br /&gt;
* OSGi Extension Projects: log4j configuration, catalina configuration, catalina.start.osgi configuration&lt;br /&gt;
* Sample OSGi Service using Spring DM&lt;br /&gt;
* Sample Web Application that uses the service above&lt;br /&gt;
&lt;br /&gt;
== Get Started Quickly ==&lt;br /&gt;
&lt;br /&gt;
To get you started please take the following steps:&lt;br /&gt;
&lt;br /&gt;
=== Get your environment ready ===&lt;br /&gt;
I use the following tools:&lt;br /&gt;
&lt;br /&gt;
* eclipse JEE 3.5 Galileo&lt;br /&gt;
* subclipse SVN eclipse plugin that works with m2eclipse maven eclipse plugin ( http://subclipse.tigris.org/update_1.6.x )&lt;br /&gt;
* m2eclipse maven eclipse plugin ( http://m2eclipse.sonatype.org/update/ )&lt;br /&gt;
* java sdk 1.6.0_14&lt;br /&gt;
&lt;br /&gt;
=== Checkout the code ===&lt;br /&gt;
&lt;br /&gt;
* start eclipse and create a new workspace&lt;br /&gt;
* open SVN Repository Exploring perspective&lt;br /&gt;
* Add SVN Repository: svn://svn.opentaps.org/opentaps&lt;br /&gt;
* File -&amp;gt; Import -&amp;gt; Maven -&amp;gt; Checkout as Maven project from SCM&amp;lt;br /&amp;gt;&lt;br /&gt;
- SCM URL: svn&amp;lt;br /&amp;gt;&lt;br /&gt;
- svn://svn.opentaps.org/opentaps/branches/danutc-2.0/org.opentaps.osgi/trunk&lt;br /&gt;
* click Finish button&lt;br /&gt;
* after the import is finished switch to JEE perspective; you should see the following projects:&lt;br /&gt;
apps&amp;lt;br /&amp;gt;&lt;br /&gt;
catalina.config&amp;lt;br /&amp;gt;&lt;br /&gt;
catalina.start.osgi.config&amp;lt;br /&amp;gt;&lt;br /&gt;
lib&amp;lt;br /&amp;gt;&lt;br /&gt;
log4j.config&amp;lt;br /&amp;gt;&lt;br /&gt;
opentaps-erp-crm&amp;lt;br /&amp;gt;&lt;br /&gt;
platform&amp;lt;br /&amp;gt;&lt;br /&gt;
reverser&amp;lt;br /&amp;gt;&lt;br /&gt;
reverser-client.war&amp;lt;br /&amp;gt;&lt;br /&gt;
sample&lt;br /&gt;
* the projects are already connected to svn&lt;br /&gt;
&lt;br /&gt;
=== Build the Projects ===&lt;br /&gt;
&lt;br /&gt;
* open opentaps-erp-crm&lt;br /&gt;
* right click on pom.xml and select Run As Maven build ...&lt;br /&gt;
* Goals: clean compile package install&lt;br /&gt;
* click Apply then Run buttons&lt;br /&gt;
* the first time the build will take long time as it downloads all dependencies from Internet&lt;br /&gt;
* after BUILD SUCCESSFUL message on console select all projects and refresh them to be in synch with the build&lt;br /&gt;
* in the problem window eclipse reports errors that will be fixed as soon as we configure the environment&lt;br /&gt;
&lt;br /&gt;
=== Configure the OSGi Environment ===&lt;br /&gt;
&lt;br /&gt;
We need to install the OSGi Platform in PDE.&lt;br /&gt;
* Window -&amp;gt; Preferences -&amp;gt; Plug-in Development -&amp;gt; Target Platform click Add... button&lt;br /&gt;
* Nothing: Start with empty target definition the click Next button&lt;br /&gt;
* click Add button to add a new location&lt;br /&gt;
* select Installation then click Next&lt;br /&gt;
* location: ${workspace_loc}/opentaps-erp-crm/platform/target/platform and click Next&lt;br /&gt;
* You should see a list of 49 plug-ins that are loaded from platform project; click Finish and Finish&lt;br /&gt;
* Select New Target Platform check box and click Apply button then OK button&lt;br /&gt;
* Now in the Problems window all compilation errors should be gone; there are some XML errors that are not important&lt;br /&gt;
&lt;br /&gt;
=== Run the Platform ===&lt;br /&gt;
&lt;br /&gt;
* click on Run Configurations... drop down menu&lt;br /&gt;
* select OSGi Framework and click New&lt;br /&gt;
* Name: opentaps-osgi&lt;br /&gt;
* there are 5 workspace projects and 49 Target Platform plug-ins selected&lt;br /&gt;
* click Validate Bundles button and there should be no problems found (make sure all bundles are selected)&lt;br /&gt;
* click Run button and watch the console window for logs&lt;br /&gt;
* focus on console window and type ss to see the list of active bundles (notice catalina, reverser and reverser-client)&lt;br /&gt;
* type status to see more comprehensive information&lt;br /&gt;
* in browser go to http://localhost:8888/reverser-client/&lt;br /&gt;
* enter a string and click Reverse String button&lt;br /&gt;
* it displays the reversed string (also watch the console window)&lt;br /&gt;
* click on browser back button and enter a new string&lt;br /&gt;
&lt;br /&gt;
=== Software Maintenance ===&lt;br /&gt;
&lt;br /&gt;
==== Change the reverser OSGi Service ====&lt;br /&gt;
&lt;br /&gt;
* type ss in console window and note the bundle numbers for reverser and reverser-client bundles (4 and 25 in my current run)&lt;br /&gt;
* in reverser project go and modify reverse method in org.springframework.osgi.sample.service.impl.StringReverserImpl&amp;lt;br /&amp;gt;&lt;br /&gt;
return &amp;quot; &amp;gt;&amp;gt;&amp;gt; &amp;quot; + reveresed;&lt;br /&gt;
* save the file&lt;br /&gt;
* notice that the web application did not pick the change yet (try to reverse more strings)&lt;br /&gt;
* in console window type &amp;quot;refresh 4&amp;quot; where 4 in my case is the bundle number for reverser OSGi service&lt;br /&gt;
* try to reverse more strings and notice that the message on screen reflects your change&lt;br /&gt;
&lt;br /&gt;
==== Change the reverser-client Web Application ====&lt;br /&gt;
&lt;br /&gt;
* do a change in file reverser-client.war\src\main\webapp\index.jsp&lt;br /&gt;
* please note that the change is not activated yet&lt;br /&gt;
* right click on reverser-client.war/pom.xml and select Run As... -&amp;gt; Maven Build ...&lt;br /&gt;
* Goals: clean compile package install&lt;br /&gt;
* click Apply and Run buttons&lt;br /&gt;
* in osgi console window type &amp;quot;refresh 25&amp;quot; where 25 in my case is the bundle number for reverser-client web application&lt;br /&gt;
* note that your change is now reflected on page in browser (refresh the page as it may be cached)&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
&lt;br /&gt;
* we have a full OSGi developmet environment working&lt;br /&gt;
* the roundtrip for sofware maintenance changes is very short as we need to refresh only the compnent we changes (we do not need to restart the whole platform)&lt;br /&gt;
* we have a solid maven build&lt;br /&gt;
* it works for me and I did not encountered any problems so far&lt;br /&gt;
* I am ready to move forward&lt;/div&gt;</summary>
		<author><name>Danutc</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=Opentaps-osgi&amp;diff=4092</id>
		<title>Opentaps-osgi</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=Opentaps-osgi&amp;diff=4092"/>
		<updated>2009-07-21T07:48:28Z</updated>

		<summary type="html">&lt;p&gt;Danutc: /* Configure the OSGi Environment */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page provides information about projects at:&lt;br /&gt;
&lt;br /&gt;
svn://svn.opentaps.org/opentaps/branches/danutc-2.0/org.opentaps.osgi&lt;br /&gt;
&lt;br /&gt;
== What is opentaps-osgi? ==&lt;br /&gt;
&lt;br /&gt;
We aim to migrate ofbiz and opentaps to a more modern architecture based on:&lt;br /&gt;
&lt;br /&gt;
* OSGi&lt;br /&gt;
* BPM&lt;br /&gt;
* ESB&lt;br /&gt;
* SCA&lt;br /&gt;
&lt;br /&gt;
It appears that many open source products have been migrated to OSGi. To take full advantage of these products would be desirable to have opentaps and ofbiz restructured as OSGi modules.&lt;br /&gt;
&lt;br /&gt;
Also migration to OSGi enables better architecture and more agile development. I make these statements based on information available on Internet.&lt;br /&gt;
&lt;br /&gt;
In current build the following features are deployed and illustrated:&lt;br /&gt;
&lt;br /&gt;
* Eclipse Equinox OSGi&lt;br /&gt;
* Spring DM (Dynamic Modules for OSGi development) and Spring Core&lt;br /&gt;
* Tomcat&lt;br /&gt;
* full maven build&lt;br /&gt;
* Eclipse PDE development&lt;br /&gt;
* OSGi Platform maven project build&lt;br /&gt;
* OSGi Extension Projects: log4j configuration, catalina configuration, catalina.start.osgi configuration&lt;br /&gt;
* Sample OSGi Service using Spring DM&lt;br /&gt;
* Sample Web Application that uses the service above&lt;br /&gt;
&lt;br /&gt;
== Get Started Quickly ==&lt;br /&gt;
&lt;br /&gt;
To get you started please take the following steps:&lt;br /&gt;
&lt;br /&gt;
=== Get your environment ready ===&lt;br /&gt;
I use the following tools:&lt;br /&gt;
&lt;br /&gt;
* eclipse JEE 3.5 Galileo&lt;br /&gt;
* subclipse SVN eclipse plugin that works with m2eclipse maven eclipse plugin ( http://subclipse.tigris.org/update_1.6.x )&lt;br /&gt;
* m2eclipse maven eclipse plugin ( http://m2eclipse.sonatype.org/update/ )&lt;br /&gt;
* java sdk 1.6.0_14&lt;br /&gt;
&lt;br /&gt;
=== Checkout the code ===&lt;br /&gt;
&lt;br /&gt;
* start eclipse and create a new workspace&lt;br /&gt;
* open SVN Repository Exploring perspective&lt;br /&gt;
* Add SVN Repository: svn://svn.opentaps.org/opentaps&lt;br /&gt;
* File -&amp;gt; Import -&amp;gt; Maven -&amp;gt; Checkout as Maven project from SCM&amp;lt;br /&amp;gt;&lt;br /&gt;
- SCM URL: svn&amp;lt;br /&amp;gt;&lt;br /&gt;
- svn://svn.opentaps.org/opentaps/branches/danutc-2.0/org.opentaps.osgi/trunk&lt;br /&gt;
* click Finish button&lt;br /&gt;
* after the import is finished switch to JEE perspective; you should see the following projects:&lt;br /&gt;
apps&amp;lt;br /&amp;gt;&lt;br /&gt;
catalina.config&amp;lt;br /&amp;gt;&lt;br /&gt;
catalina.start.osgi.config&amp;lt;br /&amp;gt;&lt;br /&gt;
lib&amp;lt;br /&amp;gt;&lt;br /&gt;
log4j.config&amp;lt;br /&amp;gt;&lt;br /&gt;
opentaps-erp-crm&amp;lt;br /&amp;gt;&lt;br /&gt;
platform&amp;lt;br /&amp;gt;&lt;br /&gt;
reverser&amp;lt;br /&amp;gt;&lt;br /&gt;
reverser-client.war&amp;lt;br /&amp;gt;&lt;br /&gt;
sample&lt;br /&gt;
* the projects are already connected to svn&lt;br /&gt;
&lt;br /&gt;
=== Build the Projects ===&lt;br /&gt;
&lt;br /&gt;
* open opentaps-erp-crm&lt;br /&gt;
* right click on pom.xml and select Run As Maven build ...&lt;br /&gt;
* Goals: clean compile package install&lt;br /&gt;
* click Apply then Run buttons&lt;br /&gt;
* the first time the build will take long time as it downloads all dependencies from Internet&lt;br /&gt;
* after BUILD SUCCESSFUL message on console select all projects and refresh them to be in synch with the build&lt;br /&gt;
* in the problem window eclipse reports errors that will be fixed as soon as we configure the environment&lt;br /&gt;
&lt;br /&gt;
=== Configure the OSGi Environment ===&lt;br /&gt;
&lt;br /&gt;
We need to install the OSGi Platform in PDE.&lt;br /&gt;
* Window -&amp;gt; Preferences -&amp;gt; Plug-in Development -&amp;gt; Target Platform click Add... button&lt;br /&gt;
* Nothing: Start with empty target definition the click Next button&lt;br /&gt;
* click Add button to add a new location&lt;br /&gt;
* select Installation then click Next&lt;br /&gt;
* location: ${workspace_loc}/opentaps-erp-crm/platform/target/platform and click Next&lt;br /&gt;
* You should see a list of 49 plug-ins that are loaded from platform project; click Finish and Finish&lt;br /&gt;
* Select New Target Platform check box and click Apply button then OK button&lt;br /&gt;
* Now in the Problems window all compilation errors should be gone; there are some XML errors that are not important&lt;br /&gt;
&lt;br /&gt;
=== Run the Platform ===&lt;br /&gt;
&lt;br /&gt;
* click on Run Configurations... drop down menu&lt;br /&gt;
* select OSGi Framework and click New&lt;br /&gt;
* Name: opentaps-osgi&lt;br /&gt;
* there are 5 workspace projects and 49 Target Platform plug-ins selected&lt;br /&gt;
* click Validate Bundles button and there should be no problems found (make sure all bundles are selected)&lt;br /&gt;
* click Run button and watch the console window for logs&lt;br /&gt;
* focus on console window and type ss to see the list of active bundles (notice catalina, reverser and reverser-client)&lt;br /&gt;
* type status to see a more comprehensive information&lt;br /&gt;
* in browser go to http://localhost:8888/reverser-client/&lt;br /&gt;
* enter a string and click Reverse String button&lt;br /&gt;
* it displays the reversed string (also watch the console window)&lt;br /&gt;
* click on browser back button and enter a new string&lt;br /&gt;
&lt;br /&gt;
=== Software Maintenance ===&lt;br /&gt;
&lt;br /&gt;
==== Change the reverser OSGi Service ====&lt;br /&gt;
&lt;br /&gt;
* type ss in console window and note the bundle numbers for reverser and reverser-client bundles (4 and 25 in my current run)&lt;br /&gt;
* in reverser project go and modify reverse method in org.springframework.osgi.sample.service.impl.StringReverserImpl&amp;lt;br /&amp;gt;&lt;br /&gt;
return &amp;quot; &amp;gt;&amp;gt;&amp;gt; &amp;quot; + reveresed;&lt;br /&gt;
* save the file&lt;br /&gt;
* notice that the web application did not pick the change yet (try to reverse more strings)&lt;br /&gt;
* in console window type &amp;quot;refresh 4&amp;quot; where 4 in my case is the bundle number for reverser OSGi service&lt;br /&gt;
* try to reverse more strings and notice that the message on screen reflects your change&lt;br /&gt;
&lt;br /&gt;
==== Change the reverser-client Web Application ====&lt;br /&gt;
&lt;br /&gt;
* do a change in file reverser-client.war\src\main\webapp\index.jsp&lt;br /&gt;
* please note that the change is not activated yet&lt;br /&gt;
* right click on reverser-client.war/pom.xml and select Run As... -&amp;gt; Maven Build ...&lt;br /&gt;
* Goals: clean compile package install&lt;br /&gt;
* click Apply and Run buttons&lt;br /&gt;
* in osgi console window type &amp;quot;refresh 25&amp;quot; where 25 in my case is the bundle number for reverser-client web application&lt;br /&gt;
* note that your change is now reflected on page in browser (refresh the page as it may be cached)&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
&lt;br /&gt;
* we have a full OSGi developmet environment working&lt;br /&gt;
* the roundtrip for sofware maintenance changes is very short as we need to refresh only the compnent we changes (we do not need to restart the whole platform)&lt;br /&gt;
* we have a solid maven build&lt;br /&gt;
* it works for me and I did not encountered any problems so far&lt;br /&gt;
* I am ready to move forward&lt;/div&gt;</summary>
		<author><name>Danutc</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=Opentaps-osgi&amp;diff=4091</id>
		<title>Opentaps-osgi</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=Opentaps-osgi&amp;diff=4091"/>
		<updated>2009-07-21T07:46:26Z</updated>

		<summary type="html">&lt;p&gt;Danutc: /* Checkout the code */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page provides information about projects at:&lt;br /&gt;
&lt;br /&gt;
svn://svn.opentaps.org/opentaps/branches/danutc-2.0/org.opentaps.osgi&lt;br /&gt;
&lt;br /&gt;
== What is opentaps-osgi? ==&lt;br /&gt;
&lt;br /&gt;
We aim to migrate ofbiz and opentaps to a more modern architecture based on:&lt;br /&gt;
&lt;br /&gt;
* OSGi&lt;br /&gt;
* BPM&lt;br /&gt;
* ESB&lt;br /&gt;
* SCA&lt;br /&gt;
&lt;br /&gt;
It appears that many open source products have been migrated to OSGi. To take full advantage of these products would be desirable to have opentaps and ofbiz restructured as OSGi modules.&lt;br /&gt;
&lt;br /&gt;
Also migration to OSGi enables better architecture and more agile development. I make these statements based on information available on Internet.&lt;br /&gt;
&lt;br /&gt;
In current build the following features are deployed and illustrated:&lt;br /&gt;
&lt;br /&gt;
* Eclipse Equinox OSGi&lt;br /&gt;
* Spring DM (Dynamic Modules for OSGi development) and Spring Core&lt;br /&gt;
* Tomcat&lt;br /&gt;
* full maven build&lt;br /&gt;
* Eclipse PDE development&lt;br /&gt;
* OSGi Platform maven project build&lt;br /&gt;
* OSGi Extension Projects: log4j configuration, catalina configuration, catalina.start.osgi configuration&lt;br /&gt;
* Sample OSGi Service using Spring DM&lt;br /&gt;
* Sample Web Application that uses the service above&lt;br /&gt;
&lt;br /&gt;
== Get Started Quickly ==&lt;br /&gt;
&lt;br /&gt;
To get you started please take the following steps:&lt;br /&gt;
&lt;br /&gt;
=== Get your environment ready ===&lt;br /&gt;
I use the following tools:&lt;br /&gt;
&lt;br /&gt;
* eclipse JEE 3.5 Galileo&lt;br /&gt;
* subclipse SVN eclipse plugin that works with m2eclipse maven eclipse plugin ( http://subclipse.tigris.org/update_1.6.x )&lt;br /&gt;
* m2eclipse maven eclipse plugin ( http://m2eclipse.sonatype.org/update/ )&lt;br /&gt;
* java sdk 1.6.0_14&lt;br /&gt;
&lt;br /&gt;
=== Checkout the code ===&lt;br /&gt;
&lt;br /&gt;
* start eclipse and create a new workspace&lt;br /&gt;
* open SVN Repository Exploring perspective&lt;br /&gt;
* Add SVN Repository: svn://svn.opentaps.org/opentaps&lt;br /&gt;
* File -&amp;gt; Import -&amp;gt; Maven -&amp;gt; Checkout as Maven project from SCM&amp;lt;br /&amp;gt;&lt;br /&gt;
- SCM URL: svn&amp;lt;br /&amp;gt;&lt;br /&gt;
- svn://svn.opentaps.org/opentaps/branches/danutc-2.0/org.opentaps.osgi/trunk&lt;br /&gt;
* click Finish button&lt;br /&gt;
* after the import is finished switch to JEE perspective; you should see the following projects:&lt;br /&gt;
apps&amp;lt;br /&amp;gt;&lt;br /&gt;
catalina.config&amp;lt;br /&amp;gt;&lt;br /&gt;
catalina.start.osgi.config&amp;lt;br /&amp;gt;&lt;br /&gt;
lib&amp;lt;br /&amp;gt;&lt;br /&gt;
log4j.config&amp;lt;br /&amp;gt;&lt;br /&gt;
opentaps-erp-crm&amp;lt;br /&amp;gt;&lt;br /&gt;
platform&amp;lt;br /&amp;gt;&lt;br /&gt;
reverser&amp;lt;br /&amp;gt;&lt;br /&gt;
reverser-client.war&amp;lt;br /&amp;gt;&lt;br /&gt;
sample&lt;br /&gt;
* the projects are already connected to svn&lt;br /&gt;
&lt;br /&gt;
=== Build the Projects ===&lt;br /&gt;
&lt;br /&gt;
* open opentaps-erp-crm&lt;br /&gt;
* right click on pom.xml and select Run As Maven build ...&lt;br /&gt;
* Goals: clean compile package install&lt;br /&gt;
* click Apply then Run buttons&lt;br /&gt;
* the first time the build will take long time as it downloads all dependencies from Internet&lt;br /&gt;
* after BUILD SUCCESSFUL message on console select all projects and refresh them to be in synch with the build&lt;br /&gt;
* in the problem window eclipse reports errors that will be fixed as soon as we configure the environment&lt;br /&gt;
&lt;br /&gt;
=== Configure the OSGi Environment ===&lt;br /&gt;
&lt;br /&gt;
We need to install the OSGi Platform in PDE.&lt;br /&gt;
* Window -&amp;gt; Preferences -&amp;gt; Plug-in Development -&amp;gt; Target Platform click Add... button&lt;br /&gt;
* Nothing: Start with empty target definition the click Next button&lt;br /&gt;
* click Add button to add a new location&lt;br /&gt;
* select Installation then click Next&lt;br /&gt;
* location: ${workspace_loc}/opentaps-erp-crm/platform/target/platform and click Nex&lt;br /&gt;
* You should see a list of 49 plug-ins that are loaded from platform project; click Finish and Finish&lt;br /&gt;
* Select New Target Platform check box and click Apply button then OK button&lt;br /&gt;
* Now in the Problems window all compilation errors should be gone; there are some XML errors that are not important&lt;br /&gt;
&lt;br /&gt;
=== Run the Platform ===&lt;br /&gt;
&lt;br /&gt;
* click on Run Configurations... drop down menu&lt;br /&gt;
* select OSGi Framework and click New&lt;br /&gt;
* Name: opentaps-osgi&lt;br /&gt;
* there are 5 workspace projects and 49 Target Platform plug-ins selected&lt;br /&gt;
* click Validate Bundles button and there should be no problems found (make sure all bundles are selected)&lt;br /&gt;
* click Run button and watch the console window for logs&lt;br /&gt;
* focus on console window and type ss to see the list of active bundles (notice catalina, reverser and reverser-client)&lt;br /&gt;
* type status to see a more comprehensive information&lt;br /&gt;
* in browser go to http://localhost:8888/reverser-client/&lt;br /&gt;
* enter a string and click Reverse String button&lt;br /&gt;
* it displays the reversed string (also watch the console window)&lt;br /&gt;
* click on browser back button and enter a new string&lt;br /&gt;
&lt;br /&gt;
=== Software Maintenance ===&lt;br /&gt;
&lt;br /&gt;
==== Change the reverser OSGi Service ====&lt;br /&gt;
&lt;br /&gt;
* type ss in console window and note the bundle numbers for reverser and reverser-client bundles (4 and 25 in my current run)&lt;br /&gt;
* in reverser project go and modify reverse method in org.springframework.osgi.sample.service.impl.StringReverserImpl&amp;lt;br /&amp;gt;&lt;br /&gt;
return &amp;quot; &amp;gt;&amp;gt;&amp;gt; &amp;quot; + reveresed;&lt;br /&gt;
* save the file&lt;br /&gt;
* notice that the web application did not pick the change yet (try to reverse more strings)&lt;br /&gt;
* in console window type &amp;quot;refresh 4&amp;quot; where 4 in my case is the bundle number for reverser OSGi service&lt;br /&gt;
* try to reverse more strings and notice that the message on screen reflects your change&lt;br /&gt;
&lt;br /&gt;
==== Change the reverser-client Web Application ====&lt;br /&gt;
&lt;br /&gt;
* do a change in file reverser-client.war\src\main\webapp\index.jsp&lt;br /&gt;
* please note that the change is not activated yet&lt;br /&gt;
* right click on reverser-client.war/pom.xml and select Run As... -&amp;gt; Maven Build ...&lt;br /&gt;
* Goals: clean compile package install&lt;br /&gt;
* click Apply and Run buttons&lt;br /&gt;
* in osgi console window type &amp;quot;refresh 25&amp;quot; where 25 in my case is the bundle number for reverser-client web application&lt;br /&gt;
* note that your change is now reflected on page in browser (refresh the page as it may be cached)&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
&lt;br /&gt;
* we have a full OSGi developmet environment working&lt;br /&gt;
* the roundtrip for sofware maintenance changes is very short as we need to refresh only the compnent we changes (we do not need to restart the whole platform)&lt;br /&gt;
* we have a solid maven build&lt;br /&gt;
* it works for me and I did not encountered any problems so far&lt;br /&gt;
* I am ready to move forward&lt;/div&gt;</summary>
		<author><name>Danutc</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=Opentaps-osgi&amp;diff=4090</id>
		<title>Opentaps-osgi</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=Opentaps-osgi&amp;diff=4090"/>
		<updated>2009-07-21T07:36:43Z</updated>

		<summary type="html">&lt;p&gt;Danutc: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page provides information about projects at:&lt;br /&gt;
&lt;br /&gt;
svn://svn.opentaps.org/opentaps/branches/danutc-2.0/org.opentaps.osgi&lt;br /&gt;
&lt;br /&gt;
== What is opentaps-osgi? ==&lt;br /&gt;
&lt;br /&gt;
We aim to migrate ofbiz and opentaps to a more modern architecture based on:&lt;br /&gt;
&lt;br /&gt;
* OSGi&lt;br /&gt;
* BPM&lt;br /&gt;
* ESB&lt;br /&gt;
* SCA&lt;br /&gt;
&lt;br /&gt;
It appears that many open source products have been migrated to OSGi. To take full advantage of these products would be desirable to have opentaps and ofbiz restructured as OSGi modules.&lt;br /&gt;
&lt;br /&gt;
Also migration to OSGi enables better architecture and more agile development. I make these statements based on information available on Internet.&lt;br /&gt;
&lt;br /&gt;
In current build the following features are deployed and illustrated:&lt;br /&gt;
&lt;br /&gt;
* Eclipse Equinox OSGi&lt;br /&gt;
* Spring DM (Dynamic Modules for OSGi development) and Spring Core&lt;br /&gt;
* Tomcat&lt;br /&gt;
* full maven build&lt;br /&gt;
* Eclipse PDE development&lt;br /&gt;
* OSGi Platform maven project build&lt;br /&gt;
* OSGi Extension Projects: log4j configuration, catalina configuration, catalina.start.osgi configuration&lt;br /&gt;
* Sample OSGi Service using Spring DM&lt;br /&gt;
* Sample Web Application that uses the service above&lt;br /&gt;
&lt;br /&gt;
== Get Started Quickly ==&lt;br /&gt;
&lt;br /&gt;
To get you started please take the following steps:&lt;br /&gt;
&lt;br /&gt;
=== Get your environment ready ===&lt;br /&gt;
I use the following tools:&lt;br /&gt;
&lt;br /&gt;
* eclipse JEE 3.5 Galileo&lt;br /&gt;
* subclipse SVN eclipse plugin that works with m2eclipse maven eclipse plugin ( http://subclipse.tigris.org/update_1.6.x )&lt;br /&gt;
* m2eclipse maven eclipse plugin ( http://m2eclipse.sonatype.org/update/ )&lt;br /&gt;
* java sdk 1.6.0_14&lt;br /&gt;
&lt;br /&gt;
=== Checkout the code ===&lt;br /&gt;
&lt;br /&gt;
* start eclipse and create a new workspace&lt;br /&gt;
* open SVN Repository Exploring perspective&lt;br /&gt;
* Add SVN Repository: svn://svn.opentaps.org/opentaps&lt;br /&gt;
* File -&amp;gt; Import -&amp;gt; Maven -&amp;gt; Checkout as Maven project from SCM&amp;lt;br /&amp;gt;&lt;br /&gt;
- SCM URL: svn&amp;lt;br /&amp;gt;&lt;br /&gt;
- svn://svn.opentaps.org/opentaps/branches/danutc-2.0/org.opentaps.osgi/trunk&lt;br /&gt;
* click Finish button&lt;br /&gt;
* after the import is finished switch to JEE perspectiv; you should see the following projects:&lt;br /&gt;
apps&amp;lt;br /&amp;gt;&lt;br /&gt;
catalina.config&amp;lt;br /&amp;gt;&lt;br /&gt;
catalina.start.osgi.config&amp;lt;br /&amp;gt;&lt;br /&gt;
lib&amp;lt;br /&amp;gt;&lt;br /&gt;
log4j.config&amp;lt;br /&amp;gt;&lt;br /&gt;
opentaps-erp-crm&amp;lt;br /&amp;gt;&lt;br /&gt;
platform&amp;lt;br /&amp;gt;&lt;br /&gt;
reverser&amp;lt;br /&amp;gt;&lt;br /&gt;
reverser-client.war&amp;lt;br /&amp;gt;&lt;br /&gt;
sample&lt;br /&gt;
* the projects are already connected to svn&lt;br /&gt;
&lt;br /&gt;
=== Build the Projects ===&lt;br /&gt;
&lt;br /&gt;
* open opentaps-erp-crm&lt;br /&gt;
* right click on pom.xml and select Run As Maven build ...&lt;br /&gt;
* Goals: clean compile package install&lt;br /&gt;
* click Apply then Run buttons&lt;br /&gt;
* the first time the build will take long time as it downloads all dependencies from Internet&lt;br /&gt;
* after BUILD SUCCESSFUL message on console select all projects and refresh them to be in synch with the build&lt;br /&gt;
* in the problem window eclipse reports errors that will be fixed as soon as we configure the environment&lt;br /&gt;
&lt;br /&gt;
=== Configure the OSGi Environment ===&lt;br /&gt;
&lt;br /&gt;
We need to install the OSGi Platform in PDE.&lt;br /&gt;
* Window -&amp;gt; Preferences -&amp;gt; Plug-in Development -&amp;gt; Target Platform click Add... button&lt;br /&gt;
* Nothing: Start with empty target definition the click Next button&lt;br /&gt;
* click Add button to add a new location&lt;br /&gt;
* select Installation then click Next&lt;br /&gt;
* location: ${workspace_loc}/opentaps-erp-crm/platform/target/platform and click Nex&lt;br /&gt;
* You should see a list of 49 plug-ins that are loaded from platform project; click Finish and Finish&lt;br /&gt;
* Select New Target Platform check box and click Apply button then OK button&lt;br /&gt;
* Now in the Problems window all compilation errors should be gone; there are some XML errors that are not important&lt;br /&gt;
&lt;br /&gt;
=== Run the Platform ===&lt;br /&gt;
&lt;br /&gt;
* click on Run Configurations... drop down menu&lt;br /&gt;
* select OSGi Framework and click New&lt;br /&gt;
* Name: opentaps-osgi&lt;br /&gt;
* there are 5 workspace projects and 49 Target Platform plug-ins selected&lt;br /&gt;
* click Validate Bundles button and there should be no problems found (make sure all bundles are selected)&lt;br /&gt;
* click Run button and watch the console window for logs&lt;br /&gt;
* focus on console window and type ss to see the list of active bundles (notice catalina, reverser and reverser-client)&lt;br /&gt;
* type status to see a more comprehensive information&lt;br /&gt;
* in browser go to http://localhost:8888/reverser-client/&lt;br /&gt;
* enter a string and click Reverse String button&lt;br /&gt;
* it displays the reversed string (also watch the console window)&lt;br /&gt;
* click on browser back button and enter a new string&lt;br /&gt;
&lt;br /&gt;
=== Software Maintenance ===&lt;br /&gt;
&lt;br /&gt;
==== Change the reverser OSGi Service ====&lt;br /&gt;
&lt;br /&gt;
* type ss in console window and note the bundle numbers for reverser and reverser-client bundles (4 and 25 in my current run)&lt;br /&gt;
* in reverser project go and modify reverse method in org.springframework.osgi.sample.service.impl.StringReverserImpl&amp;lt;br /&amp;gt;&lt;br /&gt;
return &amp;quot; &amp;gt;&amp;gt;&amp;gt; &amp;quot; + reveresed;&lt;br /&gt;
* save the file&lt;br /&gt;
* notice that the web application did not pick the change yet (try to reverse more strings)&lt;br /&gt;
* in console window type &amp;quot;refresh 4&amp;quot; where 4 in my case is the bundle number for reverser OSGi service&lt;br /&gt;
* try to reverse more strings and notice that the message on screen reflects your change&lt;br /&gt;
&lt;br /&gt;
==== Change the reverser-client Web Application ====&lt;br /&gt;
&lt;br /&gt;
* do a change in file reverser-client.war\src\main\webapp\index.jsp&lt;br /&gt;
* please note that the change is not activated yet&lt;br /&gt;
* right click on reverser-client.war/pom.xml and select Run As... -&amp;gt; Maven Build ...&lt;br /&gt;
* Goals: clean compile package install&lt;br /&gt;
* click Apply and Run buttons&lt;br /&gt;
* in osgi console window type &amp;quot;refresh 25&amp;quot; where 25 in my case is the bundle number for reverser-client web application&lt;br /&gt;
* note that your change is now reflected on page in browser (refresh the page as it may be cached)&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
&lt;br /&gt;
* we have a full OSGi developmet environment working&lt;br /&gt;
* the roundtrip for sofware maintenance changes is very short as we need to refresh only the compnent we changes (we do not need to restart the whole platform)&lt;br /&gt;
* we have a solid maven build&lt;br /&gt;
* it works for me and I did not encountered any problems so far&lt;br /&gt;
* I am ready to move forward&lt;/div&gt;</summary>
		<author><name>Danutc</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=Opentaps-osgi&amp;diff=4089</id>
		<title>Opentaps-osgi</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=Opentaps-osgi&amp;diff=4089"/>
		<updated>2009-07-21T07:29:21Z</updated>

		<summary type="html">&lt;p&gt;Danutc: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page provides information about projects at:&lt;br /&gt;
&lt;br /&gt;
svn://svn.opentaps.org/opentaps/branches/danutc-2.0/org.opentaps.osgi&lt;br /&gt;
&lt;br /&gt;
== What is opentaps-osgi? ==&lt;br /&gt;
&lt;br /&gt;
We aim to migrate ofbiz and opentaps to a more modern architecture based on:&lt;br /&gt;
&lt;br /&gt;
* OSGi&lt;br /&gt;
* BPM&lt;br /&gt;
* ESB&lt;br /&gt;
* SCA&lt;br /&gt;
&lt;br /&gt;
It appears that many open source products have been migrated to OSGi. To take full advantage of these products would be desirable to have opentaps and ofbiz restructured as OSGi modules.&lt;br /&gt;
&lt;br /&gt;
Also migration to OSGi enables better architecture and more agile development. I make these statements based on information available on Internet.&lt;br /&gt;
&lt;br /&gt;
In current build the following features are deployed and illustrated:&lt;br /&gt;
&lt;br /&gt;
* Eclipse Equinox OSGi&lt;br /&gt;
* Spring DM (Dynamic Modules for OSGi development) and Spring Core&lt;br /&gt;
* Tomcat&lt;br /&gt;
* full maven build&lt;br /&gt;
* Eclipse PDE development&lt;br /&gt;
* OSGi Platform maven project build&lt;br /&gt;
* OSGi Extension Projects: log4j configuration, catalina configuration, catalina.start.osgi configuration&lt;br /&gt;
* Sample OSGi Service using Spring DM&lt;br /&gt;
* Sample Web Application that uses the service above&lt;br /&gt;
&lt;br /&gt;
== Get Started Quickly ==&lt;br /&gt;
&lt;br /&gt;
To get you started please take the following steps:&lt;br /&gt;
&lt;br /&gt;
=== Get your environment ready ===&lt;br /&gt;
I use the following tools:&lt;br /&gt;
&lt;br /&gt;
* eclipse JEE 3.5 Galileo&lt;br /&gt;
* subclipse SVN eclipse plugin that works with m2eclipse maven eclipse plugin ( http://subclipse.tigris.org/update_1.6.x )&lt;br /&gt;
* m2eclipse maven eclipse plugin ( http://m2eclipse.sonatype.org/update/ )&lt;br /&gt;
* java sdk 1.6.0_14&lt;br /&gt;
&lt;br /&gt;
=== Checkout the code ===&lt;br /&gt;
&lt;br /&gt;
* start eclipse and create a new workspace&lt;br /&gt;
* open SVN Repository Exploring perspective&lt;br /&gt;
* Add SVN Repository: svn://svn.opentaps.org/opentaps&lt;br /&gt;
* File -&amp;gt; Import -&amp;gt; Maven -&amp;gt; Checkout as Maven project from SCM&amp;lt;br /&amp;gt;&lt;br /&gt;
- SCM URL: svn&amp;lt;br /&amp;gt;&lt;br /&gt;
- svn://svn.opentaps.org/opentaps/branches/danutc-2.0/org.opentaps.osgi/trunk&lt;br /&gt;
* click Finish button&lt;br /&gt;
* after the import is finished switch to JEE perspectiv; you should see the following projects:&lt;br /&gt;
apps&amp;lt;br /&amp;gt;&lt;br /&gt;
catalina.config&amp;lt;br /&amp;gt;&lt;br /&gt;
catalina.start.osgi.config&amp;lt;br /&amp;gt;&lt;br /&gt;
lib&amp;lt;br /&amp;gt;&lt;br /&gt;
log4j.config&amp;lt;br /&amp;gt;&lt;br /&gt;
opentaps-erp-crm&amp;lt;br /&amp;gt;&lt;br /&gt;
platform&amp;lt;br /&amp;gt;&lt;br /&gt;
reverser&amp;lt;br /&amp;gt;&lt;br /&gt;
reverser-client.war&amp;lt;br /&amp;gt;&lt;br /&gt;
sample&lt;br /&gt;
* the projects are already connected to svn&lt;br /&gt;
&lt;br /&gt;
=== Build the Projects ===&lt;br /&gt;
&lt;br /&gt;
* open opentaps-erp-crm&lt;br /&gt;
* right click on pom.xml and select Run As Maven build ...&lt;br /&gt;
* Goals: clean compile package install&lt;br /&gt;
* click Apply then Run buttons&lt;br /&gt;
* the first time the build will take long time as it downloads all dependencies from Internet&lt;br /&gt;
* after BUILD SUCCESSFUL message on console select all projects and refresh them to be in synch with the build&lt;br /&gt;
* in the problem window eclipse reports errors that will be fixed as soon as we configure the environment&lt;br /&gt;
&lt;br /&gt;
=== Configure the OSGi Environment and run opentaps-osgi ===&lt;br /&gt;
&lt;br /&gt;
We need to install the OSGi Platform in PDE.&lt;br /&gt;
* Window -&amp;gt; Preferences -&amp;gt; Plug-in Development -&amp;gt; Target Platform click Add... button&lt;br /&gt;
* Nothing: Start with empty target definition the click Next button&lt;br /&gt;
* click Add button to add a new location&lt;br /&gt;
* select Installation then click Next&lt;br /&gt;
* location: ${workspace_loc}/opentaps-erp-crm/platform/target/platform and click Nex&lt;br /&gt;
* You should see a list of 49 plug-ins that are loaded from platform project; click Finish and Finish&lt;br /&gt;
* Select New Target Platform check box and click Apply button then OK button&lt;br /&gt;
* Now in the Problems window all compilation errors should be gone; there are some XML errors that are not important&lt;br /&gt;
&lt;br /&gt;
=== Run the Platform ===&lt;br /&gt;
&lt;br /&gt;
* click on Run Configurations... drop down menu&lt;br /&gt;
* select OSGi Framework and click New&lt;br /&gt;
* Name: opentaps-osgi&lt;br /&gt;
* there are 5 workspace projects and 49 Target Platform plug-ins selected&lt;br /&gt;
* click Validate Bundles button and there should be no problems found (make sure all bundles are selected)&lt;br /&gt;
* click Run button and watch the console window for logs&lt;br /&gt;
* focus on console window and type ss to see the list of active bundles (notice catalina, reverser and reverser-client)&lt;br /&gt;
* type status to see a more comprehensive information&lt;br /&gt;
* in browser go to http://localhost:8888/reverser-client/&lt;br /&gt;
* enter a string and click Reverse String button&lt;br /&gt;
* it displays the reversed string (also watch the console window)&lt;br /&gt;
* click on browser back button and enter a new string&lt;br /&gt;
&lt;br /&gt;
=== Software Maintenance ===&lt;br /&gt;
&lt;br /&gt;
==== Change the reverser OSGi Service ====&lt;br /&gt;
&lt;br /&gt;
* type ss in console window and note the bundle numbers for reverser and reverser-client bundles (4 and 25 in my current run)&lt;br /&gt;
* in reverser project go and modify reverse method in org.springframework.osgi.sample.service.impl.StringReverserImpl&amp;lt;br /&amp;gt;&lt;br /&gt;
return &amp;quot; &amp;gt;&amp;gt;&amp;gt; &amp;quot; + reveresed;&lt;br /&gt;
* save the file&lt;br /&gt;
* notice that the web application did not pick the change yet (try to reverse more strings)&lt;br /&gt;
* in console window type &amp;quot;refresh 4&amp;quot; where 4 in my case is the bundle number for reverser OSGi service&lt;br /&gt;
* try to reverse more strings and notice that the message on screen reflects your change&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Change the reverser-client Web Application ====&lt;br /&gt;
&lt;br /&gt;
* do a change in file reverser-client.war\src\main\webapp\index.jsp&lt;br /&gt;
* please note that the change is not activated yet&lt;br /&gt;
* right click on reverser-client.war/pom.xml and select Run As... -&amp;gt; Maven Build ...&lt;br /&gt;
* Goals: clean compile package install&lt;br /&gt;
* click Apply and Run buttons&lt;br /&gt;
* in osgi console window type &amp;quot;refresh 25&amp;quot; where 25 in my case is the bundle number for reverser-client web application&lt;br /&gt;
* note that your change is now reflected on page in browser&lt;/div&gt;</summary>
		<author><name>Danutc</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=Opentaps-osgi&amp;diff=4088</id>
		<title>Opentaps-osgi</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=Opentaps-osgi&amp;diff=4088"/>
		<updated>2009-07-21T07:09:39Z</updated>

		<summary type="html">&lt;p&gt;Danutc: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page provides information about projects at:&lt;br /&gt;
&lt;br /&gt;
svn://svn.opentaps.org/opentaps/branches/danutc-2.0/org.opentaps.osgi&lt;br /&gt;
&lt;br /&gt;
== What is opentaps-osgi? ==&lt;br /&gt;
&lt;br /&gt;
We aim to migrate ofbiz and opentaps to a more modern architecture based on:&lt;br /&gt;
&lt;br /&gt;
* OSGi&lt;br /&gt;
* BPM&lt;br /&gt;
* ESB&lt;br /&gt;
* SCA&lt;br /&gt;
&lt;br /&gt;
It appears that many open source products have been migrated to OSGi. To take full advantage of these products would be desirable to have opentaps and ofbiz restructured as OSGi modules.&lt;br /&gt;
&lt;br /&gt;
Also migration to OSGi enables better architecture and more agile development. I make these statements based on information available on Internet.&lt;br /&gt;
&lt;br /&gt;
In current build the following features are deployed and illustrated:&lt;br /&gt;
&lt;br /&gt;
* Eclipse Equinox OSGi&lt;br /&gt;
* Spring DM (Dynamic Modules for OSGi development) and Spring Core&lt;br /&gt;
* Tomcat&lt;br /&gt;
* full maven build&lt;br /&gt;
* Eclipse PDE development&lt;br /&gt;
* OSGi Platform maven project build&lt;br /&gt;
* OSGi Extension Projects: log4j configuration, catalina configuration, catalina.start.osgi configuration&lt;br /&gt;
* Sample OSGi Service using Spring DM&lt;br /&gt;
* Sample Web Application that uses the service above&lt;br /&gt;
&lt;br /&gt;
== Get Started Quickly ==&lt;br /&gt;
&lt;br /&gt;
To get you started please take the following steps:&lt;br /&gt;
&lt;br /&gt;
=== Get your environment ready ===&lt;br /&gt;
I use the following tools:&lt;br /&gt;
&lt;br /&gt;
* eclipse JEE 3.5 Galileo&lt;br /&gt;
* subclipse SVN eclipse plugin that works with m2eclipse maven eclipse plugin ( http://subclipse.tigris.org/update_1.6.x )&lt;br /&gt;
* m2eclipse maven eclipse plugin ( http://m2eclipse.sonatype.org/update/ )&lt;br /&gt;
* java sdk 1.6.0_14&lt;br /&gt;
&lt;br /&gt;
=== Checkout the code ===&lt;br /&gt;
&lt;br /&gt;
* start eclipse and create a new workspace&lt;br /&gt;
* open SVN Repository Exploring perspective&lt;br /&gt;
* Add SVN Repository: svn://svn.opentaps.org/opentaps&lt;br /&gt;
* File -&amp;gt; Import -&amp;gt; Maven -&amp;gt; Checkout as Maven project from SCM&amp;lt;br /&amp;gt;&lt;br /&gt;
- SCM URL: svn&amp;lt;br /&amp;gt;&lt;br /&gt;
- svn://svn.opentaps.org/opentaps/branches/danutc-2.0/org.opentaps.osgi/trunk&lt;br /&gt;
* click Finish button&lt;br /&gt;
* after the import is finished switch to JEE perspectiv; you should see the following projects:&lt;br /&gt;
apps&amp;lt;br /&amp;gt;&lt;br /&gt;
catalina.config&amp;lt;br /&amp;gt;&lt;br /&gt;
catalina.start.osgi.config&amp;lt;br /&amp;gt;&lt;br /&gt;
lib&amp;lt;br /&amp;gt;&lt;br /&gt;
log4j.config&amp;lt;br /&amp;gt;&lt;br /&gt;
opentaps-erp-crm&amp;lt;br /&amp;gt;&lt;br /&gt;
platform&amp;lt;br /&amp;gt;&lt;br /&gt;
reverser&amp;lt;br /&amp;gt;&lt;br /&gt;
reverser-client.war&amp;lt;br /&amp;gt;&lt;br /&gt;
sample&lt;br /&gt;
* the projects are already connected to svn&lt;br /&gt;
&lt;br /&gt;
=== Build the Projects ===&lt;br /&gt;
&lt;br /&gt;
* open opentaps-erp-crm&lt;br /&gt;
* right click on pom.xml and select Run As Maven build ...&lt;br /&gt;
* Goals: clean compile package install&lt;br /&gt;
* click Apply then Run buttons&lt;br /&gt;
* the first time the build will take long time as it downloads all dependencies from Internet&lt;br /&gt;
* after BUILD SUCCESSFUL message on console select all projects and refresh them to be in synch with the build&lt;br /&gt;
* in the problem window eclipse reports errors that will be fixed as soon as we configure the environment&lt;br /&gt;
&lt;br /&gt;
=== Configure the OSGi Environment and run opentaps-osgi ===&lt;br /&gt;
&lt;br /&gt;
We need to install the OSGi Platform in PDE.&lt;br /&gt;
* Window -&amp;gt; Preferences -&amp;gt; Plug-in Development -&amp;gt; Target Platform click Add... button&lt;br /&gt;
* Nothing: Start with empty target definition the click Next button&lt;br /&gt;
* click Add button to add a new location&lt;br /&gt;
* select Installation then click Next&lt;br /&gt;
* location: ${workspace_loc}/opentaps-erp-crm/platform/target/platform and click Nex&lt;br /&gt;
* You should see a list of 49 plug-ins that are loaded from platform project; click Finish and Finish&lt;br /&gt;
* Select New Target Platform check box and click Apply button then OK button&lt;br /&gt;
* Now in the Problems window all compilation errors should be gone; there are some XML errors that are not important&lt;br /&gt;
&lt;br /&gt;
=== Run the Platform ===&lt;br /&gt;
&lt;br /&gt;
* click on Run Configurations... drop down menu&lt;br /&gt;
* select OSGi Framework and click New&lt;br /&gt;
* Name: opentaps-osgi&lt;br /&gt;
* there are 5 workspace projects and 49 Target Platform plug-ins selected&lt;br /&gt;
* click Validate Bundles button and there should be no problems found (make sure all bundles are selected)&lt;br /&gt;
* click Run button and watch the console window for logs&lt;br /&gt;
* focus on console window and type ss to see the list of active bundles (notice catalina, reverser and reverser-client)&lt;br /&gt;
* type status to see a more comprehensive information&lt;br /&gt;
* in browser go to http://localhost:8888/reverser-client/&lt;br /&gt;
* enter a string and click Reverse String button&lt;br /&gt;
* it displays the reversed string (also watch the console window)&lt;br /&gt;
* click on browser back button and enter a new string&lt;/div&gt;</summary>
		<author><name>Danutc</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=Opentaps-osgi&amp;diff=4087</id>
		<title>Opentaps-osgi</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=Opentaps-osgi&amp;diff=4087"/>
		<updated>2009-07-21T06:48:27Z</updated>

		<summary type="html">&lt;p&gt;Danutc: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page provides information about projects at:&lt;br /&gt;
&lt;br /&gt;
svn://svn.opentaps.org/opentaps/branches/danutc-2.0/org.opentaps.osgi&lt;br /&gt;
&lt;br /&gt;
== What is opentaps-osgi? ==&lt;br /&gt;
&lt;br /&gt;
We aim to migrate ofbiz and opentaps to a more modern architecture based on:&lt;br /&gt;
&lt;br /&gt;
* OSGi&lt;br /&gt;
* BPM&lt;br /&gt;
* ESB&lt;br /&gt;
* SCA&lt;br /&gt;
&lt;br /&gt;
It appears that many open source products have been migrated to OSGi. To take full advantage of these products would be desirable to have opentaps and ofbiz restructured as OSGi modules.&lt;br /&gt;
&lt;br /&gt;
Also migration to OSGi enables better architecture and more agile development. I make these statements based on information available on Internet.&lt;br /&gt;
&lt;br /&gt;
In current build the following features are deployed and illustrated:&lt;br /&gt;
&lt;br /&gt;
* Eclipse Equinox OSGi&lt;br /&gt;
* Spring DM (Dynamic Modules for OSGi development) and Spring Core&lt;br /&gt;
* Tomcat&lt;br /&gt;
* full maven build&lt;br /&gt;
* Eclipse PDE development&lt;br /&gt;
* OSGi Platform maven project build&lt;br /&gt;
* OSGi Extension Projects: log4j configuration, catalina configuration, catalina.start.osgi configuration&lt;br /&gt;
* Sample OSGi Service using Spring DM&lt;br /&gt;
* Sample Web Application that uses the service above&lt;br /&gt;
&lt;br /&gt;
== Get Started Quickly ==&lt;br /&gt;
&lt;br /&gt;
To get you started please take the following steps:&lt;br /&gt;
&lt;br /&gt;
=== Get your environment ready ===&lt;br /&gt;
I use the following tools:&lt;br /&gt;
&lt;br /&gt;
* eclipse JEE 3.5 Galileo&lt;br /&gt;
* subclipse SVN eclipse plugin that works with m2eclipse maven eclipse plugin ( http://subclipse.tigris.org/update_1.6.x )&lt;br /&gt;
* m2eclipse maven eclipse plugin ( http://m2eclipse.sonatype.org/update/ )&lt;br /&gt;
* java sdk 1.6.0_14&lt;br /&gt;
&lt;br /&gt;
=== Checkout the code ===&lt;br /&gt;
&lt;br /&gt;
* start eclipse and create a new workspace&lt;br /&gt;
* open SVN Repository Exploring perspective&lt;br /&gt;
* Add SVN Repository: svn://svn.opentaps.org/opentaps&lt;br /&gt;
* File -&amp;gt; Import -&amp;gt; Maven -&amp;gt; Checkout as Maven project from SCM&amp;lt;br /&amp;gt;&lt;br /&gt;
- SCM URL: svn&amp;lt;br /&amp;gt;&lt;br /&gt;
- svn://svn.opentaps.org/opentaps/branches/danutc-2.0/org.opentaps.osgi/trunk&lt;br /&gt;
* click Finish button&lt;br /&gt;
* after the import is finished switch to JEE perspectiv; you should see the following projects:&lt;br /&gt;
apps&amp;lt;br /&amp;gt;&lt;br /&gt;
catalina.config&amp;lt;br /&amp;gt;&lt;br /&gt;
catalina.start.osgi.config&amp;lt;br /&amp;gt;&lt;br /&gt;
lib&amp;lt;br /&amp;gt;&lt;br /&gt;
log4j.config&amp;lt;br /&amp;gt;&lt;br /&gt;
opentaps-erp-crm&amp;lt;br /&amp;gt;&lt;br /&gt;
platform&amp;lt;br /&amp;gt;&lt;br /&gt;
reverser&amp;lt;br /&amp;gt;&lt;br /&gt;
reverser-client.war&amp;lt;br /&amp;gt;&lt;br /&gt;
sample&lt;br /&gt;
* the projects are already connected to svn&lt;br /&gt;
&lt;br /&gt;
=== Build the Projects ===&lt;br /&gt;
&lt;br /&gt;
* open opentaps-erp-crm&lt;br /&gt;
* right click on pom.xml and select Run As Maven build ...&lt;br /&gt;
* Goals: clean compile package install&lt;br /&gt;
* click Apply then Run buttons&lt;br /&gt;
* after BUILD SUCCESSFUL message on console select all projects and refresh them to be in synch with the build&lt;br /&gt;
* in the problem window eclipse reports errors that will be fixed as soon as we configure the environment&lt;br /&gt;
&lt;br /&gt;
=== Configure the OSGi Environment and run opentaps-osgi ===&lt;/div&gt;</summary>
		<author><name>Danutc</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=Opentaps-osgi&amp;diff=4086</id>
		<title>Opentaps-osgi</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=Opentaps-osgi&amp;diff=4086"/>
		<updated>2009-07-21T06:35:19Z</updated>

		<summary type="html">&lt;p&gt;Danutc: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page provides information about projects at:&lt;br /&gt;
&lt;br /&gt;
svn://svn.opentaps.org/opentaps/branches/danutc-2.0/org.opentaps.osgi&lt;br /&gt;
&lt;br /&gt;
== What is opentaps-osgi? ==&lt;br /&gt;
&lt;br /&gt;
We aim to migrate ofbiz and opentaps to a more modern architecture based on:&lt;br /&gt;
&lt;br /&gt;
* OSGi&lt;br /&gt;
* BPM&lt;br /&gt;
* ESB&lt;br /&gt;
* SCA&lt;br /&gt;
&lt;br /&gt;
It appears that many open source products have been migrated to OSGi. To take full advantage of these products would be desirable to have opentaps and ofbiz restructured as OSGi modules.&lt;br /&gt;
&lt;br /&gt;
Also migration to OSGi enables better architecture and more agile development. I make these statements based on information available on Internet.&lt;br /&gt;
&lt;br /&gt;
In current build the following features are deployed and illustrated:&lt;br /&gt;
&lt;br /&gt;
* Eclipse Equinox OSGi&lt;br /&gt;
* Spring DM (Dynamic Modules for OSGi development) and Spring Core&lt;br /&gt;
* Tomcat&lt;br /&gt;
* full maven build&lt;br /&gt;
* Eclipse PDE development&lt;br /&gt;
* OSGi Platform maven project build&lt;br /&gt;
* OSGi Extension Projects: log4j configuration, catalina configuration, catalina.start.osgi configuration&lt;br /&gt;
* Sample OSGi Service using Spring DM&lt;br /&gt;
* Sample Web Application that uses the service above&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Get Started Quickly ==&lt;br /&gt;
&lt;br /&gt;
To get you started please take the following steps:&lt;br /&gt;
&lt;br /&gt;
=== Get your environment ready ===&lt;br /&gt;
I use the following tools:&lt;br /&gt;
&lt;br /&gt;
* eclipse JEE 3.5 Galileo&lt;br /&gt;
* subclipse SVN eclipse plugin that works with m2eclipse maven eclipse plugin ( http://subclipse.tigris.org/update_1.6.x )&lt;br /&gt;
* m2eclipse maven eclipse plugin ( http://m2eclipse.sonatype.org/update/ )&lt;br /&gt;
* java sdk 1.6.0_14&lt;br /&gt;
&lt;br /&gt;
=== Checkout the code ===&lt;br /&gt;
&lt;br /&gt;
* start eclipse and create a new workspace&lt;br /&gt;
* open SVN Repository Exploring perspective&lt;br /&gt;
* Add SVN Repository: svn://svn.opentaps.org/opentaps&lt;br /&gt;
* File -&amp;gt; Import -&amp;gt; Maven -&amp;gt; Checkout as Maven project from SCM&amp;lt;br /&amp;gt;&lt;br /&gt;
SCM URL: svn&amp;lt;br /&amp;gt;&lt;br /&gt;
svn://svn.opentaps.org/opentaps/branches/danutc-2.0/org.opentaps.osgi/trunk&amp;lt;br /&amp;gt;&lt;br /&gt;
* click Finish button&lt;/div&gt;</summary>
		<author><name>Danutc</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=Opentaps-osgi&amp;diff=4085</id>
		<title>Opentaps-osgi</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=Opentaps-osgi&amp;diff=4085"/>
		<updated>2009-07-21T06:15:45Z</updated>

		<summary type="html">&lt;p&gt;Danutc: Protected &amp;quot;Opentaps-osgi&amp;quot;: Sysop page [edit=sysop:move=sysop]&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page provides information about projects at:&lt;br /&gt;
&lt;br /&gt;
svn://svn.opentaps.org/opentaps/branches/danutc-2.0/org.opentaps.osgi&lt;br /&gt;
&lt;br /&gt;
== What is it? ==&lt;br /&gt;
&lt;br /&gt;
We aim to move ofbiz and opentaps on a more modern architecture based on:&lt;br /&gt;
&lt;br /&gt;
* OSGi&lt;br /&gt;
* BPM&lt;br /&gt;
* ESB&lt;br /&gt;
* SCA&lt;br /&gt;
&lt;br /&gt;
It appears that many open source products have been migrated to OSGi. To take full advantage of these products would be desirable to have opentaps and ofbiz restructured in OSGi modules.&lt;br /&gt;
&lt;br /&gt;
Also migration to OSGi enables better architecture and more agile development. I make these statements based on information available on Internet.&lt;br /&gt;
&lt;br /&gt;
In current build the following features are deployed and illustrated:&lt;br /&gt;
&lt;br /&gt;
* Equinox OSGi&lt;br /&gt;
* Spring DM (Dynamic Modules for OSGi development) and Spring Core&lt;br /&gt;
* Tomcat&lt;br /&gt;
* full maven build&lt;br /&gt;
* eclipse PDE development&lt;br /&gt;
* OSGi Platform maven project&lt;br /&gt;
* OSGi Extension projects: log4j configuration, catalina configuration, catalina.start.osgi configuration&lt;br /&gt;
* Sample OSGi Service using Spring DM&lt;br /&gt;
* Sample Web Application that uses the service above&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Get Started Quickly ==&lt;/div&gt;</summary>
		<author><name>Danutc</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=Opentaps-osgi&amp;diff=4084</id>
		<title>Opentaps-osgi</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=Opentaps-osgi&amp;diff=4084"/>
		<updated>2009-07-21T06:15:44Z</updated>

		<summary type="html">&lt;p&gt;Danutc: New page: This page provides information about projects at:  svn://svn.opentaps.org/opentaps/branches/danutc-2.0/org.opentaps.osgi  == What is it? ==  We aim to move ofbiz and opentaps on a more mod...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page provides information about projects at:&lt;br /&gt;
&lt;br /&gt;
svn://svn.opentaps.org/opentaps/branches/danutc-2.0/org.opentaps.osgi&lt;br /&gt;
&lt;br /&gt;
== What is it? ==&lt;br /&gt;
&lt;br /&gt;
We aim to move ofbiz and opentaps on a more modern architecture based on:&lt;br /&gt;
&lt;br /&gt;
* OSGi&lt;br /&gt;
* BPM&lt;br /&gt;
* ESB&lt;br /&gt;
* SCA&lt;br /&gt;
&lt;br /&gt;
It appears that many open source products have been migrated to OSGi. To take full advantage of these products would be desirable to have opentaps and ofbiz restructured in OSGi modules.&lt;br /&gt;
&lt;br /&gt;
Also migration to OSGi enables better architecture and more agile development. I make these statements based on information available on Internet.&lt;br /&gt;
&lt;br /&gt;
In current build the following features are deployed and illustrated:&lt;br /&gt;
&lt;br /&gt;
* Equinox OSGi&lt;br /&gt;
* Spring DM (Dynamic Modules for OSGi development) and Spring Core&lt;br /&gt;
* Tomcat&lt;br /&gt;
* full maven build&lt;br /&gt;
* eclipse PDE development&lt;br /&gt;
* OSGi Platform maven project&lt;br /&gt;
* OSGi Extension projects: log4j configuration, catalina configuration, catalina.start.osgi configuration&lt;br /&gt;
* Sample OSGi Service using Spring DM&lt;br /&gt;
* Sample Web Application that uses the service above&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Get Started Quickly ==&lt;/div&gt;</summary>
		<author><name>Danutc</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=User_talk:Danutc&amp;diff=4083</id>
		<title>User talk:Danutc</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=User_talk:Danutc&amp;diff=4083"/>
		<updated>2009-07-21T05:56:04Z</updated>

		<summary type="html">&lt;p&gt;Danutc: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* [[BPM Integration]]&lt;br /&gt;
* [[BPM - Getting Started]]&lt;br /&gt;
* [[jBPM - Opentaps 1.x Integration Prototype]]&lt;br /&gt;
* [[Magento 1.x - Opentaps 1.x Integration Prototype]]&lt;br /&gt;
* [[opentaps-osgi]]&lt;br /&gt;
* [[danc - temp]]&lt;/div&gt;</summary>
		<author><name>Danutc</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=JBPM_-_Opentaps_1.x_Integration_Prototype&amp;diff=4011</id>
		<title>JBPM - Opentaps 1.x Integration Prototype</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=JBPM_-_Opentaps_1.x_Integration_Prototype&amp;diff=4011"/>
		<updated>2009-06-24T02:41:01Z</updated>

		<summary type="html">&lt;p&gt;Danutc: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;To get started with BPM we decided to investigate how to integrate an existing BPM implementation, jBPM, with opentaps 1.4. As jBPM 4 is scheduled for release in July 2009 we decided to use beta 2 version for this prototype (latest jBPM build available at the time of this writing).&lt;br /&gt;
&lt;br /&gt;
For the communication between opentaps and jBPM we use Apache Tuscany 1.5 SCA ESB. The SCA bidirectional interface provides a direct call and a callback interface; jBPM can call opentaps and opentaps can fire events (callbacks) to jBPM.&lt;br /&gt;
&lt;br /&gt;
Apache Tuscany is deployable as a set of OSGi bundles; we will embed Apache Felix OSGi runtime in opentaps and we will deploy Apache Tuscany as OSGi bundles. This will further enhance the extensibility options for opentaps.&lt;br /&gt;
&lt;br /&gt;
We will implement the following business process: The sales person creates a quote. if the quote price (QP) is up to 5% below recommended retail price (QRRP) then she can submit the quote to customer otherwise she needs manager approval. The quote is converted to order and send to manufacturing after the customer deposited 50% of quoted price.&lt;br /&gt;
&lt;br /&gt;
Main scenario looks like this:&lt;br /&gt;
* sales person: creates quote&lt;br /&gt;
* if QP &amp;lt; 95% QRRP&lt;br /&gt;
** manager: approves quote&lt;br /&gt;
* else&lt;br /&gt;
** BPM: approves quote automatically&lt;br /&gt;
* accounts receivable: receives 50% QP deposit&lt;br /&gt;
* accounts receivable: convert quote to order&lt;br /&gt;
&lt;br /&gt;
The steps are:&lt;br /&gt;
* opentaps: fires an event to jBPM when a new quote is created (passing QP and QRRP to jBPM)&lt;br /&gt;
* jBPM: if QP &amp;lt; 95% QRRP&lt;br /&gt;
** jBPM: assign quote to manager for approval&lt;br /&gt;
* jBPM: assign quote to accounts receivable officer to monitor for 50% QP deposit&lt;br /&gt;
* accounts receivable officer: updates jBPM when 50% QP is received&lt;br /&gt;
* jBPM: calls opentaps to convert quote to order&lt;br /&gt;
&lt;br /&gt;
Relevant information can be found at:&lt;br /&gt;
&lt;br /&gt;
* [http://tuscany.apache.org/ Apache Tuscany SCA / ESB]&lt;br /&gt;
* [http://www.davidchappell.com/articles/Introducing_SCA.pdf INTRODUCING SCA]&lt;br /&gt;
* [http://tuscany.apache.org/sca-java-web-applications.html Using Tuscany in JEE Web Applications]&lt;br /&gt;
* [http://tuscany.apache.org/distributed-sca-domain.html Create A SCA Distributed Application]&lt;br /&gt;
* [http://cwiki.apache.org/TUSCANYWIKI/tuscany-web-application-based-integration-with-geronimo.html Tuscany Web Application based Integration with Geronimo]&lt;br /&gt;
* [http://www.theserverside.com/tt/articles/article.tss?l=MigratingPathToOSGi Modularizing Existing Web Applications With OSGi: A Migration Path to OSGi]&lt;br /&gt;
* [http://tuscany.apache.org/osgi-aware-programming-in-tuscany.html OSGi Aware Programming in Tuscany : Apache Tuscany]&lt;br /&gt;
* [http://felix.apache.org/site/apache-felix-framework-launching-and-embedding.html Apache Felix Framework Launching and Embedding]&lt;br /&gt;
* [http://s3.amazonaws.com/neilbartlett.name/osgibook_preview_20090110.pdf OSGi Book Preview]&lt;br /&gt;
* [http://apache-tuscany.blogspot.com/2009/03/closer-look-osgi-enablement-for-tuscany.html A Closer Look - OSGi Enablement for Tuscany 2.0]&lt;br /&gt;
&lt;br /&gt;
== The Prototype ==&lt;br /&gt;
&lt;br /&gt;
[[Image:jBPM.4b2_opentaps.1.4_Integration.png]]&lt;br /&gt;
&lt;br /&gt;
Details about my investigations are coming soon ...&lt;/div&gt;</summary>
		<author><name>Danutc</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=JBPM_-_Opentaps_1.x_Integration_Prototype&amp;diff=3999</id>
		<title>JBPM - Opentaps 1.x Integration Prototype</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=JBPM_-_Opentaps_1.x_Integration_Prototype&amp;diff=3999"/>
		<updated>2009-06-17T23:37:55Z</updated>

		<summary type="html">&lt;p&gt;Danutc: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;To get started with BPM we decided to investigate how to integrate an existing BPM implementation, jBPM, with opentaps 1.4. As jBPM 4 is scheduled for release in July 2009 we decided to use beta 2 version for this prototype (latest jBPM build available at the time of this writing).&lt;br /&gt;
&lt;br /&gt;
For the communication between opentaps and jBPM we use Apache Tuscany 1.5 SCA ESB. The SCA bidirectional interface provides a direct call and a callback interface; jBPM can call opentaps and opentaps can fire events (callbacks) to jBPM.&lt;br /&gt;
&lt;br /&gt;
We will implement the following business process: The sales person creates a quote. if the quote price (QP) is up to 5% below recommended retail price (QRRP) then she can submit the quote to customer otherwise she needs manager approval. The quote is converted to order and send to manufacturing after the customer deposited 50% of quoted price.&lt;br /&gt;
&lt;br /&gt;
Main scenario looks like this:&lt;br /&gt;
* sales person: creates quote&lt;br /&gt;
* if QP &amp;lt; 95% QRRP&lt;br /&gt;
** manager: approves quote&lt;br /&gt;
* else&lt;br /&gt;
** BPM: approves quote automatically&lt;br /&gt;
* accounts receivable: receives 50% QP deposit&lt;br /&gt;
* accounts receivable: convert quote to order&lt;br /&gt;
&lt;br /&gt;
The steps are:&lt;br /&gt;
* opentaps: fires an event to jBPM when a new quote is created (passing QP and QRRP to jBPM)&lt;br /&gt;
* jBPM: if QP &amp;lt; 95% QRRP&lt;br /&gt;
** jBPM: assign quote to manager for approval&lt;br /&gt;
* jBPM: assign quote to accounts receivable officer to monitor for 50% QP deposit&lt;br /&gt;
* accounts receivable officer: updates jBPM when 50% QP is received&lt;br /&gt;
* jBPM: calls opentaps to convert quote to order&lt;br /&gt;
&lt;br /&gt;
Relevant information can be found at:&lt;br /&gt;
&lt;br /&gt;
* [http://tuscany.apache.org/ Apache Tuscany SCA / ESB]&lt;br /&gt;
* [http://www.davidchappell.com/articles/Introducing_SCA.pdf INTRODUCING SCA]&lt;br /&gt;
* [http://tuscany.apache.org/sca-java-web-applications.html Using Tuscany in JEE Web Applications]&lt;br /&gt;
* [http://tuscany.apache.org/distributed-sca-domain.html Create A SCA Distributed Application]&lt;br /&gt;
* [http://cwiki.apache.org/TUSCANYWIKI/tuscany-web-application-based-integration-with-geronimo.html Tuscany Web Application based Integration with Geronimo]&lt;br /&gt;
* [http://www.theserverside.com/tt/articles/article.tss?l=MigratingPathToOSGi Modularizing Existing Web Applications With OSGi: A Migration Path to OSGi]&lt;br /&gt;
* [http://tuscany.apache.org/osgi-aware-programming-in-tuscany.html OSGi Aware Programming in Tuscany : Apache Tuscany]&lt;br /&gt;
* [http://felix.apache.org/site/apache-felix-framework-launching-and-embedding.html Apache Felix Framework Launching and Embedding]&lt;br /&gt;
* [http://s3.amazonaws.com/neilbartlett.name/osgibook_preview_20090110.pdf OSGi Book Preview]&lt;br /&gt;
* [http://apache-tuscany.blogspot.com/2009/03/closer-look-osgi-enablement-for-tuscany.html A Closer Look - OSGi Enablement for Tuscany 2.0]&lt;br /&gt;
&lt;br /&gt;
== The Prototype ==&lt;br /&gt;
&lt;br /&gt;
[[Image:jBPM.4b2_opentaps.1.4_Integration.png]]&lt;br /&gt;
&lt;br /&gt;
Details about my investigations are coming soon ...&lt;/div&gt;</summary>
		<author><name>Danutc</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=JBPM_-_Opentaps_1.x_Integration_Prototype&amp;diff=3998</id>
		<title>JBPM - Opentaps 1.x Integration Prototype</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=JBPM_-_Opentaps_1.x_Integration_Prototype&amp;diff=3998"/>
		<updated>2009-06-17T07:45:22Z</updated>

		<summary type="html">&lt;p&gt;Danutc: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;To get started with BPM we decided to investigate how to integrate an existing BPM implementation, jBPM, with opentaps 1.4. As jBPM 4 is scheduled for release in July 2009 we decided to use beta 2 version for this prototype (latest jBPM build available at the time of this writing).&lt;br /&gt;
&lt;br /&gt;
For the communication between opentaps and jBPM we use Apache Tuscany 1.5 SCA ESB. The SCA bidirectional interface provides a direct call and a callback interface; jBPM can call opentaps and opentaps can fire events (callbacks) to jBPM.&lt;br /&gt;
&lt;br /&gt;
We will implement the following business process: The sales person creates a quote. if the quote price (QP) is up to 5% below recommended retail price (QRRP) then she can submit the quote to customer otherwise she needs manager approval. The quote is converted to order and send to manufacturing after the customer deposited 50% of quoted price.&lt;br /&gt;
&lt;br /&gt;
Main scenario looks like this:&lt;br /&gt;
* sales person: creates quote&lt;br /&gt;
* if QP &amp;lt; 95% QRRP&lt;br /&gt;
** manager: approves quote&lt;br /&gt;
* else&lt;br /&gt;
** BPM: approves quote automatically&lt;br /&gt;
* accounts receivable: receives 50% QP deposit&lt;br /&gt;
* accounts receivable: convert quote to order&lt;br /&gt;
&lt;br /&gt;
The steps are:&lt;br /&gt;
* opentaps: fires an event to jBPM when a new quote is created (passing QP and QRRP to jBPM)&lt;br /&gt;
* jBPM: if QP &amp;lt; 95% QRRP&lt;br /&gt;
** jBPM: assign quote to manager for approval&lt;br /&gt;
* jBPM: assign quote to accounts receivable officer to monitor for 50% QP deposit&lt;br /&gt;
* accounts receivable officer: updates jBPM when 50% QP is received&lt;br /&gt;
* jBPM: calls opentaps to convert quote to order&lt;br /&gt;
&lt;br /&gt;
Relevant information can be found at:&lt;br /&gt;
&lt;br /&gt;
* [http://tuscany.apache.org/ Apache Tuscany SCA / ESB]&lt;br /&gt;
* [http://www.davidchappell.com/articles/Introducing_SCA.pdf INTRODUCING SCA]&lt;br /&gt;
* [http://tuscany.apache.org/sca-java-web-applications.html Using Tuscany in JEE Web Applications]&lt;br /&gt;
* [http://tuscany.apache.org/distributed-sca-domain.html Create A SCA Distributed Application]&lt;br /&gt;
* [http://cwiki.apache.org/TUSCANYWIKI/tuscany-web-application-based-integration-with-geronimo.html Tuscany Web Application based Integration with Geronimo]&lt;br /&gt;
* [http://www.theserverside.com/tt/articles/article.tss?l=MigratingPathToOSGi Modularizing Existing Web Applications With OSGi: A Migration Path to OSGi]&lt;br /&gt;
* [http://tuscany.apache.org/osgi-aware-programming-in-tuscany.html OSGi Aware Programming in Tuscany : Apache Tuscany]&lt;br /&gt;
* [http://felix.apache.org/site/apache-felix-framework-launching-and-embedding.html Apache Felix Framework Launching and Embedding]&lt;br /&gt;
* [http://s3.amazonaws.com/neilbartlett.name/osgibook_preview_20090110.pdf OSGi Book Preview]&lt;br /&gt;
&lt;br /&gt;
== The Prototype ==&lt;br /&gt;
&lt;br /&gt;
[[Image:jBPM.4b2_opentaps.1.4_Integration.png]]&lt;br /&gt;
&lt;br /&gt;
Details about my investigations are coming soon ...&lt;/div&gt;</summary>
		<author><name>Danutc</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=JBPM_-_Opentaps_1.x_Integration_Prototype&amp;diff=3997</id>
		<title>JBPM - Opentaps 1.x Integration Prototype</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=JBPM_-_Opentaps_1.x_Integration_Prototype&amp;diff=3997"/>
		<updated>2009-06-17T07:37:55Z</updated>

		<summary type="html">&lt;p&gt;Danutc: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;To get started with BPM we decided to investigate how to integrate an existing BPM implementation, jBPM, with opentaps 1.4. As jBPM 4 is scheduled for release in July 2009 we decided to use beta 2 version for this prototype (latest jBPM build available at the time of this writing).&lt;br /&gt;
&lt;br /&gt;
For the communication between opentaps and jBPM we use Apache Tuscany 1.5 SCA ESB. The SCA bidirectional interface provides a direct call and a callback interface; jBPM can call opentaps and opentaps can fire events (callbacks) to jBPM.&lt;br /&gt;
&lt;br /&gt;
We will implement the following business process: The sales person creates a quote. if the quote price (QP) is up to 5% below recommended retail price (QRRP) then she can submit the quote to customer otherwise she needs manager approval. The quote is converted to order and send to manufacturing after the customer deposited 50% of quoted price.&lt;br /&gt;
&lt;br /&gt;
Main scenario looks like this:&lt;br /&gt;
* sales person: creates quote&lt;br /&gt;
* if QP &amp;lt; 95% QRRP&lt;br /&gt;
** manager: approves quote&lt;br /&gt;
* else&lt;br /&gt;
** BPM: approves quote automatically&lt;br /&gt;
* accounts receivable: receives 50% QP deposit&lt;br /&gt;
* accounts receivable: convert quote to order&lt;br /&gt;
&lt;br /&gt;
The steps are:&lt;br /&gt;
* opentaps: fires an event to jBPM when a new quote is created (passing QP and QRRP to jBPM)&lt;br /&gt;
* jBPM: if QP &amp;lt; 95% QRRP&lt;br /&gt;
** jBPM: assign quote to manager for approval&lt;br /&gt;
* jBPM: assign quote to accounts receivable officer to monitor for 50% QP deposit&lt;br /&gt;
* accounts receivable officer: updates jBPM when 50% QP is received&lt;br /&gt;
* jBPM: calls opentaps to convert quote to order&lt;br /&gt;
&lt;br /&gt;
Relevant information can be found at:&lt;br /&gt;
&lt;br /&gt;
* [http://tuscany.apache.org/ Apache Tuscany SCA / ESB]&lt;br /&gt;
* [http://www.davidchappell.com/articles/Introducing_SCA.pdf INTRODUCING SCA]&lt;br /&gt;
* [http://tuscany.apache.org/sca-java-web-applications.html Using Tuscany in JEE Web Applications]&lt;br /&gt;
* [http://tuscany.apache.org/distributed-sca-domain.html Create A SCA Distributed Application]&lt;br /&gt;
* [http://cwiki.apache.org/TUSCANYWIKI/tuscany-web-application-based-integration-with-geronimo.html Tuscany Web Application based Integration with Geronimo]&lt;br /&gt;
* [http://www.theserverside.com/tt/articles/article.tss?l=MigratingPathToOSGi Modularizing Existing Web Applications With OSGi: A Migration Path to OSGi]&lt;br /&gt;
* [http://tuscany.apache.org/osgi-aware-programming-in-tuscany.html OSGi Aware Programming in Tuscany : Apache Tuscany]&lt;br /&gt;
* [http://felix.apache.org/site/apache-felix-framework-launching-and-embedding.html Apache Felix Framework Launching and Embedding]&lt;br /&gt;
&lt;br /&gt;
== The Prototype ==&lt;br /&gt;
&lt;br /&gt;
[[Image:jBPM.4b2_opentaps.1.4_Integration.png]]&lt;br /&gt;
&lt;br /&gt;
Details about my investigations are coming soon ...&lt;/div&gt;</summary>
		<author><name>Danutc</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=JBPM_-_Opentaps_1.x_Integration_Prototype&amp;diff=3996</id>
		<title>JBPM - Opentaps 1.x Integration Prototype</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=JBPM_-_Opentaps_1.x_Integration_Prototype&amp;diff=3996"/>
		<updated>2009-06-15T08:20:40Z</updated>

		<summary type="html">&lt;p&gt;Danutc: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;To get started with BPM we decided to investigate how to integrate an existing BPM implementation, jBPM, with opentaps 1.4. As jBPM 4 is scheduled for release in July 2009 we decided to use beta 2 version for this prototype (latest jBPM build available at the time of this writing).&lt;br /&gt;
&lt;br /&gt;
For the communication between opentaps and jBPM we use Apache Tuscany 1.5 SCA ESB. The SCA bidirectional interface provides a direct call and a callback interface; jBPM can call opentaps and opentaps can fire events (callbacks) to jBPM.&lt;br /&gt;
&lt;br /&gt;
We will implement the following business process: The sales person creates a quote. if the quote price (QP) is up to 5% below recommended retail price (QRRP) then she can submit the quote to customer otherwise she needs manager approval. The quote is converted to order and send to manufacturing after the customer deposited 50% of quoted price.&lt;br /&gt;
&lt;br /&gt;
Main scenario looks like this:&lt;br /&gt;
* sales person: creates quote&lt;br /&gt;
* if QP &amp;lt; 95% QRRP&lt;br /&gt;
** manager: approves quote&lt;br /&gt;
* else&lt;br /&gt;
** BPM: approves quote automatically&lt;br /&gt;
* accounts receivable: receives 50% QP deposit&lt;br /&gt;
* accounts receivable: convert quote to order&lt;br /&gt;
&lt;br /&gt;
The steps are:&lt;br /&gt;
* opentaps: fires an event to jBPM when a new quote is created (passing QP and QRRP to jBPM)&lt;br /&gt;
* jBPM: if QP &amp;lt; 95% QRRP&lt;br /&gt;
** jBPM: assign quote to manager for approval&lt;br /&gt;
* jBPM: assign quote to accounts receivable officer to monitor for 50% QP deposit&lt;br /&gt;
* accounts receivable officer: updates jBPM when 50% QP is received&lt;br /&gt;
* jBPM: calls opentaps to convert quote to order&lt;br /&gt;
&lt;br /&gt;
Relevant information can be found at:&lt;br /&gt;
&lt;br /&gt;
* [http://tuscany.apache.org/ Apache Tuscany SCA / ESB]&lt;br /&gt;
* [http://www.davidchappell.com/articles/Introducing_SCA.pdf INTRODUCING SCA]&lt;br /&gt;
* [http://tuscany.apache.org/sca-java-web-applications.html Using Tuscany in JEE Web Applications]&lt;br /&gt;
* [http://tuscany.apache.org/distributed-sca-domain.html Create A SCA Distributed Application]&lt;br /&gt;
* [http://cwiki.apache.org/TUSCANYWIKI/tuscany-web-application-based-integration-with-geronimo.html Tuscany Web Application based Integration with Geronimo]&lt;br /&gt;
* [http://www.theserverside.com/tt/articles/article.tss?l=MigratingPathToOSGi Modularizing Existing Web Applications With OSGi: A Migration Path to OSGi]&lt;br /&gt;
* [http://tuscany.apache.org/osgi-aware-programming-in-tuscany.html OSGi Aware Programming in Tuscany : Apache Tuscany]&lt;br /&gt;
&lt;br /&gt;
== The Prototype ==&lt;br /&gt;
&lt;br /&gt;
[[Image:jBPM.4b2_opentaps.1.4_Integration.png]]&lt;br /&gt;
&lt;br /&gt;
Details about my investigations are coming soon ...&lt;/div&gt;</summary>
		<author><name>Danutc</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=JBPM_-_Opentaps_1.x_Integration_Prototype&amp;diff=3995</id>
		<title>JBPM - Opentaps 1.x Integration Prototype</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=JBPM_-_Opentaps_1.x_Integration_Prototype&amp;diff=3995"/>
		<updated>2009-06-15T07:30:21Z</updated>

		<summary type="html">&lt;p&gt;Danutc: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;To get started with BPM we decided to investigate how to integrate an existing BPM implementation, jBPM, with opentaps 1.4. As jBPM 4 is scheduled for release in July 2009 we decided to use beta 2 version for this prototype (latest jBPM build available at the time of this writing).&lt;br /&gt;
&lt;br /&gt;
For the communication between opentaps and jBPM we use Apache Tuscany 1.5 SCA ESB. The SCA bidirectional interface provides a direct call and a callback interface; jBPM can call opentaps and opentaps can fire events (callbacks) to jBPM.&lt;br /&gt;
&lt;br /&gt;
We will implement the following business process: The sales person creates a quote. if the quote price (QP) is up to 5% below recommended retail price (QRRP) then she can submit the quote to customer otherwise she needs manager approval. The quote is converted to order and send to manufacturing after the customer deposited 50% of quoted price.&lt;br /&gt;
&lt;br /&gt;
Main scenario looks like this:&lt;br /&gt;
* sales person: creates quote&lt;br /&gt;
* if QP &amp;lt; 95% QRRP&lt;br /&gt;
** manager: approves quote&lt;br /&gt;
* else&lt;br /&gt;
** BPM: approves quote automatically&lt;br /&gt;
* accounts receivable: receives 50% QP deposit&lt;br /&gt;
* accounts receivable: convert quote to order&lt;br /&gt;
&lt;br /&gt;
The steps are:&lt;br /&gt;
* opentaps: fires an event to jBPM when a new quote is created (passing QP and QRRP to jBPM)&lt;br /&gt;
* jBPM: if QP &amp;lt; 95% QRRP&lt;br /&gt;
** jBPM: assign quote to manager for approval&lt;br /&gt;
* jBPM: assign quote to accounts receivable officer to monitor for 50% QP deposit&lt;br /&gt;
* accounts receivable officer: updates jBPM when 50% QP is received&lt;br /&gt;
* jBPM: calls opentaps to convert quote to order&lt;br /&gt;
&lt;br /&gt;
Relevant information can be found at:&lt;br /&gt;
&lt;br /&gt;
* [http://tuscany.apache.org/ Apache Tuscany SCA / ESB]&lt;br /&gt;
* [http://www.davidchappell.com/articles/Introducing_SCA.pdf INTRODUCING SCA]&lt;br /&gt;
* [http://tuscany.apache.org/sca-java-web-applications.html Using Tuscany in JEE Web Applications]&lt;br /&gt;
* [http://tuscany.apache.org/distributed-sca-domain.html Create A SCA Distributed Application]&lt;br /&gt;
* [http://cwiki.apache.org/TUSCANYWIKI/tuscany-web-application-based-integration-with-geronimo.html Tuscany Web Application based Integration with Geronimo]&lt;br /&gt;
* [http://www.theserverside.com/tt/articles/article.tss?l=MigratingPathToOSGi Modularizing Existing Web Applications With OSGi: A Migration Path to OSGi]&lt;br /&gt;
&lt;br /&gt;
== The Prototype ==&lt;br /&gt;
&lt;br /&gt;
[[Image:jBPM.4b2_opentaps.1.4_Integration.png]]&lt;br /&gt;
&lt;br /&gt;
Details about my investigations are coming soon ...&lt;/div&gt;</summary>
		<author><name>Danutc</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=JBPM_-_Opentaps_1.x_Integration_Prototype&amp;diff=3994</id>
		<title>JBPM - Opentaps 1.x Integration Prototype</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=JBPM_-_Opentaps_1.x_Integration_Prototype&amp;diff=3994"/>
		<updated>2009-06-15T07:03:51Z</updated>

		<summary type="html">&lt;p&gt;Danutc: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;To get started with BPM we decided to investigate how to integrate an existing BPM implementation, jBPM, with opentaps 1.4. As jBPM 4 is scheduled for release in July 2009 we decided to use beta 2 version for this prototype (latest jBPM build available at the time of this writing).&lt;br /&gt;
&lt;br /&gt;
For the communication between opentaps and jBPM we use Apache Tuscany 1.5 SCA ESB. The SCA bidirectional interface provides a direct call and a callback interface; jBPM can call opentaps and opentaps can fire events (callbacks) to jBPM.&lt;br /&gt;
&lt;br /&gt;
We will implement the following business process: The sales person creates a quote. if the quote price (QP) is up to 5% below recommended retail price (QRRP) then she can submit the quote to customer otherwise she needs manager approval. The quote is converted to order and send to manufacturing after the customer deposited 50% of quoted price.&lt;br /&gt;
&lt;br /&gt;
Main scenario looks like this:&lt;br /&gt;
* sales person: creates quote&lt;br /&gt;
* if QP &amp;lt; 95% QRRP&lt;br /&gt;
** manager: approves quote&lt;br /&gt;
* else&lt;br /&gt;
** BPM: approves quote automatically&lt;br /&gt;
* accounts receivable: receives 50% QP deposit&lt;br /&gt;
* accounts receivable: convert quote to order&lt;br /&gt;
&lt;br /&gt;
The steps are:&lt;br /&gt;
* opentaps: fires an event to jBPM when a new quote is created (passing QP and QRRP to jBPM)&lt;br /&gt;
* jBPM: if QP &amp;lt; 95% QRRP&lt;br /&gt;
** jBPM: assign quote to manager for approval&lt;br /&gt;
* jBPM: assign quote to accounts receivable officer to monitor for 50% QP deposit&lt;br /&gt;
* accounts receivable officer: updates jBPM when 50% QP is received&lt;br /&gt;
* jBPM: calls opentaps to convert quote to order&lt;br /&gt;
&lt;br /&gt;
Relevant information can be found at:&lt;br /&gt;
&lt;br /&gt;
* [http://tuscany.apache.org/ Apache Tuscany SCA / ESB]&lt;br /&gt;
* [http://www.davidchappell.com/articles/Introducing_SCA.pdf INTRODUCING SCA]&lt;br /&gt;
* [http://tuscany.apache.org/sca-java-web-applications.html Using Tuscany in JEE Web Applications]&lt;br /&gt;
* [http://tuscany.apache.org/distributed-sca-domain.html Create A SCA Distributed Application]&lt;br /&gt;
* [http://cwiki.apache.org/TUSCANYWIKI/tuscany-web-application-based-integration-with-geronimo.html Tuscany Web Application based Integration with Geronimo]&lt;br /&gt;
&lt;br /&gt;
== The Prototype ==&lt;br /&gt;
&lt;br /&gt;
[[Image:jBPM.4b2_opentaps.1.4_Integration.png]]&lt;br /&gt;
&lt;br /&gt;
Details about my investigations are coming soon ...&lt;/div&gt;</summary>
		<author><name>Danutc</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=JBPM_-_Opentaps_1.x_Integration_Prototype&amp;diff=3990</id>
		<title>JBPM - Opentaps 1.x Integration Prototype</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=JBPM_-_Opentaps_1.x_Integration_Prototype&amp;diff=3990"/>
		<updated>2009-06-11T04:26:46Z</updated>

		<summary type="html">&lt;p&gt;Danutc: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;To get started with BPM we decided to investigate how to integrate an existing BPM implementation, jBPM, with opentaps 1.4. As jBPM 4 is scheduled for release in July 2009 we decided to use beta 2 version for this prototype (latest jBPM build available at the time of this writing).&lt;br /&gt;
&lt;br /&gt;
For the communication between opentaps and jBPM we use Apache Tuscany 1.5 SCA ESB. The SCA bidirectional interface provides a direct call and a callback interface; jBPM can call opentaps and opentaps can fire events (callbacks) to jBPM.&lt;br /&gt;
&lt;br /&gt;
We will implement the following business process: The sales person creates a quote. if the quote price (QP) is up to 5% below recommended retail price (QRRP) then she can submit the quote to customer otherwise she needs manager approval. The quote is converted to order and send to manufacturing after the customer deposited 50% of quoted price.&lt;br /&gt;
&lt;br /&gt;
Main scenario looks like this:&lt;br /&gt;
* sales person: creates quote&lt;br /&gt;
* if QP &amp;lt; 95% QRRP&lt;br /&gt;
** manager: approves quote&lt;br /&gt;
* else&lt;br /&gt;
** BPM: approves quote automatically&lt;br /&gt;
* accounts receivable: receives 50% QP deposit&lt;br /&gt;
* accounts receivable: convert quote to order&lt;br /&gt;
&lt;br /&gt;
The steps are:&lt;br /&gt;
* opentaps: fires an event to jBPM when a new quote is created (passing QP and QRRP to jBPM)&lt;br /&gt;
* jBPM: if QP &amp;lt; 95% QRRP&lt;br /&gt;
** jBPM: assign quote to manager for approval&lt;br /&gt;
* jBPM: assign quote to accounts receivable officer to monitor for 50% QP deposit&lt;br /&gt;
* accounts receivable officer: updates jBPM when 50% QP is received&lt;br /&gt;
* jBPM: calls opentaps to convert quote to order&lt;br /&gt;
&lt;br /&gt;
Relevant information can be found at:&lt;br /&gt;
&lt;br /&gt;
* [http://tuscany.apache.org/ Apache Tuscany SCA / ESB]&lt;br /&gt;
* [http://www.davidchappell.com/articles/Introducing_SCA.pdf INTRODUCING SCA]&lt;br /&gt;
* [http://tuscany.apache.org/sca-java-web-applications.html Using Tuscany in JEE Web Applications]&lt;br /&gt;
* [http://tuscany.apache.org/distributed-sca-domain.html Create A SCA Distributed Application]&lt;br /&gt;
&lt;br /&gt;
== The Prototype ==&lt;br /&gt;
&lt;br /&gt;
[[Image:jBPM.4b2_opentaps.1.4_Integration.png]]&lt;br /&gt;
&lt;br /&gt;
Details about my investigations are coming soon ...&lt;/div&gt;</summary>
		<author><name>Danutc</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=JBPM_-_Opentaps_1.x_Integration_Prototype&amp;diff=3989</id>
		<title>JBPM - Opentaps 1.x Integration Prototype</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=JBPM_-_Opentaps_1.x_Integration_Prototype&amp;diff=3989"/>
		<updated>2009-06-11T03:23:20Z</updated>

		<summary type="html">&lt;p&gt;Danutc: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;To get started with BPM we decided to investigate how to integrate an existing BPM implementation, jBPM, with opentaps 1.4. As jBPM 4 is scheduled for release in July 2009 we decided to use beta 2 version for this prototype (latest jBPM build available at the time of this writing).&lt;br /&gt;
&lt;br /&gt;
For the communication between opentaps and jBPM we use Apache Tuscany 1.5 SCA ESB. The SCA bidirectional interface provides a direct call and a callback interface; jBPM can call opentaps and opentaps can fire events (callbacks) to jBPM.&lt;br /&gt;
&lt;br /&gt;
We will implement the following business process: The sales person creates a quote. if the quote price (QP) is up to 5% below recommended retail price (QRRP) then she can submit the quote to customer otherwise she needs manager approval. The quote is converted to order and send to manufacturing after the customer deposited 50% of quoted price.&lt;br /&gt;
&lt;br /&gt;
Main scenario looks like this:&lt;br /&gt;
* sales person: creates quote&lt;br /&gt;
* if QP &amp;lt; 95% QRRP&lt;br /&gt;
** manager: approves quote&lt;br /&gt;
* else&lt;br /&gt;
** BPM: approves quote automatically&lt;br /&gt;
* accounts receivable: receives 50% QP deposit&lt;br /&gt;
* accounts receivable: convert quote to order&lt;br /&gt;
&lt;br /&gt;
The steps are:&lt;br /&gt;
* opentaps: fires an event to jBPM when a new quote is created (passing QP and QRRP to jBPM)&lt;br /&gt;
* jBPM: if QP &amp;lt; 95% QRRP&lt;br /&gt;
** jBPM: assign quote to manager for approval&lt;br /&gt;
* jBPM: assign quote to accounts receivable officer to monitor for 50% QP deposit&lt;br /&gt;
* accounts receivable officer: updates jBPM when 50% QP is received&lt;br /&gt;
* jBPM: calls opentaps to convert quote to order&lt;br /&gt;
&lt;br /&gt;
Relevant information can be found at:&lt;br /&gt;
&lt;br /&gt;
* [http://tuscany.apache.org/ Apache Tuscany SCA / ESB]&lt;br /&gt;
* [http://www.davidchappell.com/articles/Introducing_SCA.pdf INTRODUCING SCA]&lt;br /&gt;
* [http://tuscany.apache.org/sca-java-web-applications.html Using Tuscany in JEE Web Applications]&lt;br /&gt;
&lt;br /&gt;
== The Prototype ==&lt;br /&gt;
&lt;br /&gt;
[[Image:jBPM.4b2_opentaps.1.4_Integration.png]]&lt;br /&gt;
&lt;br /&gt;
Details about my investigations are coming soon ...&lt;/div&gt;</summary>
		<author><name>Danutc</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=JBPM_-_Opentaps_1.x_Integration_Prototype&amp;diff=3988</id>
		<title>JBPM - Opentaps 1.x Integration Prototype</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=JBPM_-_Opentaps_1.x_Integration_Prototype&amp;diff=3988"/>
		<updated>2009-06-11T03:21:49Z</updated>

		<summary type="html">&lt;p&gt;Danutc: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;To get started with BPM we decided to investigate how to integrate an existing BPM implementation, jBPM, with opentaps 1.4. As jBPM 4 is scheduled for release in July 2009 we decided to use beta 2 version for this prototype (latest jBPM build available at the time of this writing).&lt;br /&gt;
&lt;br /&gt;
For the communication between opentaps and jBPM we use Apache Tuscany 1.5 SCA ESB. The SCA bidirectional interface provides a direct call and a callback interface; jBPM can call opentaps and opentaps can fire events (callbacks) to jBPM.&lt;br /&gt;
&lt;br /&gt;
We will implement the following business process: The sales person creates a quote. if the quote price (QP) is up to 5% below recommended retail price (QRRP) then she can submit the quote to customer otherwise she needs manager approval. The quote is converted to order and send to manufacturing after the customer deposited 50% of quoted price.&lt;br /&gt;
&lt;br /&gt;
Main scenario looks like this:&lt;br /&gt;
* sales person: creates quote&lt;br /&gt;
* if QP &amp;lt; 95% QRRP&lt;br /&gt;
** manager: approves quote&lt;br /&gt;
* else&lt;br /&gt;
** BPM: approves quote automatically&lt;br /&gt;
* accounts receivable: receives 50% QP deposit&lt;br /&gt;
* accounts receivable: convert quote to order&lt;br /&gt;
&lt;br /&gt;
The steps are:&lt;br /&gt;
* opentaps: fires an event to jBPM when a new quote is created (passing QP and QRRP to jBPM)&lt;br /&gt;
* jBPM: if QP &amp;lt; 95% QRRP&lt;br /&gt;
** jBPM: assign quote to manager for approval&lt;br /&gt;
* jBPM: assign quote to accounts receivable officer to monitor for 50% QP deposit&lt;br /&gt;
* accounts receivable officer: updates jBPM when 50% QP is received&lt;br /&gt;
* jBPM: calls opentaps to convert quote to order&lt;br /&gt;
&lt;br /&gt;
Relevant information can be found at:&lt;br /&gt;
&lt;br /&gt;
* [http://tuscany.apache.org/ Apache Tuscany SCA / ESB]&lt;br /&gt;
* [http://tuscany.apache.org/php-sca.html Tuscany PHP]&lt;br /&gt;
* [http://www.davidchappell.com/articles/Introducing_SCA.pdf INTRODUCING SCA]&lt;br /&gt;
* [http://tuscany.apache.org/sca-java-web-applications.html Using Tuscany in JEE Web Applications]&lt;br /&gt;
&lt;br /&gt;
== The Prototype ==&lt;br /&gt;
&lt;br /&gt;
[[Image:jBPM.4b2_opentaps.1.4_Integration.png]]&lt;br /&gt;
&lt;br /&gt;
Details about my investigations are coming soon ...&lt;/div&gt;</summary>
		<author><name>Danutc</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=JBPM_-_Opentaps_1.x_Integration_Prototype&amp;diff=3984</id>
		<title>JBPM - Opentaps 1.x Integration Prototype</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=JBPM_-_Opentaps_1.x_Integration_Prototype&amp;diff=3984"/>
		<updated>2009-06-04T07:43:20Z</updated>

		<summary type="html">&lt;p&gt;Danutc: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;To get started with BPM we decided to investigate how to integrate an existing BPM implementation, jBPM, with opentaps 1.4. As jBPM 4 is scheduled for release in July 2009 we decided to use beta 2 version for this prototype (latest jBPM build available at the time of this writing).&lt;br /&gt;
&lt;br /&gt;
For the communication between opentaps and jBPM we use Apache Tuscany 1.5 SCA ESB. The SCA bidirectional interface provides a direct call and a callback interface; jBPM can call opentaps and opentaps can fire events (callbacks) to jBPM.&lt;br /&gt;
&lt;br /&gt;
We will implement the following business process: The sales person creates a quote. if the quote price (QP) is up to 5% below recommended retail price (QRRP) then she can submit the quote to customer otherwise she needs manager approval. The quote is converted to order and send to manufacturing after the customer deposited 50% of quoted price.&lt;br /&gt;
&lt;br /&gt;
Main scenario looks like this:&lt;br /&gt;
* sales person: creates quote&lt;br /&gt;
* if QP &amp;lt; 95% QRRP&lt;br /&gt;
** manager: approves quote&lt;br /&gt;
* else&lt;br /&gt;
** BPM: approves quote automatically&lt;br /&gt;
* accounts receivable: receives 50% QP deposit&lt;br /&gt;
* accounts receivable: convert quote to order&lt;br /&gt;
&lt;br /&gt;
The steps are:&lt;br /&gt;
* opentaps: fires an event to jBPM when a new quote is created (passing QP and QRRP to jBPM)&lt;br /&gt;
* jBPM: if QP &amp;lt; 95% QRRP&lt;br /&gt;
** jBPM: assign quote to manager for approval&lt;br /&gt;
* jBPM: assign quote to accounts receivable officer to monitor for 50% QP deposit&lt;br /&gt;
* accounts receivable officer: updates jBPM when 50% QP is received&lt;br /&gt;
* jBPM: calls opentaps to convert quote to order&lt;br /&gt;
&lt;br /&gt;
== The Prototype ==&lt;br /&gt;
&lt;br /&gt;
[[Image:jBPM.4b2_opentaps.1.4_Integration.png]]&lt;br /&gt;
&lt;br /&gt;
Details about my investigations are coming soon ...&lt;/div&gt;</summary>
		<author><name>Danutc</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=File:Magento.1,3_opentaps.1.4_Integration.png&amp;diff=3981</id>
		<title>File:Magento.1,3 opentaps.1.4 Integration.png</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=File:Magento.1,3_opentaps.1.4_Integration.png&amp;diff=3981"/>
		<updated>2009-06-04T07:33:13Z</updated>

		<summary type="html">&lt;p&gt;Danutc: Protected &amp;quot;Image:Magento.1,3 opentaps.1.4 Integration.png&amp;quot;: Sysop page [edit=sysop:move=sysop]&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;magento - opentaps tuscany integration prototype&lt;/div&gt;</summary>
		<author><name>Danutc</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=File:Magento.1,3_opentaps.1.4_Integration.png&amp;diff=3980</id>
		<title>File:Magento.1,3 opentaps.1.4 Integration.png</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=File:Magento.1,3_opentaps.1.4_Integration.png&amp;diff=3980"/>
		<updated>2009-06-04T07:33:11Z</updated>

		<summary type="html">&lt;p&gt;Danutc: magento - opentaps tuscany integration prototype&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;magento - opentaps tuscany integration prototype&lt;/div&gt;</summary>
		<author><name>Danutc</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=BPM_Integration&amp;diff=3979</id>
		<title>BPM Integration</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=BPM_Integration&amp;diff=3979"/>
		<updated>2009-06-04T07:31:06Z</updated>

		<summary type="html">&lt;p&gt;Danutc: /* BPM &amp;amp; SOA Resources */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Business Process Management (BPM) is probably the killer Enterprise Application as email was the killer Internet Application. Every business small or large has a business process however in most cases it is informal and business process automation is fragmented across many Enterprise Applications. As email revolutionised the way we communicate toady I expect BPM to revolutionise the way workers, managers and partners cooperate in the Enterprise.&lt;br /&gt;
&lt;br /&gt;
== BPM and SOA ==&lt;br /&gt;
A good explanation of Service Oriented Layered Architecture (SOA) is provided by '''Object Management Group''' ([http://www.omg.org OMG]) [http://www.omg.org/attachments/pdf/OMG-and-the-SOA.pdf here] (a local copy is [[Media:OMG-and-the-SOA.pdf|here]])&lt;br /&gt;
&lt;br /&gt;
[[Image:OMG-SOA.png]]&lt;br /&gt;
&lt;br /&gt;
In a nutshell:&lt;br /&gt;
* '''Business Process''' Layer exposes IT systems functionality to '''business users''' and '''business process designers'''&lt;br /&gt;
* '''Business Services''' is the '''Enterprise Integration (EI)''' Layer for '''Enterprise Applications''' (Components)&lt;br /&gt;
* '''Components''' Layer is the '''Enterprise Applications Suite'''&lt;br /&gt;
* '''Operational Resources''' Layer are the '''Databases''' and '''Legacy Enterprise Systems'''&lt;br /&gt;
&lt;br /&gt;
== SOA Enterprise Implementation ==&lt;br /&gt;
[[Image:Soa_enterprise_suite.png]]&lt;br /&gt;
&lt;br /&gt;
'''Legend:'''&lt;br /&gt;
&lt;br /&gt;
'''BPM''': Business Process Management&amp;lt;br&amp;gt;&lt;br /&gt;
'''ESB''': Enterprise Service Bus&amp;lt;br&amp;gt;&lt;br /&gt;
'''SCA''': Service Component Architecture&amp;lt;br&amp;gt;&lt;br /&gt;
'''MF''': Manufacturing&amp;lt;br&amp;gt;&lt;br /&gt;
'''SCM''': Supply Chain Management&amp;lt;br&amp;gt;&lt;br /&gt;
'''PM''': Project Management&amp;lt;br&amp;gt;&lt;br /&gt;
'''HR''': Human Resources&amp;lt;br&amp;gt;&lt;br /&gt;
'''CRM''': Customer Relationship Management&amp;lt;br&amp;gt;&lt;br /&gt;
'''DW''': Data Warehouse&lt;br /&gt;
&lt;br /&gt;
=== Business Process ===&lt;br /&gt;
Workers and Managers use the BPM application to execute the business processes. BPM includes:&lt;br /&gt;
&lt;br /&gt;
* manual steps - the business user interacts with the system&lt;br /&gt;
* automated steps - Enterprise Applications colaborate to execute the particular function&lt;br /&gt;
&lt;br /&gt;
The Business Process Designers use a BPM Graphic Design tool to describe the process. The process is described in BPM Graphic Notation (BPMN).&lt;br /&gt;
&lt;br /&gt;
=== Business Services and Integration ===&lt;br /&gt;
This is the integration layer that performs the following functions:&lt;br /&gt;
* services aggregation and presentation&lt;br /&gt;
* data transformation&lt;br /&gt;
* protocol mediation&lt;br /&gt;
* implements non-functional requirements such as security, quality of service monitoring ...&lt;br /&gt;
This layer functionality is mostly provided by off-the-shelf products with small amounts of Java code.&lt;br /&gt;
&lt;br /&gt;
=== SOA Enterprise Applications Suite ===&lt;br /&gt;
&lt;br /&gt;
All SOA compliant business applications are included in this layer. These applications are orchestrated by BPM to deliver functionally for end-to-end processes.&lt;br /&gt;
&lt;br /&gt;
=== Databases and Legacy Applications ===&lt;br /&gt;
&lt;br /&gt;
Databases and SOA non compliant business applications belong to this layer. Special adaptors could be implemented in Integration Layer to facilitate communication with Legacy Applications.&lt;br /&gt;
&lt;br /&gt;
=== Opentaps 2.0 ===&lt;br /&gt;
If we believe that SOA will dominate the Enterprise Software landscape then it makes sense to turn '''Opentaps''' into a '''Suite of SOA Enterprise Applications'''.&lt;br /&gt;
&lt;br /&gt;
Benefits:&lt;br /&gt;
* ride the SOA / BPM wave and benefit from momentum&lt;br /&gt;
* use the best technology to achieve results with least effort in shortest timeframe&lt;br /&gt;
* use off-the-shelf runtime environments and development tools: BPM, ESB, SCA, Portal, eclipse plugins ...&lt;br /&gt;
* create custom enterprise solutions assembling together SOA business applications (ours and third party)&lt;br /&gt;
* smaller independent applications with separate life cycles are easier to develop and maintain&lt;br /&gt;
* technology changes can be introduced gradually one application at a time&lt;br /&gt;
&lt;br /&gt;
== BPM &amp;amp; SOA Resources ==&lt;br /&gt;
* Object Management Group ([http://www.omg.org OMG]) [http://www.omg.org/attachments/pdf/OMG-and-the-SOA.pdf SOA Layers Article] (a local copy is [[Media:OMG-and-the-SOA.pdf|here]])&lt;br /&gt;
* [http://www.davidchappell.com/articles/Introducing_SCA.pdf INTRODUCING SCA]&lt;br /&gt;
* [http://tuscany.apache.org/ Apache Tuscany SCA / ESB]&lt;br /&gt;
* [http://www.eclipse.org/stp/ eclipse SOA Tools Platform Project]&lt;br /&gt;
* [http://searchsoa.techtarget.com/news/article/0,289142,sid26_gci1294154,00.html Eclipse Swordfish SOA runtime mixes SCA, JBI and OSGi]&lt;br /&gt;
* [[BPM - Getting Started]]&lt;br /&gt;
* [[jBPM - Opentaps 1.x Integration Prototype]]&lt;br /&gt;
* [[Magento 1.x - Opentaps 1.x Integration Prototype]]&lt;/div&gt;</summary>
		<author><name>Danutc</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=User_talk:Danutc&amp;diff=3976</id>
		<title>User talk:Danutc</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=User_talk:Danutc&amp;diff=3976"/>
		<updated>2009-06-04T07:15:51Z</updated>

		<summary type="html">&lt;p&gt;Danutc: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* [[BPM Integration]]&lt;br /&gt;
* [[BPM - Getting Started]]&lt;br /&gt;
* [[jBPM - Opentaps 1.x Integration Prototype]]&lt;br /&gt;
* [[Magento 1.x - Opentaps 1.x Integration Prototype]]&lt;br /&gt;
* [[danc - temp]]&lt;/div&gt;</summary>
		<author><name>Danutc</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=Danc_-_temp&amp;diff=3975</id>
		<title>Danc - temp</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=Danc_-_temp&amp;diff=3975"/>
		<updated>2009-06-03T07:46:40Z</updated>

		<summary type="html">&lt;p&gt;Danutc: /* An Example Using Domains */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;One problem with early versions of opentaps is that the ofbiz framework which we used is not an object-oriented framework.  Instead, it is based on a data model which is fundamentally relational, and that data model is accessed via a map-like Java object called GenericValue.  Most of the services in the business tier used a GenericDelegator to retrieve GenericValues from the database, performed operations on them, and then stored them back into the database again using the same GenericDelegator.&lt;br /&gt;
&lt;br /&gt;
While this lightweight architecture could do a lot of things, as opentaps grew it became apparent that some of the application could significantly benefit from an object-oriented architecture.  A few months ago, we started down this path and thought about how to [[Writing_Object_Oriented_Code_in_OFBiz_Framework|write more object-oriented code with the ofbiz framework]].  More recently, after reading about [http://www.amazon.com/exec/obidos/redirect?tag=opensourcestr-20&amp;amp;path=ASIN/0321125215 Domain Driven Design] and [http://www.infoq.com/minibooks/domain-driven-design-quickly Domain Driven Design Quickly], we realized that what we really needed was not just object-oriented code, but rather a more formal classification of our business logic into domains.  This document explains what domain driven architecture is, how we have implemented it, and how it could help you structure your code.&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
==What is Domain Driven Design?==&lt;br /&gt;
&lt;br /&gt;
The basic idea behind a domain is to group together all the &amp;quot;domain expertise,&amp;quot; or business knowledge, of an application and separate it from the application and its infrastructure.  It is a different way of thinking about how to organize large software applications and complements the popular Model View Controller (MVC) architecture, which we also use in opentaps.  With the Model View Controller architecture, the application's user interface (View) is separated from its business logic (Model), and a Controller directs requests from the view layer to the relevant business logic found in the model layer.  The advantage of doing this is that the same business logic could then be reused elsewhere, either in another page in the view layer or as part of other business logic in the model layer.&lt;br /&gt;
&lt;br /&gt;
MVC, however, doesn't really say how your model should be structured.  Should it be object-oriented, or should it all be written in procedural languages or just SQL?  Should they reside in separate components and packages, or could you just have one big file, which has all of your business logic?  The domain driven design answers this question by separating the model layer (&amp;quot;M&amp;quot;) of MVC into an application tier, a domain tier, and an infrastructure tier.  The infrastructure tier is used to retrieve and store data.  The domain tier is where the business knowledge or expertise is.  The application tier is responsible for coordinating the infrastructure and domain tiers to make a useful application.  Typically, it would use the infrastructure tier to obtain the data, consult the domain tier to see what should be done, and then use the infrastructure tier again to achieve the results.&lt;br /&gt;
&lt;br /&gt;
For example, let's say that you wanted to assess late charges on all of your customers' outstanding invoices.  MVC would tell you that your application should have a screen which shows you a list of outstanding invoices, and when the user says &amp;quot;Assess Late Charges&amp;quot;, the controller would pass the users' input parameters to business logic in the model tier to do the dirty work of assessing those late charges.  &lt;br /&gt;
&lt;br /&gt;
With a domain driven design, we would look more deeply at what that dirty work actually involved.  The application tier would call upon the infrastructure tier to retrieve all the invoices which ''may'' get assessed charges.  Then, it would present that list of invoices to the domain tier, which has the business expertise to say &amp;quot;Should this invoice get charged?&amp;quot; and if so &amp;quot;How much should this invoice get charged?&amp;quot;  The domain tier would then return the late charges for each invoice to the application tier.  The application tier would then call on the infrastructure tier again to store the late charges into the database.&lt;br /&gt;
&lt;br /&gt;
==Why Domain Driven Design?==&lt;br /&gt;
&lt;br /&gt;
Why do we want to do all this?&lt;br /&gt;
&lt;br /&gt;
'''You will be able to work with opentaps more easily'''&lt;br /&gt;
&lt;br /&gt;
The first and most obvious benefit of domain driven design is that it helps us organize our application into natural domains, so you don't have to come in contact with all the 800+ tables in opentaps and the over 1,200 services that support them.  For example, a domain driven design would allow us to break an application down into a few large domains, such as Customer, Order, and Invoice, and hide all the details within each of those domains from developers who don't need to work with them.  Thus, if you are working on the Order domain, you may need to know a little bit about a Customer, such as his home address, shipping addresses, payment methods, but you don't really need to know all the tables used to track the relationship of customer information and their histories.  &lt;br /&gt;
&lt;br /&gt;
A related advantage is that it allows us to separate business tier expertise from infrastructure expertise.  Thus, if you are working primarily with implementing business processes, you can write code which basically work with the different domains.  You'll be happy to leave the database to somebody whose job is working on the infrastructure tier, and who's probably glad not to have to worry about your business processes.&lt;br /&gt;
&lt;br /&gt;
'''You will be able to extend opentaps more easily'''&lt;br /&gt;
&lt;br /&gt;
Imagine that you worked in an industry or a company that had customers, but they did some special things for their customers that most other companies don't.  With an object-oriented domain driven design, you will be able to extend the existing Customer domain objects from opentaps with new methods specific to your industry or company, while still using everything from the opentaps Customer.&lt;br /&gt;
&lt;br /&gt;
'''You will be able to use opentaps in novel ways'''&lt;br /&gt;
&lt;br /&gt;
A potentially more valuable advantage is that domain driven design gets us closer to a plug-and-play application.  Imagine again that your application is broken down into the Customer and Order domains, so that the Order domain interacts with customer information only through the Customer domain.  What if you wanted to use the opentaps order entry and order management tool with another CRM application, like SugarCRM or SalesForce.com?  With good domain separation, it would be a matter of just implementing the Customer domain objects used by the Order domain to call the new CRM application.  Alternatively, if you wanted to use opentaps CRM with a legacy order management system, you could implement the Order domain objects used by the Customer domain in opentaps.&lt;br /&gt;
&lt;br /&gt;
Finally, by separating out the domain tier of business knowledge from the infrastructure tier, it also allows us to deploy opentaps on a different infrastructure tier later as well.  For example, instead of using the entity engine, you could use Hibernate or even the Google storage API instead.  This frees your application from lock-in to a particular framework.&lt;br /&gt;
&lt;br /&gt;
If these advantages sound familiar, they should be.  They are in fact the advantages of encapsulation, polymorphism, and inheritance of object oriented programming.  Domain driven design is essentially a practice for realizing those advantages in a large-scale application.&lt;br /&gt;
&lt;br /&gt;
==Terminology==&lt;br /&gt;
&lt;br /&gt;
Now let's look at some of the terminology used by [http://www.amazon.com/exec/obidos/redirect?tag=opensourcestr-20&amp;amp;path=ASIN/0321125215 Domain Driven Design], which will serve as our starting point:&lt;br /&gt;
&lt;br /&gt;
* '''Domain''' is a body of business expertise.  For example, you might have a domain of all business expertise about customers -- who is responsible for them, what prices they should get, how to contact them, etc.&lt;br /&gt;
* '''Entity''' is an object which has a distinct identity.  For example, a Customer entity has a distinct identity with an ID.&lt;br /&gt;
* '''Value Object''' is an object which has no distinct identity.  For example, the color of a product does not have a distinct identity if you think the &amp;quot;blue&amp;quot; of two blue shirts are the same thing.&lt;br /&gt;
* '''Aggregate''' is a higher level entity which could be viewed from the outside and in turn links you to other entities and value objects.  For example, Customer might be an aggregate, so you can view Customer from Orders, Invoices, etc., but a Customer's addresses and phone numbers ''should'' only be retrieved by going through Customer first.&lt;br /&gt;
* '''Infrastructure''' is where the lower level infrastructure of your application is available.  For example, it would provide you with the ability to access databases, remote web services, etc.&lt;br /&gt;
* '''Factory''' is used to create Entities.  For example, a Factory might create an Invoice entity (and its related entities and value objects) from an Order entity.  &lt;br /&gt;
* '''Repository''' is used to retrieve, store, and delete Entities from the database.  For example, a Repository might help you store the Invoice (and related entities) your Factory created and then bring them back from the database.&lt;br /&gt;
* '''Service''' is business logic that involves several domain Entities or Aggregates.  For example, creating Invoices from Orders is a service.&lt;br /&gt;
&lt;br /&gt;
==How Domain Driven Design is Implemented==&lt;br /&gt;
&lt;br /&gt;
When we started to implement the domain driven design, we faced a common issue for many developers: How could we need true to the spirit of a domain driven design, but at the same time live with our existing framework and code base?&lt;br /&gt;
&lt;br /&gt;
What we did is first implement a set of foundation classes in org.opentaps.foundation.* to support the Entity, Repository, Inrastructure, Factory, and Service concepts under the ofbiz framework.  For each of these, we implemented an interface, and then we implemented a specific version for the ofbiz framework.  Thus, we have the following interfaces:&lt;br /&gt;
 * org.opentaps.foundation.entity.EntityInterface&lt;br /&gt;
 * org.opentaps.foundation.repository.RepositoryInterface&lt;br /&gt;
 * org.opentaps.foundation.factory.FactoryInterface&lt;br /&gt;
 * org.opentaps.foundation.infrastructure.Infrastructure&lt;br /&gt;
 * org.opentaps.foundation.service.ServiceInterface&lt;br /&gt;
&lt;br /&gt;
Then, for each of these we implemented a version for the ofbiz framework:&lt;br /&gt;
 * org.opentaps.foundation.entity.ofbiz.Entity&lt;br /&gt;
 * org.opentaps.foundation.repository.ofbiz.Repository&lt;br /&gt;
 * org.opentaps.foundation.factory.ofbiz.Factory&lt;br /&gt;
 * org.opentaps.foundation.infrastructure.ofbiz.Infrastructure&lt;br /&gt;
 * org.opentaps.foundation.service.Service&lt;br /&gt;
&lt;br /&gt;
Each of these is designed to map legacy code from ofbiz and ofbiz-based portions of opentaps into the concepts of the domain driven design:&lt;br /&gt;
&lt;br /&gt;
===Entity===&lt;br /&gt;
&lt;br /&gt;
The Entity object is a Java class equivalent for ofbiz GenericValues.  There is a package of [[Base Entity Classes|entity classes]] which are automatically generated for each entity defined by the entitymodel XMLs, including all the original ofbiz applications, the opentaps applications, and any of your own custom applications which extend existing entities or add new ones.  &lt;br /&gt;
&lt;br /&gt;
You can use than base entities as they are, converting back and forth between the GenericValue or Java Maps, or you can extend the base entities with additional methods that encapsulate business logic.  For example, there is an Invoice base entity class with fields such as invoiceId, invoiceDate, referenceNumber and accessor method such as getInvoiceId(), setInvoiceId(String invoiceId), etc.  Then, there is an Invoice class in the billing domain which extends the base Invoice class and has methods such as getInvoiceTotal(), getAppliedAmount(), etc.&lt;br /&gt;
&lt;br /&gt;
===Infrastructure===&lt;br /&gt;
&lt;br /&gt;
The Infrastructure class is a global directory of infrastructure resources, such as database access connections, located across all the frameworks and platforms of opentaps.  Initially, it can be used to obtain the delegator and dispatcher of the ofbiz framework, but as more applications are added to opentaps, it will also return the infrastructure their frameworks require, including JDBC connections or hibernate session factories.  These infrastructure resources are passed to the Repository and the Factory classes so that they can interact with the database and external Web services.  &lt;br /&gt;
&lt;br /&gt;
Part of the infrastructure package is the User class, which constructs a cross-framework user object that can be used by all the different applications and their frameworks.  For example, you can create a User from the ofbiz UserLogin GenericValue, or you will also be able to create Users from legacy or external applications, kerberos tokens, or LDAP and returned their ofbizUserLogin.  Note that this User class is not an extension of the UserLogin base entity class.  The UserLogin class is designed to model user logins as data, whereas the User classes designed to pass user authentication between applications.&lt;br /&gt;
&lt;br /&gt;
===Factory===&lt;br /&gt;
&lt;br /&gt;
The Factory class is designed to create Entity objects based on other parameters.  For example, you might want to create an Invoice Entity based on customer and invoice terms, or you might want to create an Invoice Entity based on an existing Order, taking its customer and list of items as a starting point.  The Factory class is meant to be extended to create Factories for the different domain aggregates such as Invoice, Customer, Order, etc.&lt;br /&gt;
&lt;br /&gt;
Under the ofbiz framework, the Factory often needs to use legacy services.  Note that this is an interesting issue: in a classic domain driven design, the Factory would create the Entity as pure objects, and then the Repository would be responsible for storing them to the database.  Such separation of roles is not present in the ofbiz framework, however, where virtually every service would access the database, create new data, and then store it back into the database.  Thus, to reuse these existing services, our Factories sometimes end up storing the objects to the database first by calling an ofbiz service, then retrieve them again and return them as Entity objects.&lt;br /&gt;
&lt;br /&gt;
===Repository===&lt;br /&gt;
&lt;br /&gt;
The Repository is designed to help retrieve and store Entities and is meant to be extended for the major Entities, so the foundation  Repository should be extended to CustomerRepository, InvoiceRepository, and OrderRepository to support Customer, Invoice, and Order Entities.&lt;br /&gt;
&lt;br /&gt;
For the ofbiz framework, the preferred way to retrieve and store data could either use the service dispatcher or the delegator.  Therefore, the Repository could be instantiated either with the delegator alone or with the delegator, dispatcher, and user login.  The Repository should offer a set of methods for retrieving or persisting its related Entity and then either use the delegator or call the service to do it.&lt;br /&gt;
&lt;br /&gt;
As a good design pattern, a repository should fetch objects directly and not associations.  The modeling details of a particular implementation should be hidden from the domain.  As an example, the repository should expose methods such as getPostalAddress() and getPhoneNumber() while the association tables PartyContactMech and InvoiceContactMech are dealt with within the implementation of these methods.&lt;br /&gt;
&lt;br /&gt;
===Repositories or Factories?===&lt;br /&gt;
&lt;br /&gt;
Since almost all legacy ofbiz services store values into the database, it may not be clear at first which one you should use.  Remember that Factories are intended to create new Entity objects, while Repositories are intended to retrieve and store them.  Therefore, we would follow the following rules for Factories and Repositories:&lt;br /&gt;
&lt;br /&gt;
# Use Factories for create and Repositories for get and store&lt;br /&gt;
# Always return the domain's Entity object from your Factory, so it looks like a real object Factory &lt;br /&gt;
# Factories will almost always use the service dispatcher, whereas Repositories will usually use the dispatcher but may sometimes use the delegator&lt;br /&gt;
&lt;br /&gt;
===Services===&lt;br /&gt;
&lt;br /&gt;
Services are designed to encapsulate business logic that span multiple Entities, such creating Invoice from an Order.  With the opentaps Service foundation, you can create your services as plain Java objects (POJOs), similar to the [http://struts.apache.org/2.x/docs/struts-2-spring-2-jpa-ajax.html Spring framework] or [http://docs.jboss.com/seam/1.0.1.GA/reference/en/html/tutorial.html JBoss Seam].  When your services object is instantiated, it will be created with Infrastructure, a User object, and the locale. From these objects, you can obtain the ofbiz framework's  delegator, dispatcher, and UserLogin GenericValue.  The Service foundation class also can load the domains directory (see below) for you, and this is done automatically if you use the [[POJO Service Engine]].  Parameters for your service are passed into your service via set methods, the execution of your services via a void method, errors are propagated by exceptions, and the results of your service are passed back via get methods.  This is in contrast to the ofbiz framework, where services are defined as static Java methods (don't '''ever''' write one in minilang!), the parameters are passed in a map, the results and any error messages are returned in a map.&lt;br /&gt;
&lt;br /&gt;
Because these services are Java objects, we follow the convention to group services with similar parameters together into one class.  For example, all services which create Invoices from Order should be in one class, and all services which create Invoices from Shipment should be in another.  This allows them to share set and get methods without having one service class which is too long.  &lt;br /&gt;
&lt;br /&gt;
What domain should a service be a part of?  By convention, we recommend that the service is part of the domain of its ''output'', so all services which create Invoices should be part of the Invoice domain, whether the invoices are created from orders, shipments, or recurring agreements.&lt;br /&gt;
&lt;br /&gt;
===Exceptions===&lt;br /&gt;
&lt;br /&gt;
All exceptions should be implemented as subclasses of &amp;lt;tt&amp;gt;org.opentaps.foundation.exceptions.FoundationException&amp;lt;/tt&amp;gt;, which is a base class that in its turn extends the ofbiz &amp;lt;tt&amp;gt;GeneralException&amp;lt;/tt&amp;gt; class.  &amp;lt;tt&amp;gt;EntityException&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;ServiceException&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;RepositoryException&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;InfrastructureException&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;FactoryException&amp;lt;/tt&amp;gt; all extend the base &amp;lt;tt&amp;gt;FoundationException&amp;lt;/tt&amp;gt; class.  You can in turn implement specific exceptions which subclass these general exceptions.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;FoundationException&amp;lt;/tt&amp;gt; class can be instantiated with an exception message or another exception.  It allows you to set a locale, a message UI label, and a Map context for the message UI label:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  throw new ServiceException(&amp;quot;Service failed&amp;quot;);&lt;br /&gt;
  throw new ServiceException(&amp;quot;OpentapsErorLabel&amp;quot;, UtilMisc.toMap(&amp;quot;orderId&amp;quot;, orderId), locale);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;FoundationException&amp;lt;/tt&amp;gt; class's getMessage() method has been overridden to expand the UI label with the context map and the locale.&lt;br /&gt;
&lt;br /&gt;
It also allows you to set your error message in one level in your code and then localize it at a higher level once the locale is known.  For example, in your repository, you can throw a not found exception without setting the locale, and then the [[POJO Service Engine]] will catch that exception and automatically localize it:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  // in repository:&lt;br /&gt;
  throw new EntityNotFoundException(&amp;quot;OpentapsErrorLabel&amp;quot;, UtilMisc.toMap(&amp;quot;orderId&amp;quot;, orderId));&lt;br /&gt;
&lt;br /&gt;
  // POJOJavaEngine &lt;br /&gt;
  ... catch (Throwable t) {&lt;br /&gt;
      if (t instanceof FoundationException) {&lt;br /&gt;
          (FoundationException) t.setLocale(locale);&lt;br /&gt;
          return ServiceUtil.returnError(t.getMessage());&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, the &amp;lt;tt&amp;gt;FoundationException&amp;lt;/tt&amp;gt; class allows you to set whether your exception requires a global rollback or not.  By default, exceptions do require rollback, but you can turn it off with &amp;lt;tt&amp;gt;setRequiresRollback&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   ServiceException ex = new ServiceException(...);&lt;br /&gt;
   ex.setRequiresRollback(false);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Setting requires rollback to false will cause the [[POJO Service Engine]] to use &amp;lt;tt&amp;gt;ServiceUtil.returnFailure&amp;lt;/tt&amp;gt; instead of &amp;lt;tt&amp;gt;ServiceUtil.returnError&amp;lt;/tt&amp;gt;.  This will cause the service to return an error message, but it will not cause the other services in a chain to abort.  You can also use the requires rollback flag for your own exception management.&lt;br /&gt;
&lt;br /&gt;
===Specifications===&lt;br /&gt;
&lt;br /&gt;
Most developers know that they should not use literal strings in their code.  For example, we all feel that it would be bad to write code like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  if (order.getStatusId().equals(&amp;quot;ORDER_APPROVED&amp;quot;)) {&lt;br /&gt;
     // .... }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Our first reaction is always to define a file of string literals, and then reuse the predefined literals:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  public static final String ORDER_APPROVED = &amp;quot;ORDER_APPROVED&amp;quot;;&lt;br /&gt;
  //...&lt;br /&gt;
  if (order.getStatusId().equals(ORDER_APPROVED)) {&lt;br /&gt;
     // ... }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is nice: now, the compiler will be able to check if our status IDs are correct, and if somebody decides to change the ID code, all we have to do is change in one place.&lt;br /&gt;
&lt;br /&gt;
But inevitably, we run into other problems with this kind of code.  Somebody might decide that instead of having one state called approved, we want to have several states, like: approved, in production, pending shipment, etc. that have the same meaning as being approved.  Later, somebody else might want to have more complicated logic: an order might considered approved if it is either in the approved state or does not contain certain hazardous materials and is in the in production or pending shipment state, for example.&lt;br /&gt;
&lt;br /&gt;
Now we'll have to change all our code again.  A developer's job is never done!&lt;br /&gt;
&lt;br /&gt;
The main problem we all face is one of logic: most ERP software, like opentaps, operate on a set of data in one logical state (i.e., orders that are approved) and transform them into other data and other logical states (i.e., invoices that are created.)  The problem is that these logical states are ''usually'' denoted as strings in a database field, but they are ''sometimes'' much more subtle and complex in real life.  Thus, we developers are lulled into thinking that ''all'' logical states can be modeled as literal strings.  This usually works, but in those 10% of the cases when it's not the case, our code is usually not well structured enough to deal with it.'''&lt;br /&gt;
&lt;br /&gt;
The solution is to '''avoid using string literals'''.  Instead, separate the logical checking code of a domain into a separate class, so that it can be modified as needed.  This is the role for Specifications: defining literal values and logical states.&lt;br /&gt;
&lt;br /&gt;
In practice, we recommend having one Specification class for each domain.  For example, for the order domain, there should be an OrderSpecification class and a corresponding interface.  Because in practice specifications are usually closely related to the way data is modeled in your database, we have kept it linked through the Repository class of each domain.  Thus, to get the OrderSpecification, use its repository:&lt;br /&gt;
  OrderRepositoryInterface orderRepository = orderDomain.getOrderRepository();&lt;br /&gt;
  OrderSpecificationInterface orderSpecification = orderRepository.getOrderSpecification();&lt;br /&gt;
&lt;br /&gt;
We have also found the following best practices to be helpful when implementing specifications:&lt;br /&gt;
# If you need to check whether a condition is true or not, implement Boolean methods in the specifications, which your domain objects can use, rather than using literal strings directly in the domain objects.  For example, instead of:&lt;br /&gt;
  if (orderSpecification.ORDER_APPROVED.equals(order.getOrderStatusId())) &lt;br /&gt;
use:&lt;br /&gt;
  if (orderSpecification.isApproved(order))&lt;br /&gt;
# If you need to get certain values from your specification for other purposes, get lists of values instead of string literals.  For example, if you need to get OrderRole objects related to an order in the role of customer, instead of implementing a literal like &amp;lt;tt&amp;gt;orderSpecification.BILL_TO_CUSTOMER_ROLE&amp;lt;/tt&amp;gt;, implement a method which returns a list of potential roles: &amp;lt;tt&amp;gt;orderSpecification.billToCustomerRoleTypeIds&amp;lt;/tt&amp;gt;.  You can then use the SQL IN operator to retrieve parties in all possible bill to customer roles and thus not be constrained to use only one potential role.&lt;br /&gt;
&lt;br /&gt;
In both cases, by abstracting logical states and by making type codes more general-purpose, your code will be able to handle changing requirements much more easily.&lt;br /&gt;
&lt;br /&gt;
==An Example Using Domains==&lt;br /&gt;
&lt;br /&gt;
Now let's consider an example.  Suppose we want to create an invoice for all the order items which are not physical products and which have been marked as performed (See [[Fulfilling Orders for Services]].)  Using the ofbiz framework, we would first define   a service:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    &amp;lt;service name=&amp;quot;opentaps.invoiceNonPhysicalOrderItems&amp;quot; engine=&amp;quot;java&amp;quot;&lt;br /&gt;
        location=&amp;quot;com.opensourcestrategies.financials.invoice.InvoiceServices&amp;quot; invoke=&amp;quot;invoiceNonPhysicalOrderItems&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;description&amp;gt;Creates an invoice from the non-physical items on the order.  It will invoice from the status in the orderItemStatusId,&lt;br /&gt;
        or if it is not supplied, default to ITEM_PERFORMED.  After the invoice is created, it will attempt to change the items' status&lt;br /&gt;
        to ITEM_COMPLETE.&amp;lt;/description&amp;gt;&lt;br /&gt;
        &amp;lt;attribute name=&amp;quot;orderId&amp;quot; type=&amp;quot;String&amp;quot; mode=&amp;quot;IN&amp;quot; optional=&amp;quot;false&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;attribute name=&amp;quot;orderItemStatusId&amp;quot; type=&amp;quot;String&amp;quot; mode=&amp;quot;IN&amp;quot; optional=&amp;quot;true&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;attribute name=&amp;quot;invoiceId&amp;quot; type=&amp;quot;String&amp;quot; mode=&amp;quot;OUT&amp;quot; optional=&amp;quot;false&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;/service&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, we would create a static Java method for the service:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    public static Map invoiceNonPhysicalOrderItems(DispatchContext dctx, Map context) {&lt;br /&gt;
        LocalDispatcher dispatcher = dctx.getDispatcher();&lt;br /&gt;
        GenericValue userLogin = (GenericValue) context.get(&amp;quot;userLogin&amp;quot;);&lt;br /&gt;
        Locale locale = (Locale) context.get(&amp;quot;locale&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        String orderId = (String) context.get(&amp;quot;orderId&amp;quot;);&lt;br /&gt;
        String orderItemStatusId = (String) context.get(&amp;quot;orderItemStatusId&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        try {&lt;br /&gt;
            // validate that the order actually exists and get list of non-physical&lt;br /&gt;
            GenericValue order = delegator.findByPrimaryKey(&amp;quot;OrderHeader&amp;quot;, UtilMisc.toMap(&amp;quot;orderId&amp;quot;, orderId));&lt;br /&gt;
            if (UtilValidate.isEmpty(order)) {&lt;br /&gt;
                return ServiceUtil.returnError(&amp;quot;Order [&amp;quot; + orderId + &amp;quot;] not found&amp;quot;);&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            // set default item status&lt;br /&gt;
            if (UtilValidate.isEmpty(orderItemStatusId)) {&lt;br /&gt;
                Debug.logInfo(&amp;quot;No status specified when invoicing non-physical items on order [&amp;quot; + orderId + &amp;quot;], using ITEM_PERFORMED&amp;quot;, module);&lt;br /&gt;
                orderItemStatusId = &amp;quot;ITEM_PERFORMED&amp;quot;;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            // get the non-physical items which have been performed&lt;br /&gt;
            List&amp;lt;GenericValue&amp;gt; orderItems = order.getRelatedByAnd(&amp;quot;OrderItem&amp;quot;, UtilMisc.toMap(&amp;quot;statusId&amp;quot;, orderItemStatusId));&lt;br /&gt;
            List&amp;lt;GenericValue&amp;gt; itemsToInvoice = new ArrayList();&lt;br /&gt;
            for (GenericValue orderItem:orderItems) {&lt;br /&gt;
                if (!UtilOrder.isItemPhysical(orderItem)) {&lt;br /&gt;
                    itemsToInvoice.add(orderItem);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            // check if there are items to invoice&lt;br /&gt;
            if (UtilValidate.isEmpty(itemsToInvoice)) {&lt;br /&gt;
                return UtilMessage.createAndLogServiceError(&amp;quot;OpentapsError_PerformedItemsToInvoiceNotFound&amp;quot;, locale, module );&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            // create a new invoice for the order items&lt;br /&gt;
            Map tmpResult = dispatcher.runSync(&amp;quot;createInvoiceForOrder&amp;quot;, UtilMisc.toMap(&amp;quot;orderId&amp;quot;, orderId, &amp;quot;billItems&amp;quot;,&lt;br /&gt;
                             itemsToInvoice, &amp;quot;userLogin&amp;quot;, userLogin), 7200, false);  // no new transaction&lt;br /&gt;
            if (ServiceUtil.isError(tmpResult)) {&lt;br /&gt;
                return tmpResult;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            // change the status of the order items to COMPLETED&lt;br /&gt;
            for (GenericValue orderItem:itemsToInvoice) {&lt;br /&gt;
                tmpResult = dispatcher.runSync(&amp;quot;changeOrderItemStatus&amp;quot;, UtilMisc.toMap(&amp;quot;orderId&amp;quot;, orderItem.getString(&amp;quot;orderId&amp;quot;),&lt;br /&gt;
                  &amp;quot;orderItemSeqId&amp;quot;, orderItem.getString(&amp;quot;orderItemSeqId&amp;quot;), &amp;quot;statusId&amp;quot;, &amp;quot;ITEM_COMPLETED&amp;quot;, &amp;quot;userLogin&amp;quot;, userLogin));&lt;br /&gt;
            &lt;br /&gt;
            // return invoiceId of new invoice created&lt;br /&gt;
            String invoiceId = (String) tmpResult.get(&amp;quot;invoiceId&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
            tmpResult = ServiceUtil.returnSuccess();&lt;br /&gt;
            tmpResult.put(&amp;quot;invoiceId&amp;quot;, invoiceId);&lt;br /&gt;
            return tmpResult;&lt;br /&gt;
        } catch (GeneralException e) {&lt;br /&gt;
            return UtilMessage.createAndLogServiceError(e, module);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So what's there not to love about this code?&lt;br /&gt;
# It is closely tied to the database.  Even though there's not a single line of SQL here, you have to know that orders are stored in &amp;quot;OrderHeader&amp;quot;, and that it is related to &amp;quot;OrderItem&amp;quot;, and that there are fields like statusId.  You also have to use the string literals for status, like ITEM_COMPLETED, ITEM_PERFORMED, etc.&lt;br /&gt;
# This method depends on things spread out in different parts of the application, like the UtilOrder class and the createInvoiceForOrder and changeOrderItemStatus services.  &lt;br /&gt;
# This code is completely dependent on the ofbiz framework's GenericValue, entity engine delegator, and local dispatcher.&lt;br /&gt;
# Static Java methods like this, while easier to work with than minilang, do not enjoy the benefits of real object-oriented programming.&lt;br /&gt;
&lt;br /&gt;
In other words, for somebody to write this code, they have to know a lot about the framework, the data model, and the application tier.&lt;br /&gt;
&lt;br /&gt;
Here's a re-write of the everything inside the try ... catch block using the domain driven design:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
       // validate that the order actually exists and get list of non-physical&lt;br /&gt;
       OrderRepository orderRepository = new OrderRepository(new Infrastructure(dispatcher), userLogin));&lt;br /&gt;
       Order order = orderRepository.getOrderById(orderId);&lt;br /&gt;
       if (UtilValidate.isEmpty(orderItemStatusId)) {&lt;br /&gt;
           Debug.logInfo(&amp;quot;No status specified when invoicing non-physical items on order [&amp;quot; + orderId + &lt;br /&gt;
                           &amp;quot;], using [&amp;quot; + OrderSpecification.ITEM_STATUS_PERFORMED + &amp;quot;]&amp;quot;, module);&lt;br /&gt;
           orderItemStatusId = OrderSpecification.ITEM_STATUS_PERFORMED;&lt;br /&gt;
       }&lt;br /&gt;
       List&amp;lt;GenericValue&amp;gt; itemsToInvoice = order.getNonPhysicalItemsForStatus(orderItemStatusId);&lt;br /&gt;
&lt;br /&gt;
       // check if there are items to invoice&lt;br /&gt;
       if (UtilValidate.isEmpty(itemsToInvoice)) {&lt;br /&gt;
           return UtilMessage.createAndLogServiceError(&amp;quot;OpentapsError_PerformedItemsToInvoiceNotFound&amp;quot;, locale, module );&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       // create a new invoice for the order items&lt;br /&gt;
       Map tmpResult = dispatcher.runSync(&amp;quot;createInvoiceForOrder&amp;quot;, UtilMisc.toMap(&amp;quot;orderId&amp;quot;, orderId, &amp;quot;billItems&amp;quot;,&lt;br /&gt;
                                     itemsToInvoice, &amp;quot;userLogin&amp;quot;, userLogin), 7200, false);  // no new transaction&lt;br /&gt;
       if (ServiceUtil.isError(tmpResult)) {&lt;br /&gt;
           return tmpResult;&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       // change the status of the order items to COMPLETED&lt;br /&gt;
       order.setItemsStatus(itemsToInvoice, OrderSpecification.ITEM_STATUS_COMPLETED);&lt;br /&gt;
            &lt;br /&gt;
       // return invoiceId of new invoice created&lt;br /&gt;
       String invoiceId = (String) tmpResult.get(&amp;quot;invoiceId&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
       tmpResult = ServiceUtil.returnSuccess();&lt;br /&gt;
       tmpResult.put(&amp;quot;invoiceId&amp;quot;, invoiceId);&lt;br /&gt;
       return tmpResult;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This code is the programming equivalent of the [http://en.wikipedia.org/wiki/Coelacanth missing link]: it has many features of the old code, but a few important differences as well.  What we have done is push everything related to orders to the Order Entity object, its OrderRepository, and OrderSpecification.  We don't care where the order came from, how we can get the items of an order, or even how the status codes of an order are defined any more, because those are all responsibilities of the Order domain objects.  (Even the validation that an order was obtained is handled by the OrderRepository, which will throw a RepositoryException if nothing is found from orderId.)  We are also no longer tied to the delegator, although the Order domain may itself require the delegator.  (The casting of itemsToInvoice to GenericValue is vestigal -- remember that our Entity object extends GenericValue, and a specific Java object may in turn extend Entity.)&lt;br /&gt;
&lt;br /&gt;
We are, however, still tied to the createInvoiceForOrder service and the ofbiz service engine.  That will have to wait until the next evolutionary step (which happened the next day).  Using the Service class from above, we can implement a POJO version of this service:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
public class OrderInvoicingService extends Service {&lt;br /&gt;
&lt;br /&gt;
    private static final String module = OrderInvoicingService.class.getName();&lt;br /&gt;
&lt;br /&gt;
    protected String orderId = null;&lt;br /&gt;
    protected String invoiceId = null;&lt;br /&gt;
    // by default, non-physical order items in this state will be invoiced&lt;br /&gt;
    protected String statusIdForNonPhysicalItemsToInvoice = OrderSpecification.ITEM_STATUS_PERFORMED;&lt;br /&gt;
&lt;br /&gt;
    public OrderInvoicingService(Infrastructure infrastructure, User user, Locale locale) throws ServiceException {&lt;br /&gt;
        super(infrastructure, user, locale);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    public void setOrderId(String orderId) {&lt;br /&gt;
        this.orderId = orderId;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    public String getInvoiceId() {&lt;br /&gt;
        return this.invoiceId;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Set the status id of non-physical order items to be invoiced by invoiceNonPhysicalOrderItems, or&lt;br /&gt;
     * OrderSpecification.ITEM_STATUS_PERFORMED will be used&lt;br /&gt;
     * @param statusId&lt;br /&gt;
     */&lt;br /&gt;
    public void setStatusIdForNonPhysicalItemsToInvoice(String statusId) {&lt;br /&gt;
        if (statusId != null) {&lt;br /&gt;
            statusIdForNonPhysicalItemsToInvoice = statusId;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    public void invoiceNonPhysicalOrderItems() throws ServiceException {&lt;br /&gt;
        try {&lt;br /&gt;
            // validate that the order actually exists and get list of non-physical&lt;br /&gt;
            OrderRepository orderRepository = new OrderRepository(new Infrastructure(dispatcher), user);&lt;br /&gt;
            Order order = orderRepository.getOrderById(orderId);&lt;br /&gt;
            List&amp;lt;GenericValue&amp;gt; itemsToInvoice = order.getNonPhysicalItemsForStatus(statusIdForNonPhysicalItemsToInvoice);&lt;br /&gt;
&lt;br /&gt;
            // check if there are items to invoice&lt;br /&gt;
            if (UtilValidate.isEmpty(itemsToInvoice)) {&lt;br /&gt;
                // TODO: Fix localization of errors&lt;br /&gt;
                throw new ServiceException(&amp;quot;OpentapsError_PerformedItemsToInvoiceNotFound&amp;quot;);&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            // create a new invoice for the order items&lt;br /&gt;
            // because of the way createInvoiceForOrder is written (665 lines of code!) &lt;br /&gt;
                      we'd have to do some re-factoring before we can add the items to an existing invoice&lt;br /&gt;
&lt;br /&gt;
            Map tmpResult = getDispatcher().runSync(&amp;quot;createInvoiceForOrder&amp;quot;, UtilMisc.toMap(&amp;quot;orderId&amp;quot;, orderId, &amp;quot;billItems&amp;quot;,&lt;br /&gt;
                                       itemsToInvoice, &amp;quot;userLogin&amp;quot;, user), 7200, false);  // no new transaction&lt;br /&gt;
            if (ServiceUtil.isError(tmpResult)) {&lt;br /&gt;
                throw new ServiceException(ServiceUtil.getErrorMessage(tmpResult));&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            // change the status of the order items to COMPLETED&lt;br /&gt;
            order.setItemsStatus(itemsToInvoice, OrderSpecification.ITEM_STATUS_COMPLETED);&lt;br /&gt;
&lt;br /&gt;
            // set the invoiceId of new invoice created&lt;br /&gt;
            this.invoiceId = (String) tmpResult.get(&amp;quot;invoiceId&amp;quot;);&lt;br /&gt;
        } catch (GeneralException ex) {&lt;br /&gt;
            throw new ServiceException(ex) ;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, the original Java static method simply has to pass the parameters to it, execute the method in the OrderInvoicingService, get its result, and pass it back.  Here's the content of that try ... catch block again:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            OrderInvoicingService invoicingService = new OrderInvoicingService(new Infrastructure(dispatcher),&lt;br /&gt;
                                                          new User(userLogin), locale);&lt;br /&gt;
            invoicingService.setOrderId(orderId);&lt;br /&gt;
            invoicingService.setStatusIdForNonPhysicalItemsToInvoice(orderItemStatusId);&lt;br /&gt;
            invoicingService.invoiceNonPhysicalOrderItems();&lt;br /&gt;
&lt;br /&gt;
            Map tmpResult = ServiceUtil.returnSuccess();&lt;br /&gt;
            tmpResult.put(&amp;quot;invoiceId&amp;quot;, invoicingService.getInvoiceId());&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Congratulations!  Now your business logic is a POJO.  You can add annotations, use dependency injection with it, and use it with other Java frameworks now.  (Is this how that missing link felt, seeing all those primordial forests for the first time?)  &lt;br /&gt;
&lt;br /&gt;
Your service is using a legacy ofbiz service &amp;quot;createInvoiceForOrder&amp;quot; still through its getDispatcher() method, but that's not so bad.  If you want to use an ofbiz service, you should use its dispatcher.  In this example, however, you still had to write a static Java method for your service, because you are using the ofbiz static Java method service engine.  With the [[POJO Service Engine]], however, that is no longer necessary, and you can remove the code in InvoiceServices.java and call OrderInvoicingServices.invoiceNonPhysicalOrderItems() directly.&lt;br /&gt;
&lt;br /&gt;
A final round of enhancements used the base entities instead of GenericValues and the domains directory to load the order domain and the order repository, so this order invoicing service could function independent of the order management system.  See [[POJO Service Engine]] for the code sample.&lt;br /&gt;
&lt;br /&gt;
==Putting It All Together==&lt;br /&gt;
&lt;br /&gt;
Now, let's see how we could put all this together to create applications around the domain driven architecture.  As we discussed before, related data Entities could be grouped together as an Aggregate, which will have related Factories, Repositories, and Services.  For example, an aggregate of concepts related to invoicing might include the Invoice, InvoiceItem, InvoiceStatus, InvoiceContactMech, InvoiceAttribute entities as well as invoice factories, invoice repositories, and several invoicing services:&lt;br /&gt;
[[Image:Aggregate.png]]&lt;br /&gt;
&lt;br /&gt;
Several of these Aggregates may then form a Domain of related business knowledge.  For example, the Billing domain may consist of Invoice and Payment aggregates and their related factories, repositories, and services.  This Domain would interact with other domains, such as Organization, Ledger, Party, and Product:&lt;br /&gt;
[[Image:Domain.png]]&lt;br /&gt;
&lt;br /&gt;
An application, such as opentaps Financials application, could be built from several relatively independent domains:&lt;br /&gt;
[[Image:Application.png]]&lt;br /&gt;
&lt;br /&gt;
To keep them relatively independent of each other, an interface should be declared for each domain, and they should return interfaces to the repositories, factories, and services.  Interfaces are not necessary for the entities, however, since entities represent a data model, which must be implemented in the same way for all opentaps applications.  For example, Invoice will always have to have an invoice ID field, and the getInvoiceId() method should always return the value of that field.  If different underlying invoicing systems use different types of invoice IDs, it is the responsibility of the invoice repository to parse that and store it in the invoice ID field of Invoice.  The Invoice entity does not need to be changed.  Here is an example of the interface for the billing domain, defined in &amp;lt;tt&amp;gt;org.opentaps.domain.billing.BillingDomainInterface&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import org.opentaps.domain.billing.invoice.InvoiceRepositoryInterface;&lt;br /&gt;
&lt;br /&gt;
public interface BillingDomainInterface {&lt;br /&gt;
&lt;br /&gt;
    public InvoiceRepositoryInterface getInvoiceRepository();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To make life a little easier, an abstract Domain class is available to encapsulate Infrastructure and User, so you don't have to set the Infrastructure and User after getting each repository, factory, or service.  Instead, you can associate the Infrastructure and User with an actual implementation of a domain, and it will automatically populated Infrastructure and User for you.  Here is its corresponding implementation in opentaps financials, &amp;lt;tt&amp;gt;org.opentaps.financials.domain.billing&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
public class BillingDomain extends Domain implements BillingDomainInterface {&lt;br /&gt;
&lt;br /&gt;
    public InvoiceRepository getInvoiceRepository() {&lt;br /&gt;
        InvoiceRepository repository = new InvoiceRepository();&lt;br /&gt;
        repository.setInfrastructure(getInfrastructure());&lt;br /&gt;
        repository.setUser(getUser());&lt;br /&gt;
        return repository;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
There should only be one directory of domains at any one time, so that all the opentaps applications use the same domains.  In opentaps, this domain directory is defined in the DomainsDirectory class, and the actual domains are defined in &amp;lt;tt&amp;gt;hot-deploy/opentaps-common/config/domains-directory.xml&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;beans&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;bean id=&amp;quot;opentapsBillingDomain&amp;quot; class=&amp;quot;org.opentaps.financials.domain.billing.BillingDomain&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;bean id=&amp;quot;domainsDirectory&amp;quot; class=&amp;quot;org.opentaps.domain.DomainsDirectory&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;property name=&amp;quot;billingDomain&amp;quot;&amp;gt;&amp;lt;ref bean=&amp;quot;opentapsBillingDomain&amp;quot;/&amp;gt;&amp;lt;/property&amp;gt;&lt;br /&gt;
    &amp;lt;/bean&amp;gt;&lt;br /&gt;
    &lt;br /&gt;
&amp;lt;/beans&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that domains are declared explicitly in the DomainsDirectory, rather than as a Map.  To add a new domain, you must modify the DomainsDirectory class to add a new member plus accessor (set/get) methods.  To change your domains, you can just modify this xml file.  For example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;beans&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;bean id=&amp;quot;myBillingDomain&amp;quot; class=&amp;quot;com.mycompany.domain.billing.BillingDomain&amp;quot;/&amp;gt;&lt;br /&gt;
    &lt;br /&gt;
    &amp;lt;bean id=&amp;quot;domainsDirectory&amp;quot; class=&amp;quot;org.opentaps.domain.DomainsDirectory&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;property name=&amp;quot;billingDomain&amp;quot;&amp;gt;&amp;lt;ref bean=&amp;quot;myBillingDomain&amp;quot;/&amp;gt;&amp;lt;/property&amp;gt;&lt;br /&gt;
    &amp;lt;/bean&amp;gt;&lt;br /&gt;
    &lt;br /&gt;
&amp;lt;/beans&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
When you restart opentaps, the new domains will be loaded.&lt;br /&gt;
&lt;br /&gt;
To load your domains, use &amp;lt;tt&amp;gt;DomainsLoader&amp;lt;/tt&amp;gt;, which can be instantiated with Infrastructure and User:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// get the domain&lt;br /&gt;
DomainsLoader dl = new DomainsLoader(new Infrastructure(dispatcher), new User(admin));&lt;br /&gt;
DomainsDirectory domains = dl.loadDomainsDirectory();&lt;br /&gt;
BillingDomainInterface billingDomain = domains.getBillingDomain();&lt;br /&gt;
&lt;br /&gt;
// now we can use it&lt;br /&gt;
InvoiceRepositoryInterface invoiceRepository = billingDomain.getInvoiceRepository();&lt;br /&gt;
Invoice invoice = invoiceRepository.getInvoiceById(&amp;quot;10000&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Danutc</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=Danc_-_temp&amp;diff=3974</id>
		<title>Danc - temp</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=Danc_-_temp&amp;diff=3974"/>
		<updated>2009-06-03T07:43:11Z</updated>

		<summary type="html">&lt;p&gt;Danutc: Protected &amp;quot;Danc - temp&amp;quot;: Sysop page [edit=sysop:move=sysop]&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;One problem with early versions of opentaps is that the ofbiz framework which we used is not an object-oriented framework.  Instead, it is based on a data model which is fundamentally relational, and that data model is accessed via a map-like Java object called GenericValue.  Most of the services in the business tier used a GenericDelegator to retrieve GenericValues from the database, performed operations on them, and then stored them back into the database again using the same GenericDelegator.&lt;br /&gt;
&lt;br /&gt;
While this lightweight architecture could do a lot of things, as opentaps grew it became apparent that some of the application could significantly benefit from an object-oriented architecture.  A few months ago, we started down this path and thought about how to [[Writing_Object_Oriented_Code_in_OFBiz_Framework|write more object-oriented code with the ofbiz framework]].  More recently, after reading about [http://www.amazon.com/exec/obidos/redirect?tag=opensourcestr-20&amp;amp;path=ASIN/0321125215 Domain Driven Design] and [http://www.infoq.com/minibooks/domain-driven-design-quickly Domain Driven Design Quickly], we realized that what we really needed was not just object-oriented code, but rather a more formal classification of our business logic into domains.  This document explains what domain driven architecture is, how we have implemented it, and how it could help you structure your code.&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
==What is Domain Driven Design?==&lt;br /&gt;
&lt;br /&gt;
The basic idea behind a domain is to group together all the &amp;quot;domain expertise,&amp;quot; or business knowledge, of an application and separate it from the application and its infrastructure.  It is a different way of thinking about how to organize large software applications and complements the popular Model View Controller (MVC) architecture, which we also use in opentaps.  With the Model View Controller architecture, the application's user interface (View) is separated from its business logic (Model), and a Controller directs requests from the view layer to the relevant business logic found in the model layer.  The advantage of doing this is that the same business logic could then be reused elsewhere, either in another page in the view layer or as part of other business logic in the model layer.&lt;br /&gt;
&lt;br /&gt;
MVC, however, doesn't really say how your model should be structured.  Should it be object-oriented, or should it all be written in procedural languages or just SQL?  Should they reside in separate components and packages, or could you just have one big file, which has all of your business logic?  The domain driven design answers this question by separating the model layer (&amp;quot;M&amp;quot;) of MVC into an application tier, a domain tier, and an infrastructure tier.  The infrastructure tier is used to retrieve and store data.  The domain tier is where the business knowledge or expertise is.  The application tier is responsible for coordinating the infrastructure and domain tiers to make a useful application.  Typically, it would use the infrastructure tier to obtain the data, consult the domain tier to see what should be done, and then use the infrastructure tier again to achieve the results.&lt;br /&gt;
&lt;br /&gt;
For example, let's say that you wanted to assess late charges on all of your customers' outstanding invoices.  MVC would tell you that your application should have a screen which shows you a list of outstanding invoices, and when the user says &amp;quot;Assess Late Charges&amp;quot;, the controller would pass the users' input parameters to business logic in the model tier to do the dirty work of assessing those late charges.  &lt;br /&gt;
&lt;br /&gt;
With a domain driven design, we would look more deeply at what that dirty work actually involved.  The application tier would call upon the infrastructure tier to retrieve all the invoices which ''may'' get assessed charges.  Then, it would present that list of invoices to the domain tier, which has the business expertise to say &amp;quot;Should this invoice get charged?&amp;quot; and if so &amp;quot;How much should this invoice get charged?&amp;quot;  The domain tier would then return the late charges for each invoice to the application tier.  The application tier would then call on the infrastructure tier again to store the late charges into the database.&lt;br /&gt;
&lt;br /&gt;
==Why Domain Driven Design?==&lt;br /&gt;
&lt;br /&gt;
Why do we want to do all this?&lt;br /&gt;
&lt;br /&gt;
'''You will be able to work with opentaps more easily'''&lt;br /&gt;
&lt;br /&gt;
The first and most obvious benefit of domain driven design is that it helps us organize our application into natural domains, so you don't have to come in contact with all the 800+ tables in opentaps and the over 1,200 services that support them.  For example, a domain driven design would allow us to break an application down into a few large domains, such as Customer, Order, and Invoice, and hide all the details within each of those domains from developers who don't need to work with them.  Thus, if you are working on the Order domain, you may need to know a little bit about a Customer, such as his home address, shipping addresses, payment methods, but you don't really need to know all the tables used to track the relationship of customer information and their histories.  &lt;br /&gt;
&lt;br /&gt;
A related advantage is that it allows us to separate business tier expertise from infrastructure expertise.  Thus, if you are working primarily with implementing business processes, you can write code which basically work with the different domains.  You'll be happy to leave the database to somebody whose job is working on the infrastructure tier, and who's probably glad not to have to worry about your business processes.&lt;br /&gt;
&lt;br /&gt;
'''You will be able to extend opentaps more easily'''&lt;br /&gt;
&lt;br /&gt;
Imagine that you worked in an industry or a company that had customers, but they did some special things for their customers that most other companies don't.  With an object-oriented domain driven design, you will be able to extend the existing Customer domain objects from opentaps with new methods specific to your industry or company, while still using everything from the opentaps Customer.&lt;br /&gt;
&lt;br /&gt;
'''You will be able to use opentaps in novel ways'''&lt;br /&gt;
&lt;br /&gt;
A potentially more valuable advantage is that domain driven design gets us closer to a plug-and-play application.  Imagine again that your application is broken down into the Customer and Order domains, so that the Order domain interacts with customer information only through the Customer domain.  What if you wanted to use the opentaps order entry and order management tool with another CRM application, like SugarCRM or SalesForce.com?  With good domain separation, it would be a matter of just implementing the Customer domain objects used by the Order domain to call the new CRM application.  Alternatively, if you wanted to use opentaps CRM with a legacy order management system, you could implement the Order domain objects used by the Customer domain in opentaps.&lt;br /&gt;
&lt;br /&gt;
Finally, by separating out the domain tier of business knowledge from the infrastructure tier, it also allows us to deploy opentaps on a different infrastructure tier later as well.  For example, instead of using the entity engine, you could use Hibernate or even the Google storage API instead.  This frees your application from lock-in to a particular framework.&lt;br /&gt;
&lt;br /&gt;
If these advantages sound familiar, they should be.  They are in fact the advantages of encapsulation, polymorphism, and inheritance of object oriented programming.  Domain driven design is essentially a practice for realizing those advantages in a large-scale application.&lt;br /&gt;
&lt;br /&gt;
==Terminology==&lt;br /&gt;
&lt;br /&gt;
Now let's look at some of the terminology used by [http://www.amazon.com/exec/obidos/redirect?tag=opensourcestr-20&amp;amp;path=ASIN/0321125215 Domain Driven Design], which will serve as our starting point:&lt;br /&gt;
&lt;br /&gt;
* '''Domain''' is a body of business expertise.  For example, you might have a domain of all business expertise about customers -- who is responsible for them, what prices they should get, how to contact them, etc.&lt;br /&gt;
* '''Entity''' is an object which has a distinct identity.  For example, a Customer entity has a distinct identity with an ID.&lt;br /&gt;
* '''Value Object''' is an object which has no distinct identity.  For example, the color of a product does not have a distinct identity if you think the &amp;quot;blue&amp;quot; of two blue shirts are the same thing.&lt;br /&gt;
* '''Aggregate''' is a higher level entity which could be viewed from the outside and in turn links you to other entities and value objects.  For example, Customer might be an aggregate, so you can view Customer from Orders, Invoices, etc., but a Customer's addresses and phone numbers ''should'' only be retrieved by going through Customer first.&lt;br /&gt;
* '''Infrastructure''' is where the lower level infrastructure of your application is available.  For example, it would provide you with the ability to access databases, remote web services, etc.&lt;br /&gt;
* '''Factory''' is used to create Entities.  For example, a Factory might create an Invoice entity (and its related entities and value objects) from an Order entity.  &lt;br /&gt;
* '''Repository''' is used to retrieve, store, and delete Entities from the database.  For example, a Repository might help you store the Invoice (and related entities) your Factory created and then bring them back from the database.&lt;br /&gt;
* '''Service''' is business logic that involves several domain Entities or Aggregates.  For example, creating Invoices from Orders is a service.&lt;br /&gt;
&lt;br /&gt;
==How Domain Driven Design is Implemented==&lt;br /&gt;
&lt;br /&gt;
When we started to implement the domain driven design, we faced a common issue for many developers: How could we need true to the spirit of a domain driven design, but at the same time live with our existing framework and code base?&lt;br /&gt;
&lt;br /&gt;
What we did is first implement a set of foundation classes in org.opentaps.foundation.* to support the Entity, Repository, Inrastructure, Factory, and Service concepts under the ofbiz framework.  For each of these, we implemented an interface, and then we implemented a specific version for the ofbiz framework.  Thus, we have the following interfaces:&lt;br /&gt;
 * org.opentaps.foundation.entity.EntityInterface&lt;br /&gt;
 * org.opentaps.foundation.repository.RepositoryInterface&lt;br /&gt;
 * org.opentaps.foundation.factory.FactoryInterface&lt;br /&gt;
 * org.opentaps.foundation.infrastructure.Infrastructure&lt;br /&gt;
 * org.opentaps.foundation.service.ServiceInterface&lt;br /&gt;
&lt;br /&gt;
Then, for each of these we implemented a version for the ofbiz framework:&lt;br /&gt;
 * org.opentaps.foundation.entity.ofbiz.Entity&lt;br /&gt;
 * org.opentaps.foundation.repository.ofbiz.Repository&lt;br /&gt;
 * org.opentaps.foundation.factory.ofbiz.Factory&lt;br /&gt;
 * org.opentaps.foundation.infrastructure.ofbiz.Infrastructure&lt;br /&gt;
 * org.opentaps.foundation.service.Service&lt;br /&gt;
&lt;br /&gt;
Each of these is designed to map legacy code from ofbiz and ofbiz-based portions of opentaps into the concepts of the domain driven design:&lt;br /&gt;
&lt;br /&gt;
===Entity===&lt;br /&gt;
&lt;br /&gt;
The Entity object is a Java class equivalent for ofbiz GenericValues.  There is a package of [[Base Entity Classes|entity classes]] which are automatically generated for each entity defined by the entitymodel XMLs, including all the original ofbiz applications, the opentaps applications, and any of your own custom applications which extend existing entities or add new ones.  &lt;br /&gt;
&lt;br /&gt;
You can use than base entities as they are, converting back and forth between the GenericValue or Java Maps, or you can extend the base entities with additional methods that encapsulate business logic.  For example, there is an Invoice base entity class with fields such as invoiceId, invoiceDate, referenceNumber and accessor method such as getInvoiceId(), setInvoiceId(String invoiceId), etc.  Then, there is an Invoice class in the billing domain which extends the base Invoice class and has methods such as getInvoiceTotal(), getAppliedAmount(), etc.&lt;br /&gt;
&lt;br /&gt;
===Infrastructure===&lt;br /&gt;
&lt;br /&gt;
The Infrastructure class is a global directory of infrastructure resources, such as database access connections, located across all the frameworks and platforms of opentaps.  Initially, it can be used to obtain the delegator and dispatcher of the ofbiz framework, but as more applications are added to opentaps, it will also return the infrastructure their frameworks require, including JDBC connections or hibernate session factories.  These infrastructure resources are passed to the Repository and the Factory classes so that they can interact with the database and external Web services.  &lt;br /&gt;
&lt;br /&gt;
Part of the infrastructure package is the User class, which constructs a cross-framework user object that can be used by all the different applications and their frameworks.  For example, you can create a User from the ofbiz UserLogin GenericValue, or you will also be able to create Users from legacy or external applications, kerberos tokens, or LDAP and returned their ofbizUserLogin.  Note that this User class is not an extension of the UserLogin base entity class.  The UserLogin class is designed to model user logins as data, whereas the User classes designed to pass user authentication between applications.&lt;br /&gt;
&lt;br /&gt;
===Factory===&lt;br /&gt;
&lt;br /&gt;
The Factory class is designed to create Entity objects based on other parameters.  For example, you might want to create an Invoice Entity based on customer and invoice terms, or you might want to create an Invoice Entity based on an existing Order, taking its customer and list of items as a starting point.  The Factory class is meant to be extended to create Factories for the different domain aggregates such as Invoice, Customer, Order, etc.&lt;br /&gt;
&lt;br /&gt;
Under the ofbiz framework, the Factory often needs to use legacy services.  Note that this is an interesting issue: in a classic domain driven design, the Factory would create the Entity as pure objects, and then the Repository would be responsible for storing them to the database.  Such separation of roles is not present in the ofbiz framework, however, where virtually every service would access the database, create new data, and then store it back into the database.  Thus, to reuse these existing services, our Factories sometimes end up storing the objects to the database first by calling an ofbiz service, then retrieve them again and return them as Entity objects.&lt;br /&gt;
&lt;br /&gt;
===Repository===&lt;br /&gt;
&lt;br /&gt;
The Repository is designed to help retrieve and store Entities and is meant to be extended for the major Entities, so the foundation  Repository should be extended to CustomerRepository, InvoiceRepository, and OrderRepository to support Customer, Invoice, and Order Entities.&lt;br /&gt;
&lt;br /&gt;
For the ofbiz framework, the preferred way to retrieve and store data could either use the service dispatcher or the delegator.  Therefore, the Repository could be instantiated either with the delegator alone or with the delegator, dispatcher, and user login.  The Repository should offer a set of methods for retrieving or persisting its related Entity and then either use the delegator or call the service to do it.&lt;br /&gt;
&lt;br /&gt;
As a good design pattern, a repository should fetch objects directly and not associations.  The modeling details of a particular implementation should be hidden from the domain.  As an example, the repository should expose methods such as getPostalAddress() and getPhoneNumber() while the association tables PartyContactMech and InvoiceContactMech are dealt with within the implementation of these methods.&lt;br /&gt;
&lt;br /&gt;
===Repositories or Factories?===&lt;br /&gt;
&lt;br /&gt;
Since almost all legacy ofbiz services store values into the database, it may not be clear at first which one you should use.  Remember that Factories are intended to create new Entity objects, while Repositories are intended to retrieve and store them.  Therefore, we would follow the following rules for Factories and Repositories:&lt;br /&gt;
&lt;br /&gt;
# Use Factories for create and Repositories for get and store&lt;br /&gt;
# Always return the domain's Entity object from your Factory, so it looks like a real object Factory &lt;br /&gt;
# Factories will almost always use the service dispatcher, whereas Repositories will usually use the dispatcher but may sometimes use the delegator&lt;br /&gt;
&lt;br /&gt;
===Services===&lt;br /&gt;
&lt;br /&gt;
Services are designed to encapsulate business logic that span multiple Entities, such creating Invoice from an Order.  With the opentaps Service foundation, you can create your services as plain Java objects (POJOs), similar to the [http://struts.apache.org/2.x/docs/struts-2-spring-2-jpa-ajax.html Spring framework] or [http://docs.jboss.com/seam/1.0.1.GA/reference/en/html/tutorial.html JBoss Seam].  When your services object is instantiated, it will be created with Infrastructure, a User object, and the locale. From these objects, you can obtain the ofbiz framework's  delegator, dispatcher, and UserLogin GenericValue.  The Service foundation class also can load the domains directory (see below) for you, and this is done automatically if you use the [[POJO Service Engine]].  Parameters for your service are passed into your service via set methods, the execution of your services via a void method, errors are propagated by exceptions, and the results of your service are passed back via get methods.  This is in contrast to the ofbiz framework, where services are defined as static Java methods (don't '''ever''' write one in minilang!), the parameters are passed in a map, the results and any error messages are returned in a map.&lt;br /&gt;
&lt;br /&gt;
Because these services are Java objects, we follow the convention to group services with similar parameters together into one class.  For example, all services which create Invoices from Order should be in one class, and all services which create Invoices from Shipment should be in another.  This allows them to share set and get methods without having one service class which is too long.  &lt;br /&gt;
&lt;br /&gt;
What domain should a service be a part of?  By convention, we recommend that the service is part of the domain of its ''output'', so all services which create Invoices should be part of the Invoice domain, whether the invoices are created from orders, shipments, or recurring agreements.&lt;br /&gt;
&lt;br /&gt;
===Exceptions===&lt;br /&gt;
&lt;br /&gt;
All exceptions should be implemented as subclasses of &amp;lt;tt&amp;gt;org.opentaps.foundation.exceptions.FoundationException&amp;lt;/tt&amp;gt;, which is a base class that in its turn extends the ofbiz &amp;lt;tt&amp;gt;GeneralException&amp;lt;/tt&amp;gt; class.  &amp;lt;tt&amp;gt;EntityException&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;ServiceException&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;RepositoryException&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;InfrastructureException&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;FactoryException&amp;lt;/tt&amp;gt; all extend the base &amp;lt;tt&amp;gt;FoundationException&amp;lt;/tt&amp;gt; class.  You can in turn implement specific exceptions which subclass these general exceptions.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;FoundationException&amp;lt;/tt&amp;gt; class can be instantiated with an exception message or another exception.  It allows you to set a locale, a message UI label, and a Map context for the message UI label:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  throw new ServiceException(&amp;quot;Service failed&amp;quot;);&lt;br /&gt;
  throw new ServiceException(&amp;quot;OpentapsErorLabel&amp;quot;, UtilMisc.toMap(&amp;quot;orderId&amp;quot;, orderId), locale);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;FoundationException&amp;lt;/tt&amp;gt; class's getMessage() method has been overridden to expand the UI label with the context map and the locale.&lt;br /&gt;
&lt;br /&gt;
It also allows you to set your error message in one level in your code and then localize it at a higher level once the locale is known.  For example, in your repository, you can throw a not found exception without setting the locale, and then the [[POJO Service Engine]] will catch that exception and automatically localize it:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  // in repository:&lt;br /&gt;
  throw new EntityNotFoundException(&amp;quot;OpentapsErrorLabel&amp;quot;, UtilMisc.toMap(&amp;quot;orderId&amp;quot;, orderId));&lt;br /&gt;
&lt;br /&gt;
  // POJOJavaEngine &lt;br /&gt;
  ... catch (Throwable t) {&lt;br /&gt;
      if (t instanceof FoundationException) {&lt;br /&gt;
          (FoundationException) t.setLocale(locale);&lt;br /&gt;
          return ServiceUtil.returnError(t.getMessage());&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, the &amp;lt;tt&amp;gt;FoundationException&amp;lt;/tt&amp;gt; class allows you to set whether your exception requires a global rollback or not.  By default, exceptions do require rollback, but you can turn it off with &amp;lt;tt&amp;gt;setRequiresRollback&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   ServiceException ex = new ServiceException(...);&lt;br /&gt;
   ex.setRequiresRollback(false);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Setting requires rollback to false will cause the [[POJO Service Engine]] to use &amp;lt;tt&amp;gt;ServiceUtil.returnFailure&amp;lt;/tt&amp;gt; instead of &amp;lt;tt&amp;gt;ServiceUtil.returnError&amp;lt;/tt&amp;gt;.  This will cause the service to return an error message, but it will not cause the other services in a chain to abort.  You can also use the requires rollback flag for your own exception management.&lt;br /&gt;
&lt;br /&gt;
===Specifications===&lt;br /&gt;
&lt;br /&gt;
Most developers know that they should not use literal strings in their code.  For example, we all feel that it would be bad to write code like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  if (order.getStatusId().equals(&amp;quot;ORDER_APPROVED&amp;quot;)) {&lt;br /&gt;
     // .... }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Our first reaction is always to define a file of string literals, and then reuse the predefined literals:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  public static final String ORDER_APPROVED = &amp;quot;ORDER_APPROVED&amp;quot;;&lt;br /&gt;
  //...&lt;br /&gt;
  if (order.getStatusId().equals(ORDER_APPROVED)) {&lt;br /&gt;
     // ... }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is nice: now, the compiler will be able to check if our status IDs are correct, and if somebody decides to change the ID code, all we have to do is change in one place.&lt;br /&gt;
&lt;br /&gt;
But inevitably, we run into other problems with this kind of code.  Somebody might decide that instead of having one state called approved, we want to have several states, like: approved, in production, pending shipment, etc. that have the same meaning as being approved.  Later, somebody else might want to have more complicated logic: an order might considered approved if it is either in the approved state or does not contain certain hazardous materials and is in the in production or pending shipment state, for example.&lt;br /&gt;
&lt;br /&gt;
Now we'll have to change all our code again.  A developer's job is never done!&lt;br /&gt;
&lt;br /&gt;
The main problem we all face is one of logic: most ERP software, like opentaps, operate on a set of data in one logical state (i.e., orders that are approved) and transform them into other data and other logical states (i.e., invoices that are created.)  The problem is that these logical states are ''usually'' denoted as strings in a database field, but they are ''sometimes'' much more subtle and complex in real life.  Thus, we developers are lulled into thinking that ''all'' logical states can be modeled as literal strings.  This usually works, but in those 10% of the cases when it's not the case, our code is usually not well structured enough to deal with it.'''&lt;br /&gt;
&lt;br /&gt;
The solution is to '''avoid using string literals'''.  Instead, separate the logical checking code of a domain into a separate class, so that it can be modified as needed.  This is the role for Specifications: defining literal values and logical states.&lt;br /&gt;
&lt;br /&gt;
In practice, we recommend having one Specification class for each domain.  For example, for the order domain, there should be an OrderSpecification class and a corresponding interface.  Because in practice specifications are usually closely related to the way data is modeled in your database, we have kept it linked through the Repository class of each domain.  Thus, to get the OrderSpecification, use its repository:&lt;br /&gt;
  OrderRepositoryInterface orderRepository = orderDomain.getOrderRepository();&lt;br /&gt;
  OrderSpecificationInterface orderSpecification = orderRepository.getOrderSpecification();&lt;br /&gt;
&lt;br /&gt;
We have also found the following best practices to be helpful when implementing specifications:&lt;br /&gt;
# If you need to check whether a condition is true or not, implement Boolean methods in the specifications, which your domain objects can use, rather than using literal strings directly in the domain objects.  For example, instead of:&lt;br /&gt;
  if (orderSpecification.ORDER_APPROVED.equals(order.getOrderStatusId())) &lt;br /&gt;
use:&lt;br /&gt;
  if (orderSpecification.isApproved(order))&lt;br /&gt;
# If you need to get certain values from your specification for other purposes, get lists of values instead of string literals.  For example, if you need to get OrderRole objects related to an order in the role of customer, instead of implementing a literal like &amp;lt;tt&amp;gt;orderSpecification.BILL_TO_CUSTOMER_ROLE&amp;lt;/tt&amp;gt;, implement a method which returns a list of potential roles: &amp;lt;tt&amp;gt;orderSpecification.billToCustomerRoleTypeIds&amp;lt;/tt&amp;gt;.  You can then use the SQL IN operator to retrieve parties in all possible bill to customer roles and thus not be constrained to use only one potential role.&lt;br /&gt;
&lt;br /&gt;
In both cases, by abstracting logical states and by making type codes more general-purpose, your code will be able to handle changing requirements much more easily.&lt;br /&gt;
&lt;br /&gt;
==An Example Using Domains==&lt;br /&gt;
&lt;br /&gt;
Now let's consider an example.  Suppose we want to create an invoice for all the order items which are not physical products and which have been marked as performed (See [[Fulfilling Orders for Services]].)  Using the ofbiz framework, we would first define   a service:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    &amp;lt;service name=&amp;quot;opentaps.invoiceNonPhysicalOrderItems&amp;quot; engine=&amp;quot;java&amp;quot;&lt;br /&gt;
        location=&amp;quot;com.opensourcestrategies.financials.invoice.InvoiceServices&amp;quot; invoke=&amp;quot;invoiceNonPhysicalOrderItems&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;description&amp;gt;Creates an invoice from the non-physical items on the order.  It will invoice from the status in the orderItemStatusId,&lt;br /&gt;
        or if it is not supplied, default to ITEM_PERFORMED.  After the invoice is created, it will attempt to change the items' status&lt;br /&gt;
        to ITEM_COMPLETE.&amp;lt;/description&amp;gt;&lt;br /&gt;
        &amp;lt;attribute name=&amp;quot;orderId&amp;quot; type=&amp;quot;String&amp;quot; mode=&amp;quot;IN&amp;quot; optional=&amp;quot;false&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;attribute name=&amp;quot;orderItemStatusId&amp;quot; type=&amp;quot;String&amp;quot; mode=&amp;quot;IN&amp;quot; optional=&amp;quot;true&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;attribute name=&amp;quot;invoiceId&amp;quot; type=&amp;quot;String&amp;quot; mode=&amp;quot;OUT&amp;quot; optional=&amp;quot;false&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;/service&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, we would create a static Java method for the service:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    public static Map invoiceNonPhysicalOrderItems(DispatchContext dctx, Map context) {&lt;br /&gt;
        LocalDispatcher dispatcher = dctx.getDispatcher();&lt;br /&gt;
        GenericValue userLogin = (GenericValue) context.get(&amp;quot;userLogin&amp;quot;);&lt;br /&gt;
        Locale locale = (Locale) context.get(&amp;quot;locale&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        String orderId = (String) context.get(&amp;quot;orderId&amp;quot;);&lt;br /&gt;
        String orderItemStatusId = (String) context.get(&amp;quot;orderItemStatusId&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        try {&lt;br /&gt;
            // validate that the order actually exists and get list of non-physical&lt;br /&gt;
            GenericValue order = delegator.findByPrimaryKey(&amp;quot;OrderHeader&amp;quot;, UtilMisc.toMap(&amp;quot;orderId&amp;quot;, orderId));&lt;br /&gt;
            if (UtilValidate.isEmpty(order)) {&lt;br /&gt;
                return ServiceUtil.returnError(&amp;quot;Order [&amp;quot; + orderId + &amp;quot;] not found&amp;quot;);&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            // set default item status&lt;br /&gt;
            if (UtilValidate.isEmpty(orderItemStatusId)) {&lt;br /&gt;
                Debug.logInfo(&amp;quot;No status specified when invoicing non-physical items on order [&amp;quot; + orderId + &amp;quot;], using ITEM_PERFORMED&amp;quot;, module);&lt;br /&gt;
                orderItemStatusId = &amp;quot;ITEM_PERFORMED&amp;quot;;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            // get the non-physical items which have been performed&lt;br /&gt;
            List&amp;lt;GenericValue&amp;gt; orderItems = order.getRelatedByAnd(&amp;quot;OrderItem&amp;quot;, UtilMisc.toMap(&amp;quot;statusId&amp;quot;, orderItemStatusId));&lt;br /&gt;
            List&amp;lt;GenericValue&amp;gt; itemsToInvoice = new ArrayList();&lt;br /&gt;
            for (GenericValue orderItem:orderItems) {&lt;br /&gt;
                if (!UtilOrder.isItemPhysical(orderItem)) {&lt;br /&gt;
                    itemsToInvoice.add(orderItem);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            // check if there are items to invoice&lt;br /&gt;
            if (UtilValidate.isEmpty(itemsToInvoice)) {&lt;br /&gt;
                return UtilMessage.createAndLogServiceError(&amp;quot;OpentapsError_PerformedItemsToInvoiceNotFound&amp;quot;, locale, module );&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            // create a new invoice for the order items&lt;br /&gt;
            Map tmpResult = dispatcher.runSync(&amp;quot;createInvoiceForOrder&amp;quot;, UtilMisc.toMap(&amp;quot;orderId&amp;quot;, orderId, &amp;quot;billItems&amp;quot;, itemsToInvoice, &amp;quot;userLogin&amp;quot;, userLogin), 7200, false);  // no new transaction&lt;br /&gt;
            if (ServiceUtil.isError(tmpResult)) {&lt;br /&gt;
                return tmpResult;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            // change the status of the order items to COMPLETED&lt;br /&gt;
            for (GenericValue orderItem:itemsToInvoice) {&lt;br /&gt;
                tmpResult = dispatcher.runSync(&amp;quot;changeOrderItemStatus&amp;quot;, UtilMisc.toMap(&amp;quot;orderId&amp;quot;, orderItem.getString(&amp;quot;orderId&amp;quot;), &amp;quot;orderItemSeqId&amp;quot;, orderItem.getString(&amp;quot;orderItemSeqId&amp;quot;), &amp;quot;statusId&amp;quot;, &amp;quot;ITEM_COMPLETED&amp;quot;, &amp;quot;userLogin&amp;quot;, userLogin));&lt;br /&gt;
            &lt;br /&gt;
            // return invoiceId of new invoice created&lt;br /&gt;
            String invoiceId = (String) tmpResult.get(&amp;quot;invoiceId&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
            tmpResult = ServiceUtil.returnSuccess();&lt;br /&gt;
            tmpResult.put(&amp;quot;invoiceId&amp;quot;, invoiceId);&lt;br /&gt;
            return tmpResult;&lt;br /&gt;
        } catch (GeneralException e) {&lt;br /&gt;
            return UtilMessage.createAndLogServiceError(e, module);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So what's there not to love about this code?&lt;br /&gt;
# It is closely tied to the database.  Even though there's not a single line of SQL here, you have to know that orders are stored in &amp;quot;OrderHeader&amp;quot;, and that it is related to &amp;quot;OrderItem&amp;quot;, and that there are fields like statusId.  You also have to use the string literals for status, like ITEM_COMPLETED, ITEM_PERFORMED, etc.&lt;br /&gt;
# This method depends on things spread out in different parts of the application, like the UtilOrder class and the createInvoiceForOrder and changeOrderItemStatus services.  &lt;br /&gt;
# This code is completely dependent on the ofbiz framework's GenericValue, entity engine delegator, and local dispatcher.&lt;br /&gt;
# Static Java methods like this, while easier to work with than minilang, do not enjoy the benefits of real object-oriented programming.&lt;br /&gt;
&lt;br /&gt;
In other words, for somebody to write this code, they have to know a lot about the framework, the data model, and the application tier.&lt;br /&gt;
&lt;br /&gt;
Here's a re-write of the everything inside the try ... catch block using the domain driven design:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
       // validate that the order actually exists and get list of non-physical&lt;br /&gt;
       OrderRepository orderRepository = new OrderRepository(new Infrastructure(dispatcher), userLogin));&lt;br /&gt;
       Order order = orderRepository.getOrderById(orderId);&lt;br /&gt;
       if (UtilValidate.isEmpty(orderItemStatusId)) {&lt;br /&gt;
           Debug.logInfo(&amp;quot;No status specified when invoicing non-physical items on order [&amp;quot; + orderId + &amp;quot;], using [&amp;quot; + OrderSpecification.ITEM_STATUS_PERFORMED + &amp;quot;]&amp;quot;, module);&lt;br /&gt;
           orderItemStatusId = OrderSpecification.ITEM_STATUS_PERFORMED;&lt;br /&gt;
       }&lt;br /&gt;
       List&amp;lt;GenericValue&amp;gt; itemsToInvoice = order.getNonPhysicalItemsForStatus(orderItemStatusId);&lt;br /&gt;
&lt;br /&gt;
       // check if there are items to invoice&lt;br /&gt;
       if (UtilValidate.isEmpty(itemsToInvoice)) {&lt;br /&gt;
           return UtilMessage.createAndLogServiceError(&amp;quot;OpentapsError_PerformedItemsToInvoiceNotFound&amp;quot;, locale, module );&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       // create a new invoice for the order items&lt;br /&gt;
       Map tmpResult = dispatcher.runSync(&amp;quot;createInvoiceForOrder&amp;quot;, UtilMisc.toMap(&amp;quot;orderId&amp;quot;, orderId, &amp;quot;billItems&amp;quot;, itemsToInvoice, &amp;quot;userLogin&amp;quot;, userLogin), 7200, false);  // no new transaction&lt;br /&gt;
       if (ServiceUtil.isError(tmpResult)) {&lt;br /&gt;
           return tmpResult;&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       // change the status of the order items to COMPLETED&lt;br /&gt;
       order.setItemsStatus(itemsToInvoice, OrderSpecification.ITEM_STATUS_COMPLETED);&lt;br /&gt;
            &lt;br /&gt;
       // return invoiceId of new invoice created&lt;br /&gt;
       String invoiceId = (String) tmpResult.get(&amp;quot;invoiceId&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
       tmpResult = ServiceUtil.returnSuccess();&lt;br /&gt;
       tmpResult.put(&amp;quot;invoiceId&amp;quot;, invoiceId);&lt;br /&gt;
       return tmpResult;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This code is the programming equivalent of the [http://en.wikipedia.org/wiki/Coelacanth missing link]: it has many features of the old code, but a few important differences as well.  What we have done is push everything related to orders to the Order Entity object, its OrderRepository, and OrderSpecification.  We don't care where the order came from, how we can get the items of an order, or even how the status codes of an order are defined any more, because those are all responsibilities of the Order domain objects.  (Even the validation that an order was obtained is handled by the OrderRepository, which will throw a RepositoryException if nothing is found from orderId.)  We are also no longer tied to the delegator, although the Order domain may itself require the delegator.  (The casting of itemsToInvoice to GenericValue is vestigal -- remember that our Entity object extends GenericValue, and a specific Java object may in turn extend Entity.)&lt;br /&gt;
&lt;br /&gt;
We are, however, still tied to the createInvoiceForOrder service and the ofbiz service engine.  That will have to wait until the next evolutionary step (which happened the next day).  Using the Service class from above, we can implement a POJO version of this service:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
public class OrderInvoicingService extends Service {&lt;br /&gt;
&lt;br /&gt;
    private static final String module = OrderInvoicingService.class.getName();&lt;br /&gt;
&lt;br /&gt;
    protected String orderId = null;&lt;br /&gt;
    protected String invoiceId = null;&lt;br /&gt;
    // by default, non-physical order items in this state will be invoiced&lt;br /&gt;
    protected String statusIdForNonPhysicalItemsToInvoice = OrderSpecification.ITEM_STATUS_PERFORMED;&lt;br /&gt;
&lt;br /&gt;
    public OrderInvoicingService(Infrastructure infrastructure, User user, Locale locale) throws ServiceException {&lt;br /&gt;
        super(infrastructure, user, locale);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    public void setOrderId(String orderId) {&lt;br /&gt;
        this.orderId = orderId;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    public String getInvoiceId() {&lt;br /&gt;
        return this.invoiceId;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Set the status id of non-physical order items to be invoiced by invoiceNonPhysicalOrderItems, or&lt;br /&gt;
     * OrderSpecification.ITEM_STATUS_PERFORMED will be used&lt;br /&gt;
     * @param statusId&lt;br /&gt;
     */&lt;br /&gt;
    public void setStatusIdForNonPhysicalItemsToInvoice(String statusId) {&lt;br /&gt;
        if (statusId != null) {&lt;br /&gt;
            statusIdForNonPhysicalItemsToInvoice = statusId;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    public void invoiceNonPhysicalOrderItems() throws ServiceException {&lt;br /&gt;
        try {&lt;br /&gt;
            // validate that the order actually exists and get list of non-physical&lt;br /&gt;
            OrderRepository orderRepository = new OrderRepository(new Infrastructure(dispatcher), user);&lt;br /&gt;
            Order order = orderRepository.getOrderById(orderId);&lt;br /&gt;
            List&amp;lt;GenericValue&amp;gt; itemsToInvoice = order.getNonPhysicalItemsForStatus(statusIdForNonPhysicalItemsToInvoice);&lt;br /&gt;
&lt;br /&gt;
            // check if there are items to invoice&lt;br /&gt;
            if (UtilValidate.isEmpty(itemsToInvoice)) {&lt;br /&gt;
                // TODO: Fix localization of errors&lt;br /&gt;
                throw new ServiceException(&amp;quot;OpentapsError_PerformedItemsToInvoiceNotFound&amp;quot;);&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            // create a new invoice for the order items&lt;br /&gt;
            // because of the way createInvoiceForOrder is written (665 lines of code!) we'd have to do some re-factoring before we can add the items to an existing invoice&lt;br /&gt;
            Map tmpResult = getDispatcher().runSync(&amp;quot;createInvoiceForOrder&amp;quot;, UtilMisc.toMap(&amp;quot;orderId&amp;quot;, orderId, &amp;quot;billItems&amp;quot;, itemsToInvoice, &amp;quot;userLogin&amp;quot;, user), 7200, false);  // no new transaction&lt;br /&gt;
            if (ServiceUtil.isError(tmpResult)) {&lt;br /&gt;
                throw new ServiceException(ServiceUtil.getErrorMessage(tmpResult));&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            // change the status of the order items to COMPLETED&lt;br /&gt;
            order.setItemsStatus(itemsToInvoice, OrderSpecification.ITEM_STATUS_COMPLETED);&lt;br /&gt;
&lt;br /&gt;
            // set the invoiceId of new invoice created&lt;br /&gt;
            this.invoiceId = (String) tmpResult.get(&amp;quot;invoiceId&amp;quot;);&lt;br /&gt;
        } catch (GeneralException ex) {&lt;br /&gt;
            throw new ServiceException(ex) ;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, the original Java static method simply has to pass the parameters to it, execute the method in the OrderInvoicingService, get its result, and pass it back.  Here's the content of that try ... catch block again:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            OrderInvoicingService invoicingService = new OrderInvoicingService(new Infrastructure(dispatcher), new User(userLogin), locale);&lt;br /&gt;
            invoicingService.setOrderId(orderId);&lt;br /&gt;
            invoicingService.setStatusIdForNonPhysicalItemsToInvoice(orderItemStatusId);&lt;br /&gt;
            invoicingService.invoiceNonPhysicalOrderItems();&lt;br /&gt;
&lt;br /&gt;
            Map tmpResult = ServiceUtil.returnSuccess();&lt;br /&gt;
            tmpResult.put(&amp;quot;invoiceId&amp;quot;, invoicingService.getInvoiceId());&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Congratulations!  Now your business logic is a POJO.  You can add annotations, use dependency injection with it, and use it with other Java frameworks now.  (Is this how that missing link felt, seeing all those primordial forests for the first time?)  &lt;br /&gt;
&lt;br /&gt;
Your service is using a legacy ofbiz service &amp;quot;createInvoiceForOrder&amp;quot; still through its getDispatcher() method, but that's not so bad.  If you want to use an ofbiz service, you should use its dispatcher.  In this example, however, you still had to write a static Java method for your service, because you are using the ofbiz static Java method service engine.  With the [[POJO Service Engine]], however, that is no longer necessary, and you can remove the code in InvoiceServices.java and call OrderInvoicingServices.invoiceNonPhysicalOrderItems() directly.&lt;br /&gt;
&lt;br /&gt;
A final round of enhancements used the base entities instead of GenericValues and the domains directory to load the order domain and the order repository, so this order invoicing service could function independent of the order management system.  See [[POJO Service Engine]] for the code sample.&lt;br /&gt;
&lt;br /&gt;
==Putting It All Together==&lt;br /&gt;
&lt;br /&gt;
Now, let's see how we could put all this together to create applications around the domain driven architecture.  As we discussed before, related data Entities could be grouped together as an Aggregate, which will have related Factories, Repositories, and Services.  For example, an aggregate of concepts related to invoicing might include the Invoice, InvoiceItem, InvoiceStatus, InvoiceContactMech, InvoiceAttribute entities as well as invoice factories, invoice repositories, and several invoicing services:&lt;br /&gt;
[[Image:Aggregate.png]]&lt;br /&gt;
&lt;br /&gt;
Several of these Aggregates may then form a Domain of related business knowledge.  For example, the Billing domain may consist of Invoice and Payment aggregates and their related factories, repositories, and services.  This Domain would interact with other domains, such as Organization, Ledger, Party, and Product:&lt;br /&gt;
[[Image:Domain.png]]&lt;br /&gt;
&lt;br /&gt;
An application, such as opentaps Financials application, could be built from several relatively independent domains:&lt;br /&gt;
[[Image:Application.png]]&lt;br /&gt;
&lt;br /&gt;
To keep them relatively independent of each other, an interface should be declared for each domain, and they should return interfaces to the repositories, factories, and services.  Interfaces are not necessary for the entities, however, since entities represent a data model, which must be implemented in the same way for all opentaps applications.  For example, Invoice will always have to have an invoice ID field, and the getInvoiceId() method should always return the value of that field.  If different underlying invoicing systems use different types of invoice IDs, it is the responsibility of the invoice repository to parse that and store it in the invoice ID field of Invoice.  The Invoice entity does not need to be changed.  Here is an example of the interface for the billing domain, defined in &amp;lt;tt&amp;gt;org.opentaps.domain.billing.BillingDomainInterface&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import org.opentaps.domain.billing.invoice.InvoiceRepositoryInterface;&lt;br /&gt;
&lt;br /&gt;
public interface BillingDomainInterface {&lt;br /&gt;
&lt;br /&gt;
    public InvoiceRepositoryInterface getInvoiceRepository();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To make life a little easier, an abstract Domain class is available to encapsulate Infrastructure and User, so you don't have to set the Infrastructure and User after getting each repository, factory, or service.  Instead, you can associate the Infrastructure and User with an actual implementation of a domain, and it will automatically populated Infrastructure and User for you.  Here is its corresponding implementation in opentaps financials, &amp;lt;tt&amp;gt;org.opentaps.financials.domain.billing&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
public class BillingDomain extends Domain implements BillingDomainInterface {&lt;br /&gt;
&lt;br /&gt;
    public InvoiceRepository getInvoiceRepository() {&lt;br /&gt;
        InvoiceRepository repository = new InvoiceRepository();&lt;br /&gt;
        repository.setInfrastructure(getInfrastructure());&lt;br /&gt;
        repository.setUser(getUser());&lt;br /&gt;
        return repository;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
There should only be one directory of domains at any one time, so that all the opentaps applications use the same domains.  In opentaps, this domain directory is defined in the DomainsDirectory class, and the actual domains are defined in &amp;lt;tt&amp;gt;hot-deploy/opentaps-common/config/domains-directory.xml&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;beans&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;bean id=&amp;quot;opentapsBillingDomain&amp;quot; class=&amp;quot;org.opentaps.financials.domain.billing.BillingDomain&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;bean id=&amp;quot;domainsDirectory&amp;quot; class=&amp;quot;org.opentaps.domain.DomainsDirectory&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;property name=&amp;quot;billingDomain&amp;quot;&amp;gt;&amp;lt;ref bean=&amp;quot;opentapsBillingDomain&amp;quot;/&amp;gt;&amp;lt;/property&amp;gt;&lt;br /&gt;
    &amp;lt;/bean&amp;gt;&lt;br /&gt;
    &lt;br /&gt;
&amp;lt;/beans&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that domains are declared explicitly in the DomainsDirectory, rather than as a Map.  To add a new domain, you must modify the DomainsDirectory class to add a new member plus accessor (set/get) methods.  To change your domains, you can just modify this xml file.  For example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;beans&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;bean id=&amp;quot;myBillingDomain&amp;quot; class=&amp;quot;com.mycompany.domain.billing.BillingDomain&amp;quot;/&amp;gt;&lt;br /&gt;
    &lt;br /&gt;
    &amp;lt;bean id=&amp;quot;domainsDirectory&amp;quot; class=&amp;quot;org.opentaps.domain.DomainsDirectory&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;property name=&amp;quot;billingDomain&amp;quot;&amp;gt;&amp;lt;ref bean=&amp;quot;myBillingDomain&amp;quot;/&amp;gt;&amp;lt;/property&amp;gt;&lt;br /&gt;
    &amp;lt;/bean&amp;gt;&lt;br /&gt;
    &lt;br /&gt;
&amp;lt;/beans&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
When you restart opentaps, the new domains will be loaded.&lt;br /&gt;
&lt;br /&gt;
To load your domains, use &amp;lt;tt&amp;gt;DomainsLoader&amp;lt;/tt&amp;gt;, which can be instantiated with Infrastructure and User:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// get the domain&lt;br /&gt;
DomainsLoader dl = new DomainsLoader(new Infrastructure(dispatcher), new User(admin));&lt;br /&gt;
DomainsDirectory domains = dl.loadDomainsDirectory();&lt;br /&gt;
BillingDomainInterface billingDomain = domains.getBillingDomain();&lt;br /&gt;
&lt;br /&gt;
// now we can use it&lt;br /&gt;
InvoiceRepositoryInterface invoiceRepository = billingDomain.getInvoiceRepository();&lt;br /&gt;
Invoice invoice = invoiceRepository.getInvoiceById(&amp;quot;10000&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Danutc</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=Danc_-_temp&amp;diff=3973</id>
		<title>Danc - temp</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=Danc_-_temp&amp;diff=3973"/>
		<updated>2009-06-03T07:43:08Z</updated>

		<summary type="html">&lt;p&gt;Danutc: New page: One problem with early versions of opentaps is that the ofbiz framework which we used is not an object-oriented framework.  Instead, it is based on a data model which is fundamentally rela...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;One problem with early versions of opentaps is that the ofbiz framework which we used is not an object-oriented framework.  Instead, it is based on a data model which is fundamentally relational, and that data model is accessed via a map-like Java object called GenericValue.  Most of the services in the business tier used a GenericDelegator to retrieve GenericValues from the database, performed operations on them, and then stored them back into the database again using the same GenericDelegator.&lt;br /&gt;
&lt;br /&gt;
While this lightweight architecture could do a lot of things, as opentaps grew it became apparent that some of the application could significantly benefit from an object-oriented architecture.  A few months ago, we started down this path and thought about how to [[Writing_Object_Oriented_Code_in_OFBiz_Framework|write more object-oriented code with the ofbiz framework]].  More recently, after reading about [http://www.amazon.com/exec/obidos/redirect?tag=opensourcestr-20&amp;amp;path=ASIN/0321125215 Domain Driven Design] and [http://www.infoq.com/minibooks/domain-driven-design-quickly Domain Driven Design Quickly], we realized that what we really needed was not just object-oriented code, but rather a more formal classification of our business logic into domains.  This document explains what domain driven architecture is, how we have implemented it, and how it could help you structure your code.&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
==What is Domain Driven Design?==&lt;br /&gt;
&lt;br /&gt;
The basic idea behind a domain is to group together all the &amp;quot;domain expertise,&amp;quot; or business knowledge, of an application and separate it from the application and its infrastructure.  It is a different way of thinking about how to organize large software applications and complements the popular Model View Controller (MVC) architecture, which we also use in opentaps.  With the Model View Controller architecture, the application's user interface (View) is separated from its business logic (Model), and a Controller directs requests from the view layer to the relevant business logic found in the model layer.  The advantage of doing this is that the same business logic could then be reused elsewhere, either in another page in the view layer or as part of other business logic in the model layer.&lt;br /&gt;
&lt;br /&gt;
MVC, however, doesn't really say how your model should be structured.  Should it be object-oriented, or should it all be written in procedural languages or just SQL?  Should they reside in separate components and packages, or could you just have one big file, which has all of your business logic?  The domain driven design answers this question by separating the model layer (&amp;quot;M&amp;quot;) of MVC into an application tier, a domain tier, and an infrastructure tier.  The infrastructure tier is used to retrieve and store data.  The domain tier is where the business knowledge or expertise is.  The application tier is responsible for coordinating the infrastructure and domain tiers to make a useful application.  Typically, it would use the infrastructure tier to obtain the data, consult the domain tier to see what should be done, and then use the infrastructure tier again to achieve the results.&lt;br /&gt;
&lt;br /&gt;
For example, let's say that you wanted to assess late charges on all of your customers' outstanding invoices.  MVC would tell you that your application should have a screen which shows you a list of outstanding invoices, and when the user says &amp;quot;Assess Late Charges&amp;quot;, the controller would pass the users' input parameters to business logic in the model tier to do the dirty work of assessing those late charges.  &lt;br /&gt;
&lt;br /&gt;
With a domain driven design, we would look more deeply at what that dirty work actually involved.  The application tier would call upon the infrastructure tier to retrieve all the invoices which ''may'' get assessed charges.  Then, it would present that list of invoices to the domain tier, which has the business expertise to say &amp;quot;Should this invoice get charged?&amp;quot; and if so &amp;quot;How much should this invoice get charged?&amp;quot;  The domain tier would then return the late charges for each invoice to the application tier.  The application tier would then call on the infrastructure tier again to store the late charges into the database.&lt;br /&gt;
&lt;br /&gt;
==Why Domain Driven Design?==&lt;br /&gt;
&lt;br /&gt;
Why do we want to do all this?&lt;br /&gt;
&lt;br /&gt;
'''You will be able to work with opentaps more easily'''&lt;br /&gt;
&lt;br /&gt;
The first and most obvious benefit of domain driven design is that it helps us organize our application into natural domains, so you don't have to come in contact with all the 800+ tables in opentaps and the over 1,200 services that support them.  For example, a domain driven design would allow us to break an application down into a few large domains, such as Customer, Order, and Invoice, and hide all the details within each of those domains from developers who don't need to work with them.  Thus, if you are working on the Order domain, you may need to know a little bit about a Customer, such as his home address, shipping addresses, payment methods, but you don't really need to know all the tables used to track the relationship of customer information and their histories.  &lt;br /&gt;
&lt;br /&gt;
A related advantage is that it allows us to separate business tier expertise from infrastructure expertise.  Thus, if you are working primarily with implementing business processes, you can write code which basically work with the different domains.  You'll be happy to leave the database to somebody whose job is working on the infrastructure tier, and who's probably glad not to have to worry about your business processes.&lt;br /&gt;
&lt;br /&gt;
'''You will be able to extend opentaps more easily'''&lt;br /&gt;
&lt;br /&gt;
Imagine that you worked in an industry or a company that had customers, but they did some special things for their customers that most other companies don't.  With an object-oriented domain driven design, you will be able to extend the existing Customer domain objects from opentaps with new methods specific to your industry or company, while still using everything from the opentaps Customer.&lt;br /&gt;
&lt;br /&gt;
'''You will be able to use opentaps in novel ways'''&lt;br /&gt;
&lt;br /&gt;
A potentially more valuable advantage is that domain driven design gets us closer to a plug-and-play application.  Imagine again that your application is broken down into the Customer and Order domains, so that the Order domain interacts with customer information only through the Customer domain.  What if you wanted to use the opentaps order entry and order management tool with another CRM application, like SugarCRM or SalesForce.com?  With good domain separation, it would be a matter of just implementing the Customer domain objects used by the Order domain to call the new CRM application.  Alternatively, if you wanted to use opentaps CRM with a legacy order management system, you could implement the Order domain objects used by the Customer domain in opentaps.&lt;br /&gt;
&lt;br /&gt;
Finally, by separating out the domain tier of business knowledge from the infrastructure tier, it also allows us to deploy opentaps on a different infrastructure tier later as well.  For example, instead of using the entity engine, you could use Hibernate or even the Google storage API instead.  This frees your application from lock-in to a particular framework.&lt;br /&gt;
&lt;br /&gt;
If these advantages sound familiar, they should be.  They are in fact the advantages of encapsulation, polymorphism, and inheritance of object oriented programming.  Domain driven design is essentially a practice for realizing those advantages in a large-scale application.&lt;br /&gt;
&lt;br /&gt;
==Terminology==&lt;br /&gt;
&lt;br /&gt;
Now let's look at some of the terminology used by [http://www.amazon.com/exec/obidos/redirect?tag=opensourcestr-20&amp;amp;path=ASIN/0321125215 Domain Driven Design], which will serve as our starting point:&lt;br /&gt;
&lt;br /&gt;
* '''Domain''' is a body of business expertise.  For example, you might have a domain of all business expertise about customers -- who is responsible for them, what prices they should get, how to contact them, etc.&lt;br /&gt;
* '''Entity''' is an object which has a distinct identity.  For example, a Customer entity has a distinct identity with an ID.&lt;br /&gt;
* '''Value Object''' is an object which has no distinct identity.  For example, the color of a product does not have a distinct identity if you think the &amp;quot;blue&amp;quot; of two blue shirts are the same thing.&lt;br /&gt;
* '''Aggregate''' is a higher level entity which could be viewed from the outside and in turn links you to other entities and value objects.  For example, Customer might be an aggregate, so you can view Customer from Orders, Invoices, etc., but a Customer's addresses and phone numbers ''should'' only be retrieved by going through Customer first.&lt;br /&gt;
* '''Infrastructure''' is where the lower level infrastructure of your application is available.  For example, it would provide you with the ability to access databases, remote web services, etc.&lt;br /&gt;
* '''Factory''' is used to create Entities.  For example, a Factory might create an Invoice entity (and its related entities and value objects) from an Order entity.  &lt;br /&gt;
* '''Repository''' is used to retrieve, store, and delete Entities from the database.  For example, a Repository might help you store the Invoice (and related entities) your Factory created and then bring them back from the database.&lt;br /&gt;
* '''Service''' is business logic that involves several domain Entities or Aggregates.  For example, creating Invoices from Orders is a service.&lt;br /&gt;
&lt;br /&gt;
==How Domain Driven Design is Implemented==&lt;br /&gt;
&lt;br /&gt;
When we started to implement the domain driven design, we faced a common issue for many developers: How could we need true to the spirit of a domain driven design, but at the same time live with our existing framework and code base?&lt;br /&gt;
&lt;br /&gt;
What we did is first implement a set of foundation classes in org.opentaps.foundation.* to support the Entity, Repository, Inrastructure, Factory, and Service concepts under the ofbiz framework.  For each of these, we implemented an interface, and then we implemented a specific version for the ofbiz framework.  Thus, we have the following interfaces:&lt;br /&gt;
 * org.opentaps.foundation.entity.EntityInterface&lt;br /&gt;
 * org.opentaps.foundation.repository.RepositoryInterface&lt;br /&gt;
 * org.opentaps.foundation.factory.FactoryInterface&lt;br /&gt;
 * org.opentaps.foundation.infrastructure.Infrastructure&lt;br /&gt;
 * org.opentaps.foundation.service.ServiceInterface&lt;br /&gt;
&lt;br /&gt;
Then, for each of these we implemented a version for the ofbiz framework:&lt;br /&gt;
 * org.opentaps.foundation.entity.ofbiz.Entity&lt;br /&gt;
 * org.opentaps.foundation.repository.ofbiz.Repository&lt;br /&gt;
 * org.opentaps.foundation.factory.ofbiz.Factory&lt;br /&gt;
 * org.opentaps.foundation.infrastructure.ofbiz.Infrastructure&lt;br /&gt;
 * org.opentaps.foundation.service.Service&lt;br /&gt;
&lt;br /&gt;
Each of these is designed to map legacy code from ofbiz and ofbiz-based portions of opentaps into the concepts of the domain driven design:&lt;br /&gt;
&lt;br /&gt;
===Entity===&lt;br /&gt;
&lt;br /&gt;
The Entity object is a Java class equivalent for ofbiz GenericValues.  There is a package of [[Base Entity Classes|entity classes]] which are automatically generated for each entity defined by the entitymodel XMLs, including all the original ofbiz applications, the opentaps applications, and any of your own custom applications which extend existing entities or add new ones.  &lt;br /&gt;
&lt;br /&gt;
You can use than base entities as they are, converting back and forth between the GenericValue or Java Maps, or you can extend the base entities with additional methods that encapsulate business logic.  For example, there is an Invoice base entity class with fields such as invoiceId, invoiceDate, referenceNumber and accessor method such as getInvoiceId(), setInvoiceId(String invoiceId), etc.  Then, there is an Invoice class in the billing domain which extends the base Invoice class and has methods such as getInvoiceTotal(), getAppliedAmount(), etc.&lt;br /&gt;
&lt;br /&gt;
===Infrastructure===&lt;br /&gt;
&lt;br /&gt;
The Infrastructure class is a global directory of infrastructure resources, such as database access connections, located across all the frameworks and platforms of opentaps.  Initially, it can be used to obtain the delegator and dispatcher of the ofbiz framework, but as more applications are added to opentaps, it will also return the infrastructure their frameworks require, including JDBC connections or hibernate session factories.  These infrastructure resources are passed to the Repository and the Factory classes so that they can interact with the database and external Web services.  &lt;br /&gt;
&lt;br /&gt;
Part of the infrastructure package is the User class, which constructs a cross-framework user object that can be used by all the different applications and their frameworks.  For example, you can create a User from the ofbiz UserLogin GenericValue, or you will also be able to create Users from legacy or external applications, kerberos tokens, or LDAP and returned their ofbizUserLogin.  Note that this User class is not an extension of the UserLogin base entity class.  The UserLogin class is designed to model user logins as data, whereas the User classes designed to pass user authentication between applications.&lt;br /&gt;
&lt;br /&gt;
===Factory===&lt;br /&gt;
&lt;br /&gt;
The Factory class is designed to create Entity objects based on other parameters.  For example, you might want to create an Invoice Entity based on customer and invoice terms, or you might want to create an Invoice Entity based on an existing Order, taking its customer and list of items as a starting point.  The Factory class is meant to be extended to create Factories for the different domain aggregates such as Invoice, Customer, Order, etc.&lt;br /&gt;
&lt;br /&gt;
Under the ofbiz framework, the Factory often needs to use legacy services.  Note that this is an interesting issue: in a classic domain driven design, the Factory would create the Entity as pure objects, and then the Repository would be responsible for storing them to the database.  Such separation of roles is not present in the ofbiz framework, however, where virtually every service would access the database, create new data, and then store it back into the database.  Thus, to reuse these existing services, our Factories sometimes end up storing the objects to the database first by calling an ofbiz service, then retrieve them again and return them as Entity objects.&lt;br /&gt;
&lt;br /&gt;
===Repository===&lt;br /&gt;
&lt;br /&gt;
The Repository is designed to help retrieve and store Entities and is meant to be extended for the major Entities, so the foundation  Repository should be extended to CustomerRepository, InvoiceRepository, and OrderRepository to support Customer, Invoice, and Order Entities.&lt;br /&gt;
&lt;br /&gt;
For the ofbiz framework, the preferred way to retrieve and store data could either use the service dispatcher or the delegator.  Therefore, the Repository could be instantiated either with the delegator alone or with the delegator, dispatcher, and user login.  The Repository should offer a set of methods for retrieving or persisting its related Entity and then either use the delegator or call the service to do it.&lt;br /&gt;
&lt;br /&gt;
As a good design pattern, a repository should fetch objects directly and not associations.  The modeling details of a particular implementation should be hidden from the domain.  As an example, the repository should expose methods such as getPostalAddress() and getPhoneNumber() while the association tables PartyContactMech and InvoiceContactMech are dealt with within the implementation of these methods.&lt;br /&gt;
&lt;br /&gt;
===Repositories or Factories?===&lt;br /&gt;
&lt;br /&gt;
Since almost all legacy ofbiz services store values into the database, it may not be clear at first which one you should use.  Remember that Factories are intended to create new Entity objects, while Repositories are intended to retrieve and store them.  Therefore, we would follow the following rules for Factories and Repositories:&lt;br /&gt;
&lt;br /&gt;
# Use Factories for create and Repositories for get and store&lt;br /&gt;
# Always return the domain's Entity object from your Factory, so it looks like a real object Factory &lt;br /&gt;
# Factories will almost always use the service dispatcher, whereas Repositories will usually use the dispatcher but may sometimes use the delegator&lt;br /&gt;
&lt;br /&gt;
===Services===&lt;br /&gt;
&lt;br /&gt;
Services are designed to encapsulate business logic that span multiple Entities, such creating Invoice from an Order.  With the opentaps Service foundation, you can create your services as plain Java objects (POJOs), similar to the [http://struts.apache.org/2.x/docs/struts-2-spring-2-jpa-ajax.html Spring framework] or [http://docs.jboss.com/seam/1.0.1.GA/reference/en/html/tutorial.html JBoss Seam].  When your services object is instantiated, it will be created with Infrastructure, a User object, and the locale. From these objects, you can obtain the ofbiz framework's  delegator, dispatcher, and UserLogin GenericValue.  The Service foundation class also can load the domains directory (see below) for you, and this is done automatically if you use the [[POJO Service Engine]].  Parameters for your service are passed into your service via set methods, the execution of your services via a void method, errors are propagated by exceptions, and the results of your service are passed back via get methods.  This is in contrast to the ofbiz framework, where services are defined as static Java methods (don't '''ever''' write one in minilang!), the parameters are passed in a map, the results and any error messages are returned in a map.&lt;br /&gt;
&lt;br /&gt;
Because these services are Java objects, we follow the convention to group services with similar parameters together into one class.  For example, all services which create Invoices from Order should be in one class, and all services which create Invoices from Shipment should be in another.  This allows them to share set and get methods without having one service class which is too long.  &lt;br /&gt;
&lt;br /&gt;
What domain should a service be a part of?  By convention, we recommend that the service is part of the domain of its ''output'', so all services which create Invoices should be part of the Invoice domain, whether the invoices are created from orders, shipments, or recurring agreements.&lt;br /&gt;
&lt;br /&gt;
===Exceptions===&lt;br /&gt;
&lt;br /&gt;
All exceptions should be implemented as subclasses of &amp;lt;tt&amp;gt;org.opentaps.foundation.exceptions.FoundationException&amp;lt;/tt&amp;gt;, which is a base class that in its turn extends the ofbiz &amp;lt;tt&amp;gt;GeneralException&amp;lt;/tt&amp;gt; class.  &amp;lt;tt&amp;gt;EntityException&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;ServiceException&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;RepositoryException&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;InfrastructureException&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;FactoryException&amp;lt;/tt&amp;gt; all extend the base &amp;lt;tt&amp;gt;FoundationException&amp;lt;/tt&amp;gt; class.  You can in turn implement specific exceptions which subclass these general exceptions.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;FoundationException&amp;lt;/tt&amp;gt; class can be instantiated with an exception message or another exception.  It allows you to set a locale, a message UI label, and a Map context for the message UI label:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  throw new ServiceException(&amp;quot;Service failed&amp;quot;);&lt;br /&gt;
  throw new ServiceException(&amp;quot;OpentapsErorLabel&amp;quot;, UtilMisc.toMap(&amp;quot;orderId&amp;quot;, orderId), locale);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;FoundationException&amp;lt;/tt&amp;gt; class's getMessage() method has been overridden to expand the UI label with the context map and the locale.&lt;br /&gt;
&lt;br /&gt;
It also allows you to set your error message in one level in your code and then localize it at a higher level once the locale is known.  For example, in your repository, you can throw a not found exception without setting the locale, and then the [[POJO Service Engine]] will catch that exception and automatically localize it:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  // in repository:&lt;br /&gt;
  throw new EntityNotFoundException(&amp;quot;OpentapsErrorLabel&amp;quot;, UtilMisc.toMap(&amp;quot;orderId&amp;quot;, orderId));&lt;br /&gt;
&lt;br /&gt;
  // POJOJavaEngine &lt;br /&gt;
  ... catch (Throwable t) {&lt;br /&gt;
      if (t instanceof FoundationException) {&lt;br /&gt;
          (FoundationException) t.setLocale(locale);&lt;br /&gt;
          return ServiceUtil.returnError(t.getMessage());&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, the &amp;lt;tt&amp;gt;FoundationException&amp;lt;/tt&amp;gt; class allows you to set whether your exception requires a global rollback or not.  By default, exceptions do require rollback, but you can turn it off with &amp;lt;tt&amp;gt;setRequiresRollback&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   ServiceException ex = new ServiceException(...);&lt;br /&gt;
   ex.setRequiresRollback(false);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Setting requires rollback to false will cause the [[POJO Service Engine]] to use &amp;lt;tt&amp;gt;ServiceUtil.returnFailure&amp;lt;/tt&amp;gt; instead of &amp;lt;tt&amp;gt;ServiceUtil.returnError&amp;lt;/tt&amp;gt;.  This will cause the service to return an error message, but it will not cause the other services in a chain to abort.  You can also use the requires rollback flag for your own exception management.&lt;br /&gt;
&lt;br /&gt;
===Specifications===&lt;br /&gt;
&lt;br /&gt;
Most developers know that they should not use literal strings in their code.  For example, we all feel that it would be bad to write code like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  if (order.getStatusId().equals(&amp;quot;ORDER_APPROVED&amp;quot;)) {&lt;br /&gt;
     // .... }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Our first reaction is always to define a file of string literals, and then reuse the predefined literals:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  public static final String ORDER_APPROVED = &amp;quot;ORDER_APPROVED&amp;quot;;&lt;br /&gt;
  //...&lt;br /&gt;
  if (order.getStatusId().equals(ORDER_APPROVED)) {&lt;br /&gt;
     // ... }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is nice: now, the compiler will be able to check if our status IDs are correct, and if somebody decides to change the ID code, all we have to do is change in one place.&lt;br /&gt;
&lt;br /&gt;
But inevitably, we run into other problems with this kind of code.  Somebody might decide that instead of having one state called approved, we want to have several states, like: approved, in production, pending shipment, etc. that have the same meaning as being approved.  Later, somebody else might want to have more complicated logic: an order might considered approved if it is either in the approved state or does not contain certain hazardous materials and is in the in production or pending shipment state, for example.&lt;br /&gt;
&lt;br /&gt;
Now we'll have to change all our code again.  A developer's job is never done!&lt;br /&gt;
&lt;br /&gt;
The main problem we all face is one of logic: most ERP software, like opentaps, operate on a set of data in one logical state (i.e., orders that are approved) and transform them into other data and other logical states (i.e., invoices that are created.)  The problem is that these logical states are ''usually'' denoted as strings in a database field, but they are ''sometimes'' much more subtle and complex in real life.  Thus, we developers are lulled into thinking that ''all'' logical states can be modeled as literal strings.  This usually works, but in those 10% of the cases when it's not the case, our code is usually not well structured enough to deal with it.'''&lt;br /&gt;
&lt;br /&gt;
The solution is to '''avoid using string literals'''.  Instead, separate the logical checking code of a domain into a separate class, so that it can be modified as needed.  This is the role for Specifications: defining literal values and logical states.&lt;br /&gt;
&lt;br /&gt;
In practice, we recommend having one Specification class for each domain.  For example, for the order domain, there should be an OrderSpecification class and a corresponding interface.  Because in practice specifications are usually closely related to the way data is modeled in your database, we have kept it linked through the Repository class of each domain.  Thus, to get the OrderSpecification, use its repository:&lt;br /&gt;
  OrderRepositoryInterface orderRepository = orderDomain.getOrderRepository();&lt;br /&gt;
  OrderSpecificationInterface orderSpecification = orderRepository.getOrderSpecification();&lt;br /&gt;
&lt;br /&gt;
We have also found the following best practices to be helpful when implementing specifications:&lt;br /&gt;
# If you need to check whether a condition is true or not, implement Boolean methods in the specifications, which your domain objects can use, rather than using literal strings directly in the domain objects.  For example, instead of:&lt;br /&gt;
  if (orderSpecification.ORDER_APPROVED.equals(order.getOrderStatusId())) &lt;br /&gt;
use:&lt;br /&gt;
  if (orderSpecification.isApproved(order))&lt;br /&gt;
# If you need to get certain values from your specification for other purposes, get lists of values instead of string literals.  For example, if you need to get OrderRole objects related to an order in the role of customer, instead of implementing a literal like &amp;lt;tt&amp;gt;orderSpecification.BILL_TO_CUSTOMER_ROLE&amp;lt;/tt&amp;gt;, implement a method which returns a list of potential roles: &amp;lt;tt&amp;gt;orderSpecification.billToCustomerRoleTypeIds&amp;lt;/tt&amp;gt;.  You can then use the SQL IN operator to retrieve parties in all possible bill to customer roles and thus not be constrained to use only one potential role.&lt;br /&gt;
&lt;br /&gt;
In both cases, by abstracting logical states and by making type codes more general-purpose, your code will be able to handle changing requirements much more easily.&lt;br /&gt;
&lt;br /&gt;
==An Example Using Domains==&lt;br /&gt;
&lt;br /&gt;
Now let's consider an example.  Suppose we want to create an invoice for all the order items which are not physical products and which have been marked as performed (See [[Fulfilling Orders for Services]].)  Using the ofbiz framework, we would first define   a service:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    &amp;lt;service name=&amp;quot;opentaps.invoiceNonPhysicalOrderItems&amp;quot; engine=&amp;quot;java&amp;quot;&lt;br /&gt;
        location=&amp;quot;com.opensourcestrategies.financials.invoice.InvoiceServices&amp;quot; invoke=&amp;quot;invoiceNonPhysicalOrderItems&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;description&amp;gt;Creates an invoice from the non-physical items on the order.  It will invoice from the status in the orderItemStatusId,&lt;br /&gt;
        or if it is not supplied, default to ITEM_PERFORMED.  After the invoice is created, it will attempt to change the items' status&lt;br /&gt;
        to ITEM_COMPLETE.&amp;lt;/description&amp;gt;&lt;br /&gt;
        &amp;lt;attribute name=&amp;quot;orderId&amp;quot; type=&amp;quot;String&amp;quot; mode=&amp;quot;IN&amp;quot; optional=&amp;quot;false&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;attribute name=&amp;quot;orderItemStatusId&amp;quot; type=&amp;quot;String&amp;quot; mode=&amp;quot;IN&amp;quot; optional=&amp;quot;true&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;attribute name=&amp;quot;invoiceId&amp;quot; type=&amp;quot;String&amp;quot; mode=&amp;quot;OUT&amp;quot; optional=&amp;quot;false&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;/service&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, we would create a static Java method for the service:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    public static Map invoiceNonPhysicalOrderItems(DispatchContext dctx, Map context) {&lt;br /&gt;
        LocalDispatcher dispatcher = dctx.getDispatcher();&lt;br /&gt;
        GenericValue userLogin = (GenericValue) context.get(&amp;quot;userLogin&amp;quot;);&lt;br /&gt;
        Locale locale = (Locale) context.get(&amp;quot;locale&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        String orderId = (String) context.get(&amp;quot;orderId&amp;quot;);&lt;br /&gt;
        String orderItemStatusId = (String) context.get(&amp;quot;orderItemStatusId&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        try {&lt;br /&gt;
            // validate that the order actually exists and get list of non-physical&lt;br /&gt;
            GenericValue order = delegator.findByPrimaryKey(&amp;quot;OrderHeader&amp;quot;, UtilMisc.toMap(&amp;quot;orderId&amp;quot;, orderId));&lt;br /&gt;
            if (UtilValidate.isEmpty(order)) {&lt;br /&gt;
                return ServiceUtil.returnError(&amp;quot;Order [&amp;quot; + orderId + &amp;quot;] not found&amp;quot;);&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            // set default item status&lt;br /&gt;
            if (UtilValidate.isEmpty(orderItemStatusId)) {&lt;br /&gt;
                Debug.logInfo(&amp;quot;No status specified when invoicing non-physical items on order [&amp;quot; + orderId + &amp;quot;], using ITEM_PERFORMED&amp;quot;, module);&lt;br /&gt;
                orderItemStatusId = &amp;quot;ITEM_PERFORMED&amp;quot;;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            // get the non-physical items which have been performed&lt;br /&gt;
            List&amp;lt;GenericValue&amp;gt; orderItems = order.getRelatedByAnd(&amp;quot;OrderItem&amp;quot;, UtilMisc.toMap(&amp;quot;statusId&amp;quot;, orderItemStatusId));&lt;br /&gt;
            List&amp;lt;GenericValue&amp;gt; itemsToInvoice = new ArrayList();&lt;br /&gt;
            for (GenericValue orderItem:orderItems) {&lt;br /&gt;
                if (!UtilOrder.isItemPhysical(orderItem)) {&lt;br /&gt;
                    itemsToInvoice.add(orderItem);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            // check if there are items to invoice&lt;br /&gt;
            if (UtilValidate.isEmpty(itemsToInvoice)) {&lt;br /&gt;
                return UtilMessage.createAndLogServiceError(&amp;quot;OpentapsError_PerformedItemsToInvoiceNotFound&amp;quot;, locale, module );&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            // create a new invoice for the order items&lt;br /&gt;
            Map tmpResult = dispatcher.runSync(&amp;quot;createInvoiceForOrder&amp;quot;, UtilMisc.toMap(&amp;quot;orderId&amp;quot;, orderId, &amp;quot;billItems&amp;quot;, itemsToInvoice, &amp;quot;userLogin&amp;quot;, userLogin), 7200, false);  // no new transaction&lt;br /&gt;
            if (ServiceUtil.isError(tmpResult)) {&lt;br /&gt;
                return tmpResult;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            // change the status of the order items to COMPLETED&lt;br /&gt;
            for (GenericValue orderItem:itemsToInvoice) {&lt;br /&gt;
                tmpResult = dispatcher.runSync(&amp;quot;changeOrderItemStatus&amp;quot;, UtilMisc.toMap(&amp;quot;orderId&amp;quot;, orderItem.getString(&amp;quot;orderId&amp;quot;), &amp;quot;orderItemSeqId&amp;quot;, orderItem.getString(&amp;quot;orderItemSeqId&amp;quot;), &amp;quot;statusId&amp;quot;, &amp;quot;ITEM_COMPLETED&amp;quot;, &amp;quot;userLogin&amp;quot;, userLogin));&lt;br /&gt;
            &lt;br /&gt;
            // return invoiceId of new invoice created&lt;br /&gt;
            String invoiceId = (String) tmpResult.get(&amp;quot;invoiceId&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
            tmpResult = ServiceUtil.returnSuccess();&lt;br /&gt;
            tmpResult.put(&amp;quot;invoiceId&amp;quot;, invoiceId);&lt;br /&gt;
            return tmpResult;&lt;br /&gt;
        } catch (GeneralException e) {&lt;br /&gt;
            return UtilMessage.createAndLogServiceError(e, module);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So what's there not to love about this code?&lt;br /&gt;
# It is closely tied to the database.  Even though there's not a single line of SQL here, you have to know that orders are stored in &amp;quot;OrderHeader&amp;quot;, and that it is related to &amp;quot;OrderItem&amp;quot;, and that there are fields like statusId.  You also have to use the string literals for status, like ITEM_COMPLETED, ITEM_PERFORMED, etc.&lt;br /&gt;
# This method depends on things spread out in different parts of the application, like the UtilOrder class and the createInvoiceForOrder and changeOrderItemStatus services.  &lt;br /&gt;
# This code is completely dependent on the ofbiz framework's GenericValue, entity engine delegator, and local dispatcher.&lt;br /&gt;
# Static Java methods like this, while easier to work with than minilang, do not enjoy the benefits of real object-oriented programming.&lt;br /&gt;
&lt;br /&gt;
In other words, for somebody to write this code, they have to know a lot about the framework, the data model, and the application tier.&lt;br /&gt;
&lt;br /&gt;
Here's a re-write of the everything inside the try ... catch block using the domain driven design:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
       // validate that the order actually exists and get list of non-physical&lt;br /&gt;
       OrderRepository orderRepository = new OrderRepository(new Infrastructure(dispatcher), userLogin));&lt;br /&gt;
       Order order = orderRepository.getOrderById(orderId);&lt;br /&gt;
       if (UtilValidate.isEmpty(orderItemStatusId)) {&lt;br /&gt;
           Debug.logInfo(&amp;quot;No status specified when invoicing non-physical items on order [&amp;quot; + orderId + &amp;quot;], using [&amp;quot; + OrderSpecification.ITEM_STATUS_PERFORMED + &amp;quot;]&amp;quot;, module);&lt;br /&gt;
           orderItemStatusId = OrderSpecification.ITEM_STATUS_PERFORMED;&lt;br /&gt;
       }&lt;br /&gt;
       List&amp;lt;GenericValue&amp;gt; itemsToInvoice = order.getNonPhysicalItemsForStatus(orderItemStatusId);&lt;br /&gt;
&lt;br /&gt;
       // check if there are items to invoice&lt;br /&gt;
       if (UtilValidate.isEmpty(itemsToInvoice)) {&lt;br /&gt;
           return UtilMessage.createAndLogServiceError(&amp;quot;OpentapsError_PerformedItemsToInvoiceNotFound&amp;quot;, locale, module );&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       // create a new invoice for the order items&lt;br /&gt;
       Map tmpResult = dispatcher.runSync(&amp;quot;createInvoiceForOrder&amp;quot;, UtilMisc.toMap(&amp;quot;orderId&amp;quot;, orderId, &amp;quot;billItems&amp;quot;, itemsToInvoice, &amp;quot;userLogin&amp;quot;, userLogin), 7200, false);  // no new transaction&lt;br /&gt;
       if (ServiceUtil.isError(tmpResult)) {&lt;br /&gt;
           return tmpResult;&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       // change the status of the order items to COMPLETED&lt;br /&gt;
       order.setItemsStatus(itemsToInvoice, OrderSpecification.ITEM_STATUS_COMPLETED);&lt;br /&gt;
            &lt;br /&gt;
       // return invoiceId of new invoice created&lt;br /&gt;
       String invoiceId = (String) tmpResult.get(&amp;quot;invoiceId&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
       tmpResult = ServiceUtil.returnSuccess();&lt;br /&gt;
       tmpResult.put(&amp;quot;invoiceId&amp;quot;, invoiceId);&lt;br /&gt;
       return tmpResult;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This code is the programming equivalent of the [http://en.wikipedia.org/wiki/Coelacanth missing link]: it has many features of the old code, but a few important differences as well.  What we have done is push everything related to orders to the Order Entity object, its OrderRepository, and OrderSpecification.  We don't care where the order came from, how we can get the items of an order, or even how the status codes of an order are defined any more, because those are all responsibilities of the Order domain objects.  (Even the validation that an order was obtained is handled by the OrderRepository, which will throw a RepositoryException if nothing is found from orderId.)  We are also no longer tied to the delegator, although the Order domain may itself require the delegator.  (The casting of itemsToInvoice to GenericValue is vestigal -- remember that our Entity object extends GenericValue, and a specific Java object may in turn extend Entity.)&lt;br /&gt;
&lt;br /&gt;
We are, however, still tied to the createInvoiceForOrder service and the ofbiz service engine.  That will have to wait until the next evolutionary step (which happened the next day).  Using the Service class from above, we can implement a POJO version of this service:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
public class OrderInvoicingService extends Service {&lt;br /&gt;
&lt;br /&gt;
    private static final String module = OrderInvoicingService.class.getName();&lt;br /&gt;
&lt;br /&gt;
    protected String orderId = null;&lt;br /&gt;
    protected String invoiceId = null;&lt;br /&gt;
    // by default, non-physical order items in this state will be invoiced&lt;br /&gt;
    protected String statusIdForNonPhysicalItemsToInvoice = OrderSpecification.ITEM_STATUS_PERFORMED;&lt;br /&gt;
&lt;br /&gt;
    public OrderInvoicingService(Infrastructure infrastructure, User user, Locale locale) throws ServiceException {&lt;br /&gt;
        super(infrastructure, user, locale);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    public void setOrderId(String orderId) {&lt;br /&gt;
        this.orderId = orderId;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    public String getInvoiceId() {&lt;br /&gt;
        return this.invoiceId;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Set the status id of non-physical order items to be invoiced by invoiceNonPhysicalOrderItems, or&lt;br /&gt;
     * OrderSpecification.ITEM_STATUS_PERFORMED will be used&lt;br /&gt;
     * @param statusId&lt;br /&gt;
     */&lt;br /&gt;
    public void setStatusIdForNonPhysicalItemsToInvoice(String statusId) {&lt;br /&gt;
        if (statusId != null) {&lt;br /&gt;
            statusIdForNonPhysicalItemsToInvoice = statusId;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    public void invoiceNonPhysicalOrderItems() throws ServiceException {&lt;br /&gt;
        try {&lt;br /&gt;
            // validate that the order actually exists and get list of non-physical&lt;br /&gt;
            OrderRepository orderRepository = new OrderRepository(new Infrastructure(dispatcher), user);&lt;br /&gt;
            Order order = orderRepository.getOrderById(orderId);&lt;br /&gt;
            List&amp;lt;GenericValue&amp;gt; itemsToInvoice = order.getNonPhysicalItemsForStatus(statusIdForNonPhysicalItemsToInvoice);&lt;br /&gt;
&lt;br /&gt;
            // check if there are items to invoice&lt;br /&gt;
            if (UtilValidate.isEmpty(itemsToInvoice)) {&lt;br /&gt;
                // TODO: Fix localization of errors&lt;br /&gt;
                throw new ServiceException(&amp;quot;OpentapsError_PerformedItemsToInvoiceNotFound&amp;quot;);&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            // create a new invoice for the order items&lt;br /&gt;
            // because of the way createInvoiceForOrder is written (665 lines of code!) we'd have to do some re-factoring before we can add the items to an existing invoice&lt;br /&gt;
            Map tmpResult = getDispatcher().runSync(&amp;quot;createInvoiceForOrder&amp;quot;, UtilMisc.toMap(&amp;quot;orderId&amp;quot;, orderId, &amp;quot;billItems&amp;quot;, itemsToInvoice, &amp;quot;userLogin&amp;quot;, user), 7200, false);  // no new transaction&lt;br /&gt;
            if (ServiceUtil.isError(tmpResult)) {&lt;br /&gt;
                throw new ServiceException(ServiceUtil.getErrorMessage(tmpResult));&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            // change the status of the order items to COMPLETED&lt;br /&gt;
            order.setItemsStatus(itemsToInvoice, OrderSpecification.ITEM_STATUS_COMPLETED);&lt;br /&gt;
&lt;br /&gt;
            // set the invoiceId of new invoice created&lt;br /&gt;
            this.invoiceId = (String) tmpResult.get(&amp;quot;invoiceId&amp;quot;);&lt;br /&gt;
        } catch (GeneralException ex) {&lt;br /&gt;
            throw new ServiceException(ex) ;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, the original Java static method simply has to pass the parameters to it, execute the method in the OrderInvoicingService, get its result, and pass it back.  Here's the content of that try ... catch block again:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            OrderInvoicingService invoicingService = new OrderInvoicingService(new Infrastructure(dispatcher), new User(userLogin), locale);&lt;br /&gt;
            invoicingService.setOrderId(orderId);&lt;br /&gt;
            invoicingService.setStatusIdForNonPhysicalItemsToInvoice(orderItemStatusId);&lt;br /&gt;
            invoicingService.invoiceNonPhysicalOrderItems();&lt;br /&gt;
&lt;br /&gt;
            Map tmpResult = ServiceUtil.returnSuccess();&lt;br /&gt;
            tmpResult.put(&amp;quot;invoiceId&amp;quot;, invoicingService.getInvoiceId());&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Congratulations!  Now your business logic is a POJO.  You can add annotations, use dependency injection with it, and use it with other Java frameworks now.  (Is this how that missing link felt, seeing all those primordial forests for the first time?)  &lt;br /&gt;
&lt;br /&gt;
Your service is using a legacy ofbiz service &amp;quot;createInvoiceForOrder&amp;quot; still through its getDispatcher() method, but that's not so bad.  If you want to use an ofbiz service, you should use its dispatcher.  In this example, however, you still had to write a static Java method for your service, because you are using the ofbiz static Java method service engine.  With the [[POJO Service Engine]], however, that is no longer necessary, and you can remove the code in InvoiceServices.java and call OrderInvoicingServices.invoiceNonPhysicalOrderItems() directly.&lt;br /&gt;
&lt;br /&gt;
A final round of enhancements used the base entities instead of GenericValues and the domains directory to load the order domain and the order repository, so this order invoicing service could function independent of the order management system.  See [[POJO Service Engine]] for the code sample.&lt;br /&gt;
&lt;br /&gt;
==Putting It All Together==&lt;br /&gt;
&lt;br /&gt;
Now, let's see how we could put all this together to create applications around the domain driven architecture.  As we discussed before, related data Entities could be grouped together as an Aggregate, which will have related Factories, Repositories, and Services.  For example, an aggregate of concepts related to invoicing might include the Invoice, InvoiceItem, InvoiceStatus, InvoiceContactMech, InvoiceAttribute entities as well as invoice factories, invoice repositories, and several invoicing services:&lt;br /&gt;
[[Image:Aggregate.png]]&lt;br /&gt;
&lt;br /&gt;
Several of these Aggregates may then form a Domain of related business knowledge.  For example, the Billing domain may consist of Invoice and Payment aggregates and their related factories, repositories, and services.  This Domain would interact with other domains, such as Organization, Ledger, Party, and Product:&lt;br /&gt;
[[Image:Domain.png]]&lt;br /&gt;
&lt;br /&gt;
An application, such as opentaps Financials application, could be built from several relatively independent domains:&lt;br /&gt;
[[Image:Application.png]]&lt;br /&gt;
&lt;br /&gt;
To keep them relatively independent of each other, an interface should be declared for each domain, and they should return interfaces to the repositories, factories, and services.  Interfaces are not necessary for the entities, however, since entities represent a data model, which must be implemented in the same way for all opentaps applications.  For example, Invoice will always have to have an invoice ID field, and the getInvoiceId() method should always return the value of that field.  If different underlying invoicing systems use different types of invoice IDs, it is the responsibility of the invoice repository to parse that and store it in the invoice ID field of Invoice.  The Invoice entity does not need to be changed.  Here is an example of the interface for the billing domain, defined in &amp;lt;tt&amp;gt;org.opentaps.domain.billing.BillingDomainInterface&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import org.opentaps.domain.billing.invoice.InvoiceRepositoryInterface;&lt;br /&gt;
&lt;br /&gt;
public interface BillingDomainInterface {&lt;br /&gt;
&lt;br /&gt;
    public InvoiceRepositoryInterface getInvoiceRepository();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To make life a little easier, an abstract Domain class is available to encapsulate Infrastructure and User, so you don't have to set the Infrastructure and User after getting each repository, factory, or service.  Instead, you can associate the Infrastructure and User with an actual implementation of a domain, and it will automatically populated Infrastructure and User for you.  Here is its corresponding implementation in opentaps financials, &amp;lt;tt&amp;gt;org.opentaps.financials.domain.billing&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
public class BillingDomain extends Domain implements BillingDomainInterface {&lt;br /&gt;
&lt;br /&gt;
    public InvoiceRepository getInvoiceRepository() {&lt;br /&gt;
        InvoiceRepository repository = new InvoiceRepository();&lt;br /&gt;
        repository.setInfrastructure(getInfrastructure());&lt;br /&gt;
        repository.setUser(getUser());&lt;br /&gt;
        return repository;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
There should only be one directory of domains at any one time, so that all the opentaps applications use the same domains.  In opentaps, this domain directory is defined in the DomainsDirectory class, and the actual domains are defined in &amp;lt;tt&amp;gt;hot-deploy/opentaps-common/config/domains-directory.xml&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;beans&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;bean id=&amp;quot;opentapsBillingDomain&amp;quot; class=&amp;quot;org.opentaps.financials.domain.billing.BillingDomain&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;bean id=&amp;quot;domainsDirectory&amp;quot; class=&amp;quot;org.opentaps.domain.DomainsDirectory&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;property name=&amp;quot;billingDomain&amp;quot;&amp;gt;&amp;lt;ref bean=&amp;quot;opentapsBillingDomain&amp;quot;/&amp;gt;&amp;lt;/property&amp;gt;&lt;br /&gt;
    &amp;lt;/bean&amp;gt;&lt;br /&gt;
    &lt;br /&gt;
&amp;lt;/beans&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that domains are declared explicitly in the DomainsDirectory, rather than as a Map.  To add a new domain, you must modify the DomainsDirectory class to add a new member plus accessor (set/get) methods.  To change your domains, you can just modify this xml file.  For example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;beans&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;bean id=&amp;quot;myBillingDomain&amp;quot; class=&amp;quot;com.mycompany.domain.billing.BillingDomain&amp;quot;/&amp;gt;&lt;br /&gt;
    &lt;br /&gt;
    &amp;lt;bean id=&amp;quot;domainsDirectory&amp;quot; class=&amp;quot;org.opentaps.domain.DomainsDirectory&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;property name=&amp;quot;billingDomain&amp;quot;&amp;gt;&amp;lt;ref bean=&amp;quot;myBillingDomain&amp;quot;/&amp;gt;&amp;lt;/property&amp;gt;&lt;br /&gt;
    &amp;lt;/bean&amp;gt;&lt;br /&gt;
    &lt;br /&gt;
&amp;lt;/beans&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
When you restart opentaps, the new domains will be loaded.&lt;br /&gt;
&lt;br /&gt;
To load your domains, use &amp;lt;tt&amp;gt;DomainsLoader&amp;lt;/tt&amp;gt;, which can be instantiated with Infrastructure and User:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// get the domain&lt;br /&gt;
DomainsLoader dl = new DomainsLoader(new Infrastructure(dispatcher), new User(admin));&lt;br /&gt;
DomainsDirectory domains = dl.loadDomainsDirectory();&lt;br /&gt;
BillingDomainInterface billingDomain = domains.getBillingDomain();&lt;br /&gt;
&lt;br /&gt;
// now we can use it&lt;br /&gt;
InvoiceRepositoryInterface invoiceRepository = billingDomain.getInvoiceRepository();&lt;br /&gt;
Invoice invoice = invoiceRepository.getInvoiceById(&amp;quot;10000&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Danutc</name></author>
		
	</entry>
	<entry>
		<id>https://docs.opentaps.org/docs/index.php?title=User_talk:Danutc&amp;diff=3972</id>
		<title>User talk:Danutc</title>
		<link rel="alternate" type="text/html" href="https://docs.opentaps.org/docs/index.php?title=User_talk:Danutc&amp;diff=3972"/>
		<updated>2009-06-03T07:42:24Z</updated>

		<summary type="html">&lt;p&gt;Danutc: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* [[BPM Integration]]&lt;br /&gt;
* [[BPM - Getting Started]]&lt;br /&gt;
* [[jBPM - Opentaps 1.x Integration Prototype]]&lt;br /&gt;
* [[danc - temp]]&lt;/div&gt;</summary>
		<author><name>Danutc</name></author>
		
	</entry>
</feed>