Showing posts with label cloud. Show all posts
Showing posts with label cloud. Show all posts

Monday, January 6, 2014

how-to cloudbees minuteproject 4 openxava

Minuteproject releases a demo Openxava application to be hosted on cloudbees at http://petshopox.minuteproject.cloudbees.net/

Following those steps, you can recreate an Openxava application with minuteproject and host it on cloudbees.
All those steps are IDE-free (i.e. productivity oriented) all is done by command line!
This is a requirement for automation, since it is very easy to integrate with a CI tool such as Jenkins.
Meanwhile the code is compatible with Eclipse (for java), Mysql Workbench (for DB design + release) and Cloudbees website for manual release.

Principles

Generate an openxava application with minuteproject base on an DB structure.
The database use here is petshop; for the generation the database can be local or already hosted on cloudbees PaaS. At running the database is the one of the cloudbees PaaS.

The generated Openxava compliant artifacts are built into an Openxava application.
The application is to be deployed on a tomcat server.
The application relies on a JNDI Datasource on the tomcat server.

After setting the database on cloudbees and the connection pool cloudbees tomcat server, the application can be deployed.

Ingredients

Infrastructure

JDK 1.6+
Minuteproject last version
Openxava 4.9
Mysql DB
Tomcat
Cloudbees

  • sdk
  • account

Set up Cloudbees

Database

Create a mysql db schema on cloudbees
bees db:create petshopDB
   
Retrieve the DB info (connection info: server, port, user...) all you need to create you connection pool

bees app:info -db petshopDB 


Application

Create application

bees app:create -petshopox
     

Datasource

This is use get the alias use in the persistence.xml datasource (java:comp/env/jdbc/petshopDS)

bees app:bind -db petshopDB -a petshopox -as petshopDS 


Database setup

Run you database script from the information receive via $bees db:info -db petshopDB

Sample
mysql --host=ec2-50-19-213-178.compute-1.amazonaws.com --user=xxxx --password=xxxx --port=3306 xxx < petshop.sql
petshop-mysql.sql can be found in MP_HOME/sample/schema/

Generation

Full details at http://minuteproject.wikispaces.com/OpenXava
The generation is done by Minuteproject.
Minuteproject generation by command line comes by passing a configuration file name to model-generation.

Sample
model-generation petshop.xml

Sample petshop.xml configuration
<!DOCTYPE root>
<generator-config xmlns="http://minuteproject.sf.net/xsd/mp-config"
	xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"
	xs:noNamespaceSchemaLocation="mp-config.xsd">
	<!-- adapted for cloudbees petshop model -->
	<configuration>
		<conventions>
			<target-convention type="enable-updatable-code-feature" />
		</conventions>
		<model name="petshop" version="1.0" package-root="net.sf.mp.demo">
			<data-model>
				<driver name="mysql" version="5.1.16" groupId="mysql"
					artifactId="mysql-connector-java"></driver>
				<dataSource>
					<driverClassName>org.gjt.mm.mysql.Driver</driverClassName>
					<url>jdbc:mysql://localhost:3306/petshop</url>
					<username>root</username>
					<password>mysql</password>
				</dataSource>
				<primaryKeyPolicy oneGlobal="false">
					<primaryKeyPolicyPattern name="autoincrementPattern"></primaryKeyPolicyPattern>
				</primaryKeyPolicy>
			</data-model>
			<business-model>
				<generation-condition>
					<condition type="exclude" startsWith="DUAL"></condition>
					<condition type="exclude" startsWith="ID_GEN"></condition>
					<condition type="exclude" startsWith="SEQUENCE"></condition>
				</generation-condition>
				<business-package default="pet">
					<condition type="package" startsWith="PRODUCT" result="product"></condition>
					<condition type="package" startsWith="ITEM" result="product"></condition>
				</business-package>
				<enrichment>
					<conventions>
						<entity-naming-convention type="apply-strip-table-name-prefix"
							pattern-to-strip="SYS,FIN" />
						<reference-naming-convention
							type="apply-referenced-alias-when-no-ambiguity" is-to-plurialize="true"></reference-naming-convention>
					</conventions>
					<package name="product">
						<entity-group entities="PRODUCT"></entity-group>
						<entity-group entities="ITEM"></entity-group>
					</package>
					<entity name="PRODUCT" alias="MY_GOOD_PRODUCT">
					</entity>
					<entity name="ITEM" alias="MY_GOOD_ITEM" comment="my item table">
						<field name="PRODUCTID" alias="THIS_IS_MY_PRODUCT" comment="my product field reference"></field>
					</entity>
					<entity name="CATEGORY" content-type="reference-data">
						<field name="DESCRIPTION" ordering="asc" label="my description"
							is-searchable="true"></field>
						<field name="NAME" ordering="asc"></field>
					</entity>
					<entity name="TAG" content-type="reference-data">
						<field name="TAG" ordering="asc">
							<semantic-reference>
								<sql-path path="NAME" />
							</semantic-reference>
						</field>
					</entity>
				</enrichment>
			</business-model>
			<statement-model>
				<enrichment>
					<conventions>
						<sdd-dummy-primarykey-convention add="true" />
					</conventions>
				</enrichment>
				<queries>
					<query name="get address abstract" id="dashAddress" type="dashboard"
						category="pie-chart">
						<query-body> <!-- dimensions column first -->
							<value>
<![CDATA[select city, count(*) as nb from address group by city order by count(*) desc limit ?]]>
                            </value>
						</query-body>
						<query-params>
							<query-param name="top city" is-mandatory="false"
								type="INT" sample="37" default="10"></query-param>
						</query-params>
					</query>
					<query name="get address summary" id="dashCity" type="dashboard"
						category="bar-chart">
						<query-body> <!-- dimensions column first -->
							<value>
<![CDATA[select city, count(*) as nb, count(*) as nb2 from address group by city order by count(*) desc]]>
                            </value>
						</query-body>
					</query>
					<query name="get addresses by criteria" id="c">
						<query-body>
							<value>
<![CDATA[select * from address where lcase(city) like ?]]>
                            </value>
						</query-body>
						<query-params>
							<query-param name="city" type="STRING" sample="'S'"
								convert="lowercase,append%" default="%">
							</query-param>
						</query-params>
					</query>
				</queries>
			</statement-model>
		</model>
		<targets catalog-entry="OpenXava" >
			<property name="environment" value="remote"></property>
			<property name="cloud-platform" value="cloudbees"></property>
			<property name="embed-driver" value="true"></property>
		</targets>
	</configuration>
</generator-config>

Appart from the 'classical' enrichment facilities, the interesting point are the properties under the targets node:
name="environment" value="remote" 
Implies to use a connection pool (for persistence.xml)
name="cloud-platform" value="cloudbees" 
Performs additional build facilities for Openxava on cloudbees
The OX war has to hold jta.jar, ejb.jar, mysql driver jar.
  • jta.jar and ejb.jar are embedded in tomcat/lib on the OX delivery.
name="embed-driver" value="true" 

  • mysql driver jar is shipped on MP delivery

  • Remark: the last 2 options are available on Minuteproject 0.8.6

    Build

    On the generated directory
    set/export OX_HOME
    set/export MP_HOME
    Run

    build-petshop.cmd/sh

    The application petshop.war goes into OX_HOME/workspace/petshop.dist

    The application is ready to be deployed on Cloudbees.

    Deploy

    bees app:deploy -a petshopox -t tomcat7 -Rjava_version=1.7 petshop.war

    petshopox is the name of the application on cloudbees

    Enjoy

    Monday, April 29, 2013

    How-to cloudbees minuteproject 4 primefaces

    Introduction

    Cloudbees offers JEE app and Mysql DB storage.
    Minuteproject generates CRUD and reporting application for Primefaces based on a database model.

    This article is based on upon the petshop mysql database.
    The result can be show on cloudbees at http://petshopapp.minuteproject.cloudbees.net

    The application, minuteproject configuration and DB model can be found on google code at https://code.google.com/p/minuteproject/downloads/detail?name=petshop-mp4primeface-cloudbees.zip

    Prerequisits

    Download and install Minuteproject set MP_HOME
    Download and install Cloudbees SDK set BEES_HOME
    Create a cloudbees account
    Mysql local DB running with a schema.

    Steps

    In order to get Cloudbees Primefaces application quickly follow the next steps.

    Cloudbees setups

    Cloudbees setup can be done on the website, but also by the following command lines

    Cloudbees app

    $bees app:create petshopapp

    Cloudbees  DB

    $bees db:create petshopappDB -u username -p password

    Cloudbees binding

    $bees app:bind -db petshopappDB -a petshopapp -as petshopAppDS

    Deployment on Cloudbees

    $bees app:deploy -a account/petshopapp -t tomcat7 path-to-your-app.war
    This step is performed after you have build your app.

    Install you DB schema

    Get the server connection information:
    • server
    • port
    • user_name
    • pass_word

    $mysql --user=user_name --password=pass_word --host=server --port=port < schema.sql

    Minuteproject 4 Primefaces app

    To create a primefaces application, minuteproject can generate one based on a database structure.
    Minuteproject runs with a command line.
    The configuration file used is petshop-mp4primeface-cloudbees.zip 

    Configuration

    The configuration file can be found in the zip under mp-config-JSF-Spring.xml
    The main points of the file are
    <!DOCTYPE root>
    <generator-config xmlns="http://minuteproject.sf.net/xsd/mp-config" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema-instance" 
    xs:noNamespaceSchemaLocation="mp-config.xsd">
        <configuration>
      <conventions>
       <target-convention type="enable-updatable-code-feature" />
      </conventions> 
      <model name="petshop" version="1.0" package-root="net.sf.mp.demo">   
       <data-model>
                    <driver name="mysql" version="5.1.16" groupId="mysql"
                        artifactId="mysql-connector-java"></driver>
                    <dataSource>
                        <driverClassName>org.gjt.mm.mysql.Driver</driverClassName>
                        <url>jdbc:mysql://127.0.0.1:3306/petshop</url>
                        <username>root</username>
                        <password>mysql</password>
                    </dataSource>
                    <primaryKeyPolicy oneGlobal="false">
                        <primaryKeyPolicyPattern name="autoincrementPattern"></primaryKeyPolicyPattern>
                    </primaryKeyPolicy>
       </data-model>
       <business-model>
        <generation-condition>
         <condition type="exclude" startsWith="DUAL"></condition>
         <condition type="exclude" startsWith="ID_GEN"></condition>
         <condition type="exclude" startsWith="SEQUENCE"></condition>
        </generation-condition>  
        <business-package default="pet">
         <condition type="package" startsWith="PRODUCT" result="product"></condition>
         <condition type="package" startsWith="ITEM" result="product"></condition>
        </business-package> 
        <enrichment>
           <conventions>
              <entity-naming-convention type="apply-strip-table-name-prefix" pattern-to-strip="SYS,FIN"/>
              <reference-naming-convention type="apply-referenced-alias-when-no-ambiguity" is-to-plurialize="true"></reference-naming-convention>
           </conventions>
            <package name="product">
             <entity-group entities="PRODUCT"></entity-group>
             <entity-group entities="ITEM"></entity-group>
            </package>
         <entity name="PRODUCT" alias="MY_GOOD_PRODUCT">    
         </entity>        
         <entity name="ITEM" alias="MY_GOOD_ITEM" comment="my item table">
          <field name="PRODUCTID" alias="THIS_IS_MY_PRODUCT" comment="my product field reference"></field>     
         </entity>        
         <entity name="CATEGORY" content-type="reference-data" >
            <field name="DESCRIPTION" ordering="asc" label="my description" is-searchable="true"></field>
            <field name="NAME" ordering="asc" ></field>
            <semantic-reference>
              <sql-path path="NAME"/>
            </semantic-reference>
         </entity>
        </enrichment>     
       </business-model>
                <statement-model>
                    <queries>
                         <query name="get address abstract" id="dashAddress" type="dashboard" category="pie-chart">
                             <query-body> <!-- dimensions column first -->
                             <value>
    <![CDATA[select city, count(*) as nb from address group by city order by count(*) desc limit ? ]]>
                                </value>
                             </query-body>
                             <query-params>
                                 <query-param name="top city" is-mandatory="false" type="INT" sample="37" default="10"></query-param>
                             </query-params>
                         </query>
                         <query name="get address summary" id="dashCity" type="dashboard" category="bar-chart">
                             <query-body> <!-- dimensions column first -->
                             <value>
    <![CDATA[select city, count(*) as nb, count(*) as nb2 from address group by city order by count(*) desc]]>
                                </value>
                             </query-body>
                         </query>
                         <query name="get addresses by criteria" id="c">
                             <query-body><value>
    <![CDATA[select * from address where lcase(city) like ?]]>
                                </value>
                             </query-body>
                             <query-params>
                                 <query-param name="city" type="STRING" sample="'S'" convert="lowercase,append%" default="%">
                                 </query-param>
                             </query-params>
                         </query>
                    </queries>
                </statement-model>
      </model> 
    
    The database driver is mysql and the primary key strategy is autoincrement for not natural primary key
    Product and Item tables have been aliased
    Product and Item tables goes in product package, which means graphically a distinct menu access.
    Category is a reference-data table, which means caching and access via drop down list

    Statement:
    Misc statement queries can be used to produce report in forms of list, pie-chart, bar-chart.

    Generate

    Copy the file in $MP_HOME/mywork/config From a prompt run
    $model-generation mp-config-JSF-Spring.xml
    

    Build

    The generation result is in $MP_HOME/dev/JSF/petshop From a prompt run
    $mvn clean package
    

    Customise package for cloudbees


    Cloudbees context

    Optional step to perform if your not creating the binding between the Application and DB.

    Add a Cloudbees file context.xml

    In /WEB-INF/lib add context.xml in war/META-INF
    <Context>
    <Resource name="jdbc/petshopAppDS"
                auth="Container"
                type="javax.sql.DataSource"
    
                url="jdbc:${DATABASE_URL}"
                username="${USER_NAME}"
                password="${PASS_WORD}"
    
                driverClassName="com.mysql.jdbc.Driver"
    
                maxActive="20"
                maxIdle="1"
                maxWait="10000"
                removeAbandoned="true"
                removeAbandonedTimeout="60"
                logAbandoned="true"
    
                validationQuery="SELECT 1"
                testOnBorrow="true"
                />
    </Context>
    

    The ${DATABASE_URL} is retrieved from 

    $bees db:info petshopapp

    Persistence.xml

    adapt persistence.xml with Cloudbees binding alias
    change non-jta-data-source node with java:comp/env/jdbc/petshopAppDS
    remove properties hibernate connection info

    The persistence.xml is located in petshopBackEnd-1.0-SNAPSHOT.jar!/META-INF

    <?xml version="1.0"?>
    <persistence xmlns="http://java.sun.com/xml/ns/persistence"
                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                 xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
                 version="1.0">
    <!--MP-MANAGED-UPDATABLE-BEGINNING-DISABLE @PERSISTENCE-UNIT-petshop@-->
        <persistence-unit name="petshop">
    <!--MP-MANAGED-UPDATABLE-ENDING-->
    <non-jta-data-source>java:comp/env/jdbc/petshopAppDS</non-jta-data-source>
            <provider>org.hibernate.ejb.HibernatePersistence</provider>
            <!-- pet --> 
            <class>net.sf.mp.demo.petshop.domain.pet.Address</class>
            <class>net.sf.mp.demo.petshop.domain.pet.Category</class>
            <class>net.sf.mp.demo.petshop.domain.pet.Sellercontactinfo</class>
            <class>net.sf.mp.demo.petshop.domain.pet.Tag</class>
            <class>net.sf.mp.demo.petshop.domain.pet.Ziplocation</class>
    
            <!-- product --> 
            <class>net.sf.mp.demo.petshop.domain.product.MyGoodItem</class>
            <class>net.sf.mp.demo.petshop.domain.product.MyGoodProduct</class>
    
    
            <properties>
                <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
                <property name="hibernate.cache.provider_class" value="net.sf.ehcache.hibernate.SingletonEhCacheProvider" />
                <property name="net.sf.ehcache.configurationResourceName" value="/ehcache.xml" />
                <property name="hibernate.cache.use_query_cache" value="true" />
                <property name="hibernate.cache.use_second_level_cache" value="true" />
    <!--MP-MANAGED-ADDED-AREA-BEGINNING @properties@-->
    <!--MP-MANAGED-ADDED-AREA-ENDING @properties@-->
            </properties> 
    
    
    <!--MP-MANAGED-ADDED-AREA-BEGINNING @persistence-unit@-->
    <!--MP-MANAGED-ADDED-AREA-ENDING @persistence-unit@-->
        </persistence-unit>
    
    <!--MP-MANAGED-ADDED-AREA-BEGINNING @persistence@-->
    <!--MP-MANAGED-ADDED-AREA-ENDING @persistence@-->
    
    </persistence>
    
    

    Deploy

    $bees app:deploy -a account/petshopapp -t tomcat7 JSF/target/petshopApp.war
    where account is the account you created

    Tomcat7 target ensure the EL libraries are present.

    Result


    Improvements

    For those who think it's a bit long, they are right!
    Most of the step could be simplified since most of it could be generated!

    Minuteproject will add a cloud track with cloudbees for that in the next release.