Skip to content
Browse files

added the Hotels booking micro application. It is using the ActiveJDB…

…C framework for ORM and it was designed for benchmarking the Micro framework. The database used is H2 using BoneCP for JDBC pooling. JMeter script and stats attached
  • Loading branch information...
1 parent 295839e commit dbd576d82f7c1eaa5e9866aae1a2d5d4d800184a @florinpatrascu committed Mar 3, 2013
Showing with 3,785 additions and 3 deletions.
  1. +2 −3 README.md
  2. BIN micro-aj/.DS_Store
  3. +72 −0 micro-aj/README.md
  4. BIN micro-aj/WEB-INF/booking_development.h2.db
  5. +89 −0 micro-aj/WEB-INF/build.xml
  6. +3 −0 micro-aj/WEB-INF/classes/activejdbc_models.properties
  7. BIN micro-aj/WEB-INF/classes/controllers/BookingController.class
  8. BIN micro-aj/WEB-INF/classes/controllers/CancelReservation.class
  9. BIN micro-aj/WEB-INF/classes/controllers/FindHotels.class
  10. BIN micro-aj/WEB-INF/classes/controllers/HotelInfo.class
  11. BIN micro-aj/WEB-INF/classes/controllers/Login.class
  12. BIN micro-aj/WEB-INF/classes/controllers/Register.class
  13. BIN micro-aj/WEB-INF/classes/controllers/filters/After.class
  14. BIN micro-aj/WEB-INF/classes/controllers/filters/Before.class
  15. +31 −0 micro-aj/WEB-INF/classes/ehcache.xml
  16. +12 −0 micro-aj/WEB-INF/classes/log4j.properties
  17. BIN micro-aj/WEB-INF/classes/models/Booking.class
  18. BIN micro-aj/WEB-INF/classes/models/Customer.class
  19. BIN micro-aj/WEB-INF/classes/models/Hotel.class
  20. +10 −0 micro-aj/WEB-INF/config/application.bsh
  21. +21 −0 micro-aj/WEB-INF/config/db.yml
  22. +7 −0 micro-aj/WEB-INF/config/extensions/activejdbc_m.yml
  23. +207 −0 micro-aj/WEB-INF/config/extensions/activejdbc_m/lib/LICENSE
  24. BIN micro-aj/WEB-INF/config/extensions/activejdbc_m/lib/activejdbc-1.4.7-SNAPSHOT.jar
  25. BIN micro-aj/WEB-INF/config/extensions/activejdbc_m/lib/activejdbc-instrumentation-1.4.7-SNAPSHOT.jar
  26. BIN micro-aj/WEB-INF/config/extensions/activejdbc_m/lib/activejdbc_m-0.1.1.jar
  27. BIN micro-aj/WEB-INF/config/extensions/activejdbc_m/lib/bonecp-0.7.1.RELEASE.jar
  28. BIN micro-aj/WEB-INF/config/extensions/activejdbc_m/lib/guava-11.0.2.jar
  29. BIN micro-aj/WEB-INF/config/extensions/activejdbc_m/lib/h2-1.3.170.jar
  30. BIN micro-aj/WEB-INF/config/extensions/activejdbc_m/lib/javalite-common-1.4.7-SNAPSHOT.jar
  31. BIN micro-aj/WEB-INF/config/extensions/activejdbc_m/lib/javassist-3.17.1-GA.jar
  32. +7 −0 micro-aj/WEB-INF/config/extensions/i18N.yml
  33. +1 −0 micro-aj/WEB-INF/config/locales/messages_en.properties
  34. +1 −0 micro-aj/WEB-INF/config/locales/messages_fr.properties
  35. +32 −0 micro-aj/WEB-INF/config/micro-config.yml
  36. +16 −0 micro-aj/WEB-INF/config/routes.yml
  37. +95 −0 micro-aj/WEB-INF/controllers/BookingController.java
  38. +52 −0 micro-aj/WEB-INF/controllers/CancelReservation.java
  39. +46 −0 micro-aj/WEB-INF/controllers/FindHotels.java
  40. +48 −0 micro-aj/WEB-INF/controllers/HotelInfo.java
  41. +53 −0 micro-aj/WEB-INF/controllers/Login.java
  42. +9 −0 micro-aj/WEB-INF/controllers/Logout.bsh
  43. +62 −0 micro-aj/WEB-INF/controllers/Register.java
  44. +27 −0 micro-aj/WEB-INF/controllers/filters/After.java
  45. +10 −0 micro-aj/WEB-INF/controllers/filters/AfterThanks.bsh
  46. +27 −0 micro-aj/WEB-INF/controllers/filters/Before.java
  47. +1 −0 micro-aj/WEB-INF/lib/README.md
  48. BIN micro-aj/WEB-INF/lib/joda-time-2.1.jar
  49. +34 −0 micro-aj/WEB-INF/models/Booking.java
  50. +17 −0 micro-aj/WEB-INF/models/Customer.java
  51. +10 −0 micro-aj/WEB-INF/models/Hotel.java
  52. BIN micro-aj/WEB-INF/smith-1.0.jar
  53. +5 −0 micro-aj/WEB-INF/views/content/about.md
  54. +124 −0 micro-aj/WEB-INF/views/content/book.html
  55. +6 −0 micro-aj/WEB-INF/views/content/cancel.html
  56. +9 −0 micro-aj/WEB-INF/views/content/config/book.yml
  57. +3 −0 micro-aj/WEB-INF/views/content/config/cancel.yml
  58. +11 −0 micro-aj/WEB-INF/views/content/config/confirm.yml
  59. +9 −0 micro-aj/WEB-INF/views/content/config/hotel.yml
  60. +9 −0 micro-aj/WEB-INF/views/content/config/index.yml
  61. +9 −0 micro-aj/WEB-INF/views/content/config/login.yml
  62. +10 −0 micro-aj/WEB-INF/views/content/config/register.yml
  63. +3 −0 micro-aj/WEB-INF/views/content/config/thanks.yml
  64. +48 −0 micro-aj/WEB-INF/views/content/confirm.html
  65. +30 −0 micro-aj/WEB-INF/views/content/hotel.html
  66. +52 −0 micro-aj/WEB-INF/views/content/index.html
  67. +50 −0 micro-aj/WEB-INF/views/content/login.html
  68. +68 −0 micro-aj/WEB-INF/views/content/register.html
  69. +20 −0 micro-aj/WEB-INF/views/content/thanks.html
  70. +19 −0 micro-aj/WEB-INF/views/partials/footer.html
  71. +25 −0 micro-aj/WEB-INF/views/partials/header.html
  72. +22 −0 micro-aj/WEB-INF/views/partials/hotel_info.html
  73. +12 −0 micro-aj/WEB-INF/views/partials/sidebar.html
  74. +30 −0 micro-aj/WEB-INF/views/templates/404.html
  75. +31 −0 micro-aj/WEB-INF/views/templates/500.html
  76. +81 −0 micro-aj/WEB-INF/views/templates/default.html
  77. +52 −0 micro-aj/WEB-INF/views/templates/default.md
  78. +49 −0 micro-aj/WEB-INF/web.xml
  79. +16 −0 micro-aj/arun.sh
  80. +9 −0 micro-aj/bootstrap/css/bootstrap-responsive.min.css
  81. +9 −0 micro-aj/bootstrap/css/bootstrap.min.css
  82. BIN micro-aj/bootstrap/img/glyphicons-halflings-white.png
  83. BIN micro-aj/bootstrap/img/glyphicons-halflings.png
  84. +6 −0 micro-aj/bootstrap/js/bootstrap.min.js
  85. +182 −0 micro-aj/datepicker/css/datepicker.css
  86. +470 −0 micro-aj/datepicker/js/bootstrap-datepicker.js
  87. BIN micro-aj/favicon.ico
  88. BIN micro-aj/fonts/.DS_Store
  89. BIN micro-aj/fonts/Inconsolata/Inconsolata-Bold.ttf
  90. BIN micro-aj/fonts/Inconsolata/Inconsolata-Regular.ttf
  91. +92 −0 micro-aj/fonts/Inconsolata/OFL.txt
  92. +14 −0 micro-aj/hot_queries.txt
  93. BIN micro-aj/images/b_black.png
  94. BIN micro-aj/images/hotels-logo.png
  95. BIN micro-aj/images/keyboard.png
  96. BIN micro-aj/images/micro-aj-10-users-per-sec.png
  97. BIN micro-aj/images/micro-aj-20-users-per-sec.png
  98. BIN micro-aj/images/micro-aj-40-users-per-sec.png
  99. BIN micro-aj/images/micro-aj-home-page.png
  100. BIN micro-aj/images/micro-icon.png
  101. BIN micro-aj/images/micro-logo.png
  102. +81 −0 micro-aj/jetty.xml
  103. +324 −0 micro-aj/js/bootstrap-form.js
  104. +560 −0 micro-aj/micro-aj.jmx
  105. +21 −0 micro-aj/run.sh
  106. +8 −0 micro-aj/styles/bootstrap-form.css
  107. +186 −0 micro-aj/styles/github.css
  108. +16 −0 micro-aj/styles/main.css
  109. +2 −0 micro-aj/users.txt
View
5 README.md
@@ -12,7 +12,8 @@ In this repo:
- `lib` - a folder containing the latest Micro binaries, frequently updated.
- `hello_world` - a minimalistic Micro web application
- - `aj_demo` - a very small Micro web application demonstrating the integration with the [ActiveJDBC](https://code.google.com/p/activejdbc/) framework for ORM. ActiveJDBC is a Java implementation of the Active Record design pattern. It was inspired by ActiveRecord ORM from Ruby on Rails.<p></p>
+ - `aj_demo` - a very small Micro web application demonstrating the integration with the [ActiveJDBC](https://code.google.com/p/activejdbc/) framework for ORM. ActiveJDBC is a Java implementation of the Active Record design pattern. It was inspired by ActiveRecord ORM from Ruby on Rails.
+ - `micro-aj` - a Hotel booking demo app used for benchmarking the Micro framework. It is loosely modelled after the Wicket application used by Peter Thomas in his article: [Seam / JSF vs Wicket](http://ptrthomas.wordpress.com/2009/01/14/seam-jsf-vs-wicket-performance-comparison/)<p></p>. The app repo contains details about the stress sessions and some simple stats.
- *more to come*
and an arbitrary number of folders containing examples of Micro web applications. Each example will have a `run.sh` (or `run.bat`) command line that will start Micro in server mode and a `README.md` file describing the example.
@@ -40,5 +41,3 @@ Follow us on Twitter: [@micro_mvc](http://twitter.com/micro_mvc), for Micro rela
- [micro](https://github.com/florinpatrascu/micro) - a modular micro MVC framework for Java web applications, the main repository.
- [micro-docs](https://github.com/florinpatrascu/micro-docs) - the Micro documentation
- [jrack](https://github.com/florinpatrascu/jrack) - another port of Rack to Java
-
-
View
BIN micro-aj/.DS_Store
Binary file not shown.
View
72 micro-aj/README.md
@@ -0,0 +1,72 @@
+## Hotels Booking
+
+A minimalistic *Hotel booking* demo app used for benchmarking the Micro framework. It is loosely modelled after the Wicket application used by Peter Thomas in his article: [Seam / JSF vs Wicket](http://ptrthomas.wordpress.com/2009/01/14/seam-jsf-vs-wicket-performance-comparison/). The app repo contains the simple stats grabbed during the benchmarking sessions.
+
+### Available functionality:
+
+ - Login/Logout and User registration
+ - search hotels
+ - full pagination support
+ - view hotel details
+ - booking a reservation
+ - view hotel reservations
+ - cancel reservations
+ - using [Bootstrap Twitter](http://twitter.github.com/bootstrap/index.html) for styling
+
+This is the main page of the web application:
+
+![Home page](images/micro-aj-home-page.png)
+
+### Additional stuff included
+Apart the application itself the following extras are included:
+
+ - the latest [Bootstrap Twitter](http://twitter.github.com/bootstrap/index.html) release
+ - a pre-release binary of the [ActiveJDBC](https://code.google.com/p/activejdbc/)(AJ) µ Extensions using the [BoneCP](http://jolbox.com/) Java database connection pool (JDBC Pool) library.
+ - the ANT scripts for compiling the AJ models and controllers
+ - the JMeter script used for benchmarking the application.
+ - various screen grabs containing the JMeter results, in case you don't wish to run them by yourself
+ - a jetty.xml file that you can use to customize your µ applications i.e. logging, min/max threads, stderr output, SSL and more. Please make sure you're using the latest Micro distribution!
+
+### Benchmarks results
+The following results were obtained on an iMac 2.8GHz Intel Core I5, 8GB mem. The JVM runtime configuration is using the same setup I have for my free Heroku instance hosting the Micro [documentation web site](micro-docs.simplegames.ca). Attached for brevity:
+
+ -Xmx128m -Xss512k -XX:+UseCompressedOops
+
+Below are the screens captured at the end of each of the three benchmarking sessions.
+
+## 10 Users
+
+ ![10-users](images/micro-aj-10-users-per-sec.png)
+
+## 20 Users
+
+ ![40-users](images/micro-aj-20-users-per-sec.png)
+
+## 40 Users
+
+ ![40-users](images/micro-aj-40-users-per-sec.png)
+
+### To use it:
+
+ - check if Micro is installed properly; see the [docs](http://micro-docs.simplegames.ca/), for more details.
+ - quickly check if Micro was built and it can be used:
+ `$ micro -v`; you should see something like this: `Micro 0.1.2`
+ - start this web application:
+ `$ cd micro-aj`
+ `$ ./run.sh`
+
+Optionally, if you want to modify the ActiveJDBC models or the µ controllers:
+
+ $ cd WEB-INF
+ $ ant
+The steps above will compile all the classes and will instrument the ActiveJDBC models. The binaries are provided for your convenience. Sorry, Maven users :P
+
+if the server is running, you can access this app at:
+
+ `http://localhost:8080` or `http://0.0.0.0:8080`
+
+### To stop the app
+
+Simply press `CTRL-C` in the console where the application was started.
+
+Feedback is highly appreciated, thank you.
View
BIN micro-aj/WEB-INF/booking_development.h2.db
Binary file not shown.
View
89 micro-aj/WEB-INF/build.xml
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ ~ This script is used for fast instrumentation of the project's models as well as
+ ~ for compiling micro controllers
+ -->
+
+<project default="instrument" basedir=".">
+ <property environment="env"/>
+ <property name="micro.dir" value="${env.MICRO_HOME}"/>
+ <property name="out.dir" value="classes"/>
+ <property name="lib.dir" value="config/extensions/activejdbc_m/lib"/>
+
+ <tstamp>
+ <format property="TODAY" pattern="yyyy-MM-dd HH:mm:ss"/>
+ </tstamp>
+
+ <path id="instrument_classpath">
+ <pathelement location="${out.dir}"/>
+ <path location="${lib.dir}/activejdbc-1.4.7-SNAPSHOT.jar"/>
+ <path location="${lib.dir}/activejdbc-instrumentation-1.4.7-SNAPSHOT.jar"/>
+ <path location="${lib.dir}/javassist-3.17.1-GA.jar"/>
+
+ <!--
+ <path location="${user.home}/.m2/repository/org/javalite/activejdbc-instrumentation/1.4.5/activejdbc-instrumentation-1.4.5.jar"/>
+ <path location="${user.home}/.m2/repository/javassist/javassist/3.8.0.GA/javassist-3.8.0.GA.jar"/>
+ <path location="${user.home}/.m2/repository/org/javalite/activejdbc/1.4.5/activejdbc-1.4.5.jar"/>
+ -->
+ </path>
+
+ <!-- Compiler options -->
+ <property name="compiler.debug" value="on"/>
+ <property name="compiler.optimize" value="on"/>
+ <property name="compiler.generate.no.warnings" value="off"/>
+ <property name="compiler.encoding" value="utf-8"/>
+ <property name="compiler.args" value=""/>
+ <property name="compiler.source" value="1.6"/>
+ <property name="compiler.target" value="1.6"/>
+
+
+ <target name="compile" description="compile and instrument user models">
+ <delete dir="${out.dir}/models"/>
+ <delete dir="${out.dir}/controllers"/>
+
+ <javac destdir="classes"
+ debug="${compiler.debug}"
+ deprecation="${compiler.generate.no.warnings}"
+ encoding="utf8"
+ includeantruntime="false"
+ optimize="${compiler.optimize}">
+
+ <src path="models:controllers"/>
+
+ <classpath refid="instrument_classpath"/>
+ <classpath>
+ <fileset dir="${lib.dir}">
+ <include name="**/*.jar"/>
+ </fileset>
+ <fileset dir="lib">
+ <include name="**/*.jar"/>
+ </fileset>
+ <fileset dir="${micro.dir}/lib/">
+ <include name="**/*.jar"/>
+ </fileset>
+ <fileset dir="${micro.dir}/dist">
+ <include name="**/*.jar"/>
+ </fileset>
+ </classpath>
+
+ </javac>
+
+ </target>
+
+ <target name="instrument" depends="compile">
+ <java classname="org.javalite.instrumentation.Main">
+ <sysproperty key="outputDirectory" value="${out.dir}"/>
+ <classpath refid="instrument_classpath"/>
+ </java>
+
+ <!-- optional:
+ <jar jarfile="lib/models.jar" basedir="${out.dir}">
+ <manifest>
+ <attribute name="Built-Date" value="${TODAY}"/>
+ </manifest>
+ </jar>
+ -->
+ </target>
+
+</project>
View
3 micro-aj/WEB-INF/classes/activejdbc_models.properties
@@ -0,0 +1,3 @@
+models.Booking:default
+models.Customer:default
+models.Hotel:default
View
BIN micro-aj/WEB-INF/classes/controllers/BookingController.class
Binary file not shown.
View
BIN micro-aj/WEB-INF/classes/controllers/CancelReservation.class
Binary file not shown.
View
BIN micro-aj/WEB-INF/classes/controllers/FindHotels.class
Binary file not shown.
View
BIN micro-aj/WEB-INF/classes/controllers/HotelInfo.class
Binary file not shown.
View
BIN micro-aj/WEB-INF/classes/controllers/Login.class
Binary file not shown.
View
BIN micro-aj/WEB-INF/classes/controllers/Register.class
Binary file not shown.
View
BIN micro-aj/WEB-INF/classes/controllers/filters/After.class
Binary file not shown.
View
BIN micro-aj/WEB-INF/classes/controllers/filters/Before.class
Binary file not shown.
View
31 micro-aj/WEB-INF/classes/ehcache.xml
@@ -0,0 +1,31 @@
+<ehcache>
+ <diskStore path="java.io.tmpdir"/>
+
+ <defaultCache
+ maxElementsInMemory="500"
+ eternal="false"
+ overflowToDisk="false"
+ timeToIdleSeconds="10"
+ timeToLiveSeconds="20"
+ />
+
+ <cache name="memCache"
+ maxElementsInMemory="100"
+ eternal="false"
+ timeToIdleSeconds="320"
+ timeToLiveSeconds="420"
+ overflowToDisk="false"
+ diskPersistent="false"
+ diskExpiryThreadIntervalSeconds="60"
+ />
+
+ <cache name="views"
+ maxElementsInMemory="200"
+ eternal="false"
+ timeToIdleSeconds="320"
+ timeToLiveSeconds="420"
+ overflowToDisk="false"
+ diskPersistent="false"
+ diskExpiryThreadIntervalSeconds="60"
+ />
+</ehcache>
View
12 micro-aj/WEB-INF/classes/log4j.properties
@@ -0,0 +1,12 @@
+log4j.appender.stdout=org.apache.log4j.ConsoleAppender
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.stdout.layout.conversionPattern=[%t] %p [%c] %m%n
+
+log4j.rootLogger=ERROR,stdout
+
+log4j.logger.wicketjpa=INFO
+
+# log4j.logger.org.hibernate.SQL=DEBUG
+
+
+
View
BIN micro-aj/WEB-INF/classes/models/Booking.class
Binary file not shown.
View
BIN micro-aj/WEB-INF/classes/models/Customer.class
Binary file not shown.
View
BIN micro-aj/WEB-INF/classes/models/Hotel.class
Binary file not shown.
View
10 micro-aj/WEB-INF/config/application.bsh
@@ -0,0 +1,10 @@
+import ca.simplegames.micro.Globals;
+/**
+ * This controller is executed after the Micro framework is loaded
+ */
+
+site.ExtensionsManager
+ .require("i18N")
+ .require("activejdbc_m");
+
+// log.info("Micro is running ...");
View
21 micro-aj/WEB-INF/config/db.yml
@@ -0,0 +1,21 @@
+production:
+ driver: com.mysql.jdbc.Driver
+ url: jdbc:mysql://flop.ca:3306/booking_development
+ user: sa
+ password:
+ pool: 15
+
+development:
+ driver: org.h2.Driver
+ url: jdbc:h2:WEB-INF/booking_development
+ user: sa
+ password:
+ pool: 5
+
+test:
+ driver: org.h2.Driver
+ url: jdbc:h2:WEB-INF/articles_test
+ user: sa
+ password:
+ pool: 1
+
View
7 micro-aj/WEB-INF/config/extensions/activejdbc_m.yml
@@ -0,0 +1,7 @@
+class: ca.simplegames.micro.extensions.ActivejdbcExtension
+options:
+ models: models
+ debug: true
+ db: db.yml
+
+
View
207 micro-aj/WEB-INF/config/extensions/activejdbc_m/lib/LICENSE
@@ -0,0 +1,207 @@
+Apache License
+Version 2.0, January 2004
+http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction, and
+ distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by the
+ copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all other
+ entities that control, are controlled by, or are under common control with
+ that entity. For the purposes of this definition, "control" means (i) the
+ power, direct or indirect, to cause the direction or management of such
+ entity, whether by contract or otherwise, or (ii) ownership of
+ fifty percent (50%) or more of the outstanding shares, or (iii) beneficial
+ ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity exercising
+ permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation source,
+ and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical transformation
+ or translation of a Source form, including but not limited to compiled
+ object code, generated documentation, and conversions to
+ other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or Object
+ form, made available under the License, as indicated by a copyright notice
+ that is included in or attached to the work (an example is provided in the
+ Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object form,
+ that is based on (or derived from) the Work and for which the editorial
+ revisions, annotations, elaborations, or other modifications represent,
+ as a whole, an original work of authorship. For the purposes of this
+ License, Derivative Works shall not include works that remain separable
+ from, or merely link (or bind by name) to the interfaces of, the Work and
+ Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including the original
+ version of the Work and any modifications or additions to that Work or
+ Derivative Works thereof, that is intentionally submitted to Licensor for
+ inclusion in the Work by the copyright owner or by an individual or
+ Legal Entity authorized to submit on behalf of the copyright owner.
+ For the purposes of this definition, "submitted" means any form of
+ electronic, verbal, or written communication sent to the Licensor or its
+ representatives, including but not limited to communication on electronic
+ mailing lists, source code control systems, and issue tracking systems
+ that are managed by, or on behalf of, the Licensor for the purpose of
+ discussing and improving the Work, but excluding communication that is
+ conspicuously marked or otherwise designated in writing by the copyright
+ owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity on
+ behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+2. Grant of Copyright License.
+
+ Subject to the terms and conditions of this License, each Contributor
+ hereby grants to You a perpetual, worldwide, non-exclusive, no-charge,
+ royalty-free, irrevocable copyright license to reproduce, prepare
+ Derivative Works of, publicly display, publicly perform, sublicense,
+ and distribute the Work and such Derivative Works in
+ Source or Object form.
+
+3. Grant of Patent License.
+
+ Subject to the terms and conditions of this License, each Contributor
+ hereby grants to You a perpetual, worldwide, non-exclusive, no-charge,
+ royalty-free, irrevocable (except as stated in this section) patent
+ license to make, have made, use, offer to sell, sell, import, and
+ otherwise transfer the Work, where such license applies only to those
+ patent claims licensable by such Contributor that are necessarily
+ infringed by their Contribution(s) alone or by combination of their
+ Contribution(s) with the Work to which such Contribution(s) was submitted.
+ If You institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work or a
+ Contribution incorporated within the Work constitutes direct or
+ contributory patent infringement, then any patent licenses granted to
+ You under this License for that Work shall terminate as of the date such
+ litigation is filed.
+
+4. Redistribution.
+
+ You may reproduce and distribute copies of the Work or Derivative Works
+ thereof in any medium, with or without modifications, and in Source or
+ Object form, provided that You meet the following conditions:
+
+ 1. You must give any other recipients of the Work or Derivative Works a
+ copy of this License; and
+
+ 2. You must cause any modified files to carry prominent notices stating
+ that You changed the files; and
+
+ 3. You must retain, in the Source form of any Derivative Works that You
+ distribute, all copyright, patent, trademark, and attribution notices from
+ the Source form of the Work, excluding those notices that do not pertain
+ to any part of the Derivative Works; and
+
+ 4. If the Work includes a "NOTICE" text file as part of its distribution,
+ then any Derivative Works that You distribute must include a readable copy
+ of the attribution notices contained within such NOTICE file, excluding
+ those notices that do not pertain to any part of the Derivative Works,
+ in at least one of the following places: within a NOTICE text file
+ distributed as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or, within a
+ display generated by the Derivative Works, if and wherever such
+ third-party notices normally appear. The contents of the NOTICE file are
+ for informational purposes only and do not modify the License.
+ You may add Your own attribution notices within Derivative Works that You
+ distribute, alongside or as an addendum to the NOTICE text from the Work,
+ provided that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and may
+ provide additional or different license terms and conditions for use,
+ reproduction, or distribution of Your modifications, or for any such
+ Derivative Works as a whole, provided Your use, reproduction, and
+ distribution of the Work otherwise complies with the conditions
+ stated in this License.
+
+5. Submission of Contributions.
+
+ Unless You explicitly state otherwise, any Contribution intentionally
+ submitted for inclusion in the Work by You to the Licensor shall be under
+ the terms and conditions of this License, without any additional
+ terms or conditions. Notwithstanding the above, nothing herein shall
+ supersede or modify the terms of any separate license agreement you may
+ have executed with Licensor regarding such Contributions.
+
+6. Trademarks.
+
+ This License does not grant permission to use the trade names, trademarks,
+ service marks, or product names of the Licensor, except as required for
+ reasonable and customary use in describing the origin of the Work and
+ reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty.
+
+ Unless required by applicable law or agreed to in writing, Licensor
+ provides the Work (and each Contributor provides its Contributions)
+ on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ either express or implied, including, without limitation, any warranties
+ or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS
+ FOR A PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any risks
+ associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability.
+
+ In no event and under no legal theory, whether in tort
+ (including negligence), contract, or otherwise, unless required by
+ applicable law (such as deliberate and grossly negligent acts) or agreed
+ to in writing, shall any Contributor be liable to You for damages,
+ including any direct, indirect, special, incidental, or consequential
+ damages of any character arising as a result of this License or out of
+ the use or inability to use the Work (including but not limited to damages
+ for loss of goodwill, work stoppage, computer failure or malfunction,
+ or any and all other commercial damages or losses), even if such
+ Contributor has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability.
+
+ While redistributing the Work or Derivative Works thereof, You may choose
+ to offer, and charge a fee for, acceptance of support, warranty,
+ indemnity, or other liability obligations and/or rights consistent with
+ this License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf of any
+ other Contributor, and only if You agree to indemnify, defend, and hold
+ each Contributor harmless for any liability incurred by, or claims
+ asserted against, such Contributor by reason of your accepting any such
+ warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work
+
+ To apply the Apache License to your work, attach the following boilerplate
+ notice, with the fields enclosed by brackets "[]" replaced with your own
+ identifying information. (Don't include the brackets!) The text should be
+ enclosed in the appropriate comment syntax for the file format. We also
+ recommend that a file or class name and description of purpose be included
+ on the same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright 2013 Florin T.PATRASCU
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ or implied. See the License for the specific language governing
+ permissions and limitations under the License.
View
BIN micro-aj/WEB-INF/config/extensions/activejdbc_m/lib/activejdbc-1.4.7-SNAPSHOT.jar
Binary file not shown.
View
BIN .../WEB-INF/config/extensions/activejdbc_m/lib/activejdbc-instrumentation-1.4.7-SNAPSHOT.jar
Binary file not shown.
View
BIN micro-aj/WEB-INF/config/extensions/activejdbc_m/lib/activejdbc_m-0.1.1.jar
Binary file not shown.
View
BIN micro-aj/WEB-INF/config/extensions/activejdbc_m/lib/bonecp-0.7.1.RELEASE.jar
Binary file not shown.
View
BIN micro-aj/WEB-INF/config/extensions/activejdbc_m/lib/guava-11.0.2.jar
Binary file not shown.
View
BIN micro-aj/WEB-INF/config/extensions/activejdbc_m/lib/h2-1.3.170.jar
Binary file not shown.
View
BIN micro-aj/WEB-INF/config/extensions/activejdbc_m/lib/javalite-common-1.4.7-SNAPSHOT.jar
Binary file not shown.
View
BIN micro-aj/WEB-INF/config/extensions/activejdbc_m/lib/javassist-3.17.1-GA.jar
Binary file not shown.
View
7 micro-aj/WEB-INF/config/extensions/i18N.yml
@@ -0,0 +1,7 @@
+#alias: L10n
+class: ca.simplegames.micro.extensions.i18n.I18NExtension
+intercept: {parameter_name: language, scope: "session, request, context"}
+default_encoding: utf-8
+fallback_to_system_locale: true
+resource_cache: 10
+base_names: [config/locales/messages]
View
1 micro-aj/WEB-INF/config/locales/messages_en.properties
@@ -0,0 +1 @@
+copyright=Copyright © 2012-2013 Florin T.PATRASCU
View
1 micro-aj/WEB-INF/config/locales/messages_fr.properties
@@ -0,0 +1 @@
+hello_world=Bonjour tout le monde!
View
32 micro-aj/WEB-INF/config/micro-config.yml
@@ -0,0 +1,32 @@
+name: micro_app
+description: describe your web application
+
+repositories:
+ content: {path: views/content, cache: views, default: true}
+ partials: {path: views/partials, cache: views}
+ templates: {path: views/templates, cache: views}
+
+controllers: {path: controllers, cache: memCache}
+
+cache:
+ names: [memCache, views]
+ class: ca.simplegames.micro.cache.DefaultCache
+
+template_engines:
+ - engine:
+ name: velocity
+ class: ca.simplegames.micro.viewers.velocity.VelocityViewRenderer
+ options:
+ resource_cache_enabled: true
+ resource_cache_interval: 15
+ global_macro_library: global_library.vm
+ default: true
+
+ - engine:
+ name: markdown
+ class: ca.simplegames.micro.viewers.markup.MarkupViewRenderer
+
+# possible values: production, test or development:
+# MICRO_ENV: production
+mime_types:
+ .md: text/html; charset=utf8
View
16 micro-aj/WEB-INF/config/routes.yml
@@ -0,0 +1,16 @@
+# validate the YAMl structure with: http://yaml-online-parser.appspot.com/
+- route: "/{image_file}.{type: png|jpg|jpeg|txt}"
+ method: get, head
+ controller:
+ name: ca.simplegames.micro.controllers.BinaryContent
+ options: {
+ mime_types: { .txt: "text/plain;charset=UTF-8" }
+ }
+
+- route: /system/info
+ controller:
+ name: ca.simplegames.micro.controllers.StatsController
+
+- route: /logout
+ controller:
+ name: Logout.bsh
View
95 micro-aj/WEB-INF/controllers/BookingController.java
@@ -0,0 +1,95 @@
+package controllers;
+
+import ca.simplegames.micro.Controller;
+import ca.simplegames.micro.Globals;
+import ca.simplegames.micro.MicroContext;
+import ca.simplegames.micro.controllers.ControllerException;
+import ca.simplegames.micro.utils.StringUtils;
+import models.Booking;
+import models.Customer;
+import models.Hotel;
+import org.joda.time.DateTime;
+import org.joda.time.Duration;
+import org.joda.time.format.DateTimeFormat;
+import org.joda.time.format.DateTimeFormatter;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+import java.io.FileNotFoundException;
+import java.math.BigDecimal;
+import java.util.Map;
+
+/**
+ * collect the data from the booking order, validate some fields and save everything
+ * in the session.
+ */
+
+public class BookingController implements Controller {
+ public static final String YYYY_MM_DD = "yyyy-MM-dd";
+ static DateTimeFormatter fmt = DateTimeFormat.forPattern(YYYY_MM_DD);
+
+ public void execute(MicroContext context, Map map) throws ControllerException, FileNotFoundException {
+ DateTime today = DateTime.now();
+ HttpServletRequest request = context.getRequest();
+
+ Hotel hotel = (Hotel) context.get("hotel");
+ final HttpSession session = request.getSession();
+ Map user = (Map) session.getAttribute("user");
+
+ if (user != null) {
+ Customer customer = Customer.findById(user.get("id"));
+
+ if (hotel != null) {
+
+ Booking booking = Booking.create(
+ "customer_id", customer.getId(),
+ "hotel_id", hotel.getId(),
+ "checkin_date", fmt.parseDateTime(request.getParameter("checkinDate")).toDate(),
+ "checkout_date", fmt.parseDateTime(request.getParameter("checkoutDate")).toDate(),
+ "beds", Integer.parseInt(StringUtils.defaultString(request.getParameter("beds"), "1")),
+ "smoking", request.getParameter("smoking") != null && request.getParameter("smoking").equalsIgnoreCase("true"),
+ "credit_card", request.getParameter("creditCard"),
+ "credit_card_name", request.getParameter("creditCardName"),
+ "credit_card_expiry_month", Integer.parseInt(StringUtils.defaultString(request.getParameter("creditCardExpiryMonth"), "0")),
+ "credit_card_expiry_year", Integer.parseInt(StringUtils.defaultString(request.getParameter("creditCardExpiryYear"), "0"))
+ );
+
+ try {
+ booking.validate();
+ if (StringUtils.defaultString(request.getParameter("eh"),
+ Globals.EMPTY_STRING).equalsIgnoreCase("Ido")) {
+ booking.saveIt();
+ }
+ } catch (Exception e) {
+ context.put("errors", booking.errors());
+ e.printStackTrace();
+ //context.setRedirect(String.format("%s/book.html?id=%s", request.getContextPath(), hotel.getId()), false);
+ }
+
+ Map bookingOrder = booking.toMap();
+ bookingOrder.put("hotel", hotel.toMap());
+ session.setAttribute("bookingOrder", bookingOrder);
+
+ if (booking.getId() != null) {
+ context.setRedirect(String.format("%s/thanks.html", request.getContextPath()), false);
+ } else {
+ context.put("booking", booking);
+ DateTime cIn = new DateTime(booking.get("checkin_date"));
+ DateTime cOut = new DateTime(booking.get("checkout_date"));
+ Duration stayDuration = new Duration(cIn, cOut);
+
+ context.put("checkinDate", cIn.toString(YYYY_MM_DD));
+ context.put("checkoutDate", cOut.toString(YYYY_MM_DD));
+ final long days = stayDuration.getStandardDays();
+ context.put("total", ((BigDecimal) hotel.get("price")).doubleValue() * days);
+ context.put("days", days);
+ context.put("orderDate", today);
+ }
+ } else {
+ context.with("error", "Please select a hotel first!");
+ }
+ } else {
+ context.with("error", "Please login first!");
+ }
+ }
+}
View
52 micro-aj/WEB-INF/controllers/CancelReservation.java
@@ -0,0 +1,52 @@
+package controllers;
+
+import ca.simplegames.micro.Controller;
+import ca.simplegames.micro.MicroContext;
+import ca.simplegames.micro.controllers.ControllerException;
+import ca.simplegames.micro.extensions.ActivejdbcExtension;
+import models.Booking;
+import models.Customer;
+import org.apache.commons.lang.StringUtils;
+
+import java.io.FileNotFoundException;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * cancel a reservation
+ *
+ * @author <a href="mailto:florin.patrascu@gmail.com">Florin T.PATRASCU</a>
+ * @since $Revision$ (created: 2013-02-28 7:27 PM)
+ */
+public class CancelReservation implements Controller {
+ public void execute(MicroContext context, Map configuration) throws ControllerException, FileNotFoundException {
+ Map user = (Map) context.getRequest().getSession().getAttribute("user");
+ ActivejdbcExtension aj = (ActivejdbcExtension) context.getSiteContext().get("activejdbc_m");
+
+ Integer reservationId = Integer.parseInt(
+ StringUtils.defaultIfEmpty(
+ context.getRequest().getParameter("id"), "-1"));
+
+ if (reservationId > 0) {
+ aj.before();
+
+ try {
+ if (user != null) {
+ Customer customer = Customer.findById(user.get("id"));
+ if (customer != null) {
+ List<Booking> reservations = customer.get(Booking.class, "id=?", reservationId);
+ for (Booking reservation : reservations) {
+ reservation.delete();
+ }
+ context.with("success", Boolean.TRUE);
+ }
+ }
+ } catch (Exception e) {
+ throw new ControllerException(e.getMessage(), e);
+ } finally {
+ aj.after();
+ }
+ }
+
+ }
+}
View
46 micro-aj/WEB-INF/controllers/FindHotels.java
@@ -0,0 +1,46 @@
+package controllers;
+
+import ca.simplegames.micro.Controller;
+import ca.simplegames.micro.MicroContext;
+import ca.simplegames.micro.controllers.ControllerException;
+import models.Hotel;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.javalite.activejdbc.Paginator;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:florin.patrascu@gmail.com">Florin T.PATRASCU</a>
+ * @since $Revision$ (created: 2013-01-12)
+ */
+public class FindHotels implements Controller {
+ protected static final Log log = LogFactory.getLog(FindHotels.class);
+
+ public void execute(MicroContext context, Map configuration) throws ControllerException {
+ HttpServletRequest request = context.getRequest();
+ String searchString = StringUtils.defaultString(request.getParameter("search_string"));
+
+ if (!searchString.isEmpty()) {
+ int currentPage = Integer.parseInt(StringUtils.defaultIfEmpty(
+ request.getParameter("page"), "1"));
+ // hotels = Hotel.findAll().limit(5);
+ String pattern = '%' + searchString.toLowerCase().replace('*', '%') + '%';
+
+ log.info("Searching for pattern: `" + pattern + "`");
+ Paginator paginator = new Paginator(Hotel.class, 5, "lower(name) like ? or lower(city) like ?"
+ + " or lower(zip) like ? or lower(address) like ?",
+ pattern, pattern, pattern, pattern);
+
+ context.put("hotels", paginator.getPage(currentPage));
+ context.put("searchString", searchString);
+
+ context.put("totalPages", paginator.pageCount());
+ context.put("currentPage", currentPage);
+ context.put("searchString", searchString);
+ }
+ }
+}
+
View
48 micro-aj/WEB-INF/controllers/HotelInfo.java
@@ -0,0 +1,48 @@
+package controllers;
+
+import ca.simplegames.micro.Controller;
+import ca.simplegames.micro.MicroContext;
+import ca.simplegames.micro.controllers.ControllerException;
+import models.Booking;
+import models.Customer;
+import models.Hotel;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.joda.time.DateTime;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * find the hotel based on the request parameter: 'id'
+ *
+ * @author <a href="mailto:florin.patrascu@gmail.com">Florin T.PATRASCU</a>
+ * @since $Revision$ (created: 2013.02.24)
+ */
+
+public class HotelInfo implements Controller {
+ protected static final Log log = LogFactory.getLog(HotelInfo.class);
+
+ public void execute(MicroContext context, Map configuration) throws ControllerException {
+ String id = StringUtils.defaultString(context.getRequest().getParameter("id"));
+
+ if (!id.isEmpty()) {
+ Hotel hotel = Hotel.findById(id);
+ context.put("hotel", hotel);
+
+ Map user = (Map) context.getRequest().getSession().getAttribute("user");
+ if (user != null) {
+ Customer customer = Customer.findById(user.get("id"));
+ if (customer != null) {
+ List<Booking> reservations = customer.get(Booking.class, "hotel_id=?", hotel.getId());
+ context.put("reservations", reservations);
+ }
+ }
+ }
+
+ context.with("yyyyMMdd", DateTime.now().toString("yyyy-MM-dd"));
+ context.with("month", DateTime.now().getMonthOfYear());
+ context.with("year", DateTime.now().getYear());
+ }
+}
View
53 micro-aj/WEB-INF/controllers/Login.java
@@ -0,0 +1,53 @@
+package controllers;
+
+import ca.simplegames.micro.Controller;
+import ca.simplegames.micro.MicroContext;
+import ca.simplegames.micro.controllers.ControllerException;
+import models.Customer;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * simple login support, the username and the password must match to an existing db record
+ *
+ * @author <a href="mailto:florin.patrascu@gmail.com">Florin T.PATRASCU</a>
+ * @since $Revision$ (created: 2013.02.24)
+ */
+
+public class Login implements Controller {
+ protected static final Log log = LogFactory.getLog(Login.class);
+
+ public void execute(MicroContext context, Map configuration) throws ControllerException {
+
+ HttpServletRequest request = context.getRequest();
+ String username = StringUtils.defaultString(request.getParameter("username"));
+ String password = StringUtils.defaultString(request.getParameter("password"));
+
+ if (StringUtils.isNotBlank(username) && StringUtils.isNotBlank(password)) {
+ try {
+ List customers = Customer.where("lower(username) = ? and lower(password) = ? ",
+ username, password).limit(1);
+ if (customers.size() > 0) {
+ request.getSession().setAttribute("user", ((Customer) customers.get(0)).toMap());
+ final String hotelId = request.getParameter("id");
+
+ if (hotelId != null) {
+ context.setRedirect(String.format("%s/hotel.html?id=%s",
+ request.getContextPath(), hotelId), false);
+ } else {
+ context.setRedirect(String.format("%s/", request.getContextPath()), false);
+ }
+ } else {
+ context.with("error", "Invalid credentials, sorry.");
+ }
+ } catch (Exception e) {
+ log.error(e.getMessage());
+ }
+ }
+ }
+}
View
9 micro-aj/WEB-INF/controllers/Logout.bsh
@@ -0,0 +1,9 @@
+/**
+ * delete the user object from the current session and redirect to
+ * the main page; a basic Logout.
+ *
+ * - florin, 2013.02.19
+ */
+request = context.getRequest();
+request.Session.setAttribute("user", null);
+context.setRedirect(request.ContextPath+"/", false);
View
62 micro-aj/WEB-INF/controllers/Register.java
@@ -0,0 +1,62 @@
+package controllers;
+
+import ca.simplegames.micro.Controller;
+import ca.simplegames.micro.MicroContext;
+import ca.simplegames.micro.RedirectException;
+import ca.simplegames.micro.controllers.ControllerException;
+import models.Customer;
+import org.apache.commons.lang.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.servlet.http.HttpServletRequest;
+import java.io.FileNotFoundException;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:florin.patrascu@gmail.com">Florin T.PATRASCU</a>
+ * @since $Revision$ (created: 2013-02-24 2:15 PM)
+ */
+public class Register implements Controller {
+ protected static final Logger log = LoggerFactory.getLogger(Register.class);
+
+ @SuppressWarnings("unchecked")
+ public void execute(MicroContext context, Map config) throws ControllerException, FileNotFoundException {
+ HttpServletRequest request = context.getRequest();
+
+ try {
+ String registration = StringUtils.defaultString(request.getParameter("registration"));
+
+ if (StringUtils.isNotEmpty(registration)) {
+ String username = StringUtils.defaultString(request.getParameter("username"));
+ String name = StringUtils.defaultString(request.getParameter("name"));
+ String password = StringUtils.defaultString(request.getParameter("password"));
+ String verify = StringUtils.defaultString(request.getParameter("verify"));
+
+ List users = Customer.where("username = ?", username);
+ if (users != null && users.isEmpty()) {
+ if (password.equals(verify)) {
+
+ Customer user = Customer.createIt("username", username, "name", name, "password", password);
+ if (user != null) {
+ Map richUser = user.toMap();
+ richUser.put("welcome", Boolean.TRUE);
+ request.getSession().setAttribute("user", richUser);
+ context.setRedirect(request.getContextPath()+"/index.html", false);
+ }
+ } else {
+ context.with("error", "The two passwords don't match");
+ }
+ } else {
+ context.with("error", String.format("Username %s already exists", username));
+ }
+ }
+ } catch (Exception e) {
+ if (!(e instanceof RedirectException)) {
+ e.printStackTrace();
+ context.with("error", String.format("%s", e.getMessage()));
+ }
+ }
+ }
+}
View
27 micro-aj/WEB-INF/controllers/filters/After.java
@@ -0,0 +1,27 @@
+package controllers.filters;
+
+import ca.simplegames.micro.Controller;
+import ca.simplegames.micro.MicroContext;
+import ca.simplegames.micro.SiteContext;
+import ca.simplegames.micro.controllers.ControllerException;
+import ca.simplegames.micro.extensions.ActivejdbcExtension;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.util.Map;
+
+/**
+ * basic AFTER advise that take care about opening an AJ connection
+ *
+ * @author <a href="mailto:florin.patrascu@gmail.com">Florin T.PATRASCU</a>
+ * @since $Revision$ (created: 2013-02-24 12:37 PM)
+ */
+public class After implements Controller {
+ protected static final Log log = LogFactory.getLog(After.class);
+
+ public void execute(MicroContext context, Map configuration) throws ControllerException {
+ SiteContext site = context.getSiteContext();
+ ActivejdbcExtension aj = (ActivejdbcExtension)site.get("activejdbc_m");
+ aj.after();
+ }
+}
View
10 micro-aj/WEB-INF/controllers/filters/AfterThanks.bsh
@@ -0,0 +1,10 @@
+/**
+ * simple aspect used for clearing out the session objects after the booking was finalized
+ *
+ * @author <a href="mailto:florin.patrascu@gmail.com">Florin T.PATRASCU</a>
+ */
+
+session = context.Request.Session;
+if(session.getAttribute("bookingOrder") != null){
+ session.removeAttribute("bookingOrder");
+}
View
27 micro-aj/WEB-INF/controllers/filters/Before.java
@@ -0,0 +1,27 @@
+package controllers.filters;
+
+import ca.simplegames.micro.Controller;
+import ca.simplegames.micro.MicroContext;
+import ca.simplegames.micro.SiteContext;
+import ca.simplegames.micro.controllers.ControllerException;
+import ca.simplegames.micro.extensions.ActivejdbcExtension;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.util.Map;
+
+/**
+ * basic BEFORE advise that take care about closing an AJ connection
+ *
+ * @author <a href="mailto:florin.patrascu@gmail.com">Florin T.PATRASCU</a>
+ * @since $Revision$ (created: 2013-02-24 12:37 PM)
+ */
+public class Before implements Controller {
+ protected static final Log log = LogFactory.getLog(Before.class);
+
+ public void execute(MicroContext context, Map configuration) throws ControllerException {
+ SiteContext site = context.getSiteContext();
+ ActivejdbcExtension aj = (ActivejdbcExtension) site.get("activejdbc_m");
+ aj.before();
+ }
+}
View
1 micro-aj/WEB-INF/lib/README.md
@@ -0,0 +1 @@
+throwing in some libraries for verifying if µ can load from multiple paths.
View
BIN micro-aj/WEB-INF/lib/joda-time-2.1.jar
Binary file not shown.
View
34 micro-aj/WEB-INF/models/Booking.java
@@ -0,0 +1,34 @@
+package models;
+
+import org.javalite.activejdbc.Model;
+import org.joda.time.DateTime;
+
+/**
+ * @author <a href="mailto:florin.patrascu@gmail.com">Florin T.PATRASCU</a>
+ * @since $Revision$ (created: 2013-02-24 1:43 PM)
+ */
+public class Booking extends Model {
+
+ static {
+ validatePresenceOf("credit_card", "credit_card_name");
+ validateRange("credit_card_expiry_month", 0, 13);
+ validateRange("credit_card_expiry_year", DateTime.now().getYear(), DateTime.now().getYear() + 4);
+ }
+
+ @Override
+ protected void beforeValidation() {
+ DateTime checkinDate = new DateTime(this.getDate("checkin_date"));
+ DateTime checkoutDate = new DateTime(this.getDate("checkout_date"));
+ if (checkoutDate.isEqual(checkinDate)) {
+ final String errMsg = "can't checkout the same day";
+ errors.put("checkout_date", errMsg);
+ throw new IllegalArgumentException(errMsg);
+ }
+
+ if (checkoutDate.isBefore(checkinDate)) {
+ final String errMsg = "can't checkout before checking in";
+ errors.put("checkout_date", errMsg);
+ throw new IllegalArgumentException(errMsg);
+ }
+ }
+}
View
17 micro-aj/WEB-INF/models/Customer.java
@@ -0,0 +1,17 @@
+package models;
+
+import org.javalite.activejdbc.Model;
+
+/**
+ * @author <a href="mailto:florin.patrascu@gmail.com">Florin T.PATRASCU</a>
+ * @since $Revision$ (created: 2013.02.17)
+ */
+public class Customer extends Model {
+ static {
+ validatePresenceOf("username", "username");
+ validatePresenceOf("password", "password");
+ validatePresenceOf("name", "name");
+ validateRegexpOf("email", "\\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,4}\\b");
+ validateEmailOf("email");
+ }
+}
View
10 micro-aj/WEB-INF/models/Hotel.java
@@ -0,0 +1,10 @@
+package models;
+
+import org.javalite.activejdbc.Model;
+
+/**
+ * @author <a href="mailto:florin.patrascu@gmail.com">Florin T.PATRASCU</a>
+ * @since $Revision$ (created: 2013.02.17)
+ */
+public class Hotel extends Model {
+}
View
BIN micro-aj/WEB-INF/smith-1.0.jar
Binary file not shown.
View
5 micro-aj/WEB-INF/views/content/about.md
@@ -0,0 +1,5 @@
+### About this application ###
+
+This is a port of the [Wicket-JPA Booking](http://perfbench.googlecode.com/svn/trunk/perfbench/wicket-jpa/) demo web application. This application is done for benchmarking purposes and to demonstrate some of the numerous features exposed by Micro.
+
+Please see the original article: [Seam / JSF vs Wicket: performance comparison](http://ptrthomas.wordpress.com/2009/01/14/seam-jsf-vs-wicket-performance-comparison/)
View
124 micro-aj/WEB-INF/views/content/book.html
@@ -0,0 +1,124 @@
+<h1>Book Hotel</h1>
+
+#set($serror = $request.Session.getAttribute("error"))
+#if($serror)
+ ##${serror}
+#end
+
+#if($user)
+<div class="row">
+ <div class="span3">
+ #set($booking = true)
+ $partials.get("hotel_info.html")
+ </div>
+
+ <div class="span5">
+ <form id="form" class="form form-horizontal" method="POST" action="${request.ContextPath}/confirm.html">
+ <input type="hidden" name="id" value="${hotel.id}">
+ <fieldset>
+ <div class="control-group">
+ <label class="control-label" for="checkinDate">Check In Date:</label>
+
+ <div class="controls">
+ <div class="input-append date" id="checkinDate"
+ data-date="${yyyyMMdd}" data-date-format="yyyy-mm-dd">
+ <input class="span2" name="checkinDate" size="16" type="text" value="${yyyyMMdd}" readonly>
+ <span class="add-on"><i class="icon-th"></i></span>
+ </div>
+ </div>
+ </div>
+
+ <div class="control-group">
+ <label class="control-label" for="checkoutDate">Check Out Date:</label>
+
+ <div class="controls">
+ <div class="input-append date" id="checkoutDate"
+ data-date="${yyyyMMdd}" data-date-format="yyyy-mm-dd">
+ <input class="span2" name="checkoutDate" size="16" type="text" value="${yyyyMMdd}" readonly>
+ <span class="add-on"><i class="icon-th"></i></span>
+ </div>
+ </div>
+ </div>
+
+ <div class="control-group">
+ <label class="control-label" for="beds">Room: </label>
+
+ <div class="controls">
+ <select id="beds" name="beds" class="">
+ #foreach($bedType in ["One king-sized bed", "Two double beds", "Three beds"])
+ <option value="${velocityCount}">$bedType</option>
+ #end
+ </select>
+ </div>
+ </div>
+
+ <div class="control-group">
+ <label class="control-label" for="smokingPrefs">Smoking prefs:</label>
+
+ <div id="smokingPrefsDiv" class="offset2">
+ <label class="radio">
+ <input type="radio" name="smoking" value="2" id="smokingPrefs" checked> Non Smoking
+ </label>
+ <label class="radio">
+ <input type="radio" name="smoking" value="1"> Smoking
+ </label>
+ </div>
+ </div>
+
+ <div class="control-group">
+ <label class="control-label" for="creditCard">Credit Card #:</label>
+ <div class="controls">
+ <input type="text" id="creditCard" name="creditCard" placeholder="credit card number"
+ required="required" pattern="[0-9]{13,19}|([0-9- ]{3,8}){3,6}" data-error="Please enter a credit card number">
+ </div>
+ </div>
+
+ <div class="control-group">
+ <label class="control-label" for="creditCardName">Credit Card Name:</label>
+
+ <div class="controls" style="white-space:nowrap;">
+ <input type="text" id="creditCardName" name="creditCardName" placeholder="name on the card"
+ required="required" pattern="[A-Za-z0-9 ]*" data-error="Please enter a correct name.">
+ </div>
+ </div>
+
+ <div class="control-group">
+ <label class="control-label" for="cce">Credit Card Expiry:</label>
+
+ <div class="controls">
+ <select id="cce" name="creditCardExpiryMonth" class="input-mini">
+ #foreach($month in ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"])
+ <option value="${velocityCount}">$month</option>
+ #end
+ </select>
+ <select name="creditCardExpiryYear" class="input-medium">
+ #set($future=$year+2)
+ #foreach($y in [$year..$future])
+ <option value="${y}">${y}</option>
+ #end
+ </select>
+ </div>
+ </div>
+
+
+ <div class="control-group">
+ <div class="controls">
+ <button type="submit" class="btn btn-primary">Proceed</button>
+ </div>
+ </div>
+ </fieldset>
+ </form>
+ </div>
+</div>
+
+<script type="text/javascript">
+ jQuery(document).ready(function () {
+ jQuery('form').form();
+ jQuery('#checkinDate, #checkoutDate').datepicker();
+ });
+</script>
+
+#else
+Please <a href="${request.ContextPath}/login.html?id=$!{hotel.id}">login</a> first before booking a Hotel.
+#end
+
View
6 micro-aj/WEB-INF/views/content/cancel.html
@@ -0,0 +1,6 @@
+#if($success)
+ <h3>Your reservation was cancelled.</h3>
+ Thank you.
+#else
+ <h3>Sorry, you have no reservations.</h3>
+#end
View
9 micro-aj/WEB-INF/views/content/config/book.yml
@@ -0,0 +1,9 @@
+filters:
+ - before:
+ controller: controllers.filters.Before
+ - after:
+ controller: controllers.filters.After
+
+controllers:
+ - controller:
+ name: controllers.HotelInfo
View
3 micro-aj/WEB-INF/views/content/config/cancel.yml
@@ -0,0 +1,3 @@
+controllers:
+ - controller:
+ name: controllers.CancelReservation
View
11 micro-aj/WEB-INF/views/content/config/confirm.yml
@@ -0,0 +1,11 @@
+filters:
+ - before:
+ controller: controllers.filters.Before
+ - after:
+ controller: controllers.filters.After
+
+controllers:
+ - controller:
+ name: controllers.HotelInfo
+ - controller:
+ name: controllers.BookingController
View
9 micro-aj/WEB-INF/views/content/config/hotel.yml
@@ -0,0 +1,9 @@
+filters:
+ - before:
+ controller: controllers.filters.Before
+ - after:
+ controller: controllers.filters.After
+
+controllers:
+ - controller:
+ name: controllers.HotelInfo
View
9 micro-aj/WEB-INF/views/content/config/index.yml
@@ -0,0 +1,9 @@
+filters:
+ - before:
+ controller: controllers.filters.Before
+ - after:
+ controller: controllers.filters.After
+
+controllers:
+ - controller:
+ name: controllers.FindHotels #beanshell will not work with ActiveJDBC
View
9 micro-aj/WEB-INF/views/content/config/login.yml
@@ -0,0 +1,9 @@
+filters:
+ - before:
+ controller: controllers.filters.Before
+ - after:
+ controller: controllers.filters.After
+
+controllers:
+ - controller:
+ name: controllers.Login
View
10 micro-aj/WEB-INF/views/content/config/register.yml
@@ -0,0 +1,10 @@
+filters:
+ - before:
+ controller: controllers.filters.Before
+ - after:
+ controller: controllers.filters.After
+
+controllers:
+ - controller:
+ name: controllers.Register
+ options: {}
View
3 micro-aj/WEB-INF/views/content/config/thanks.yml
@@ -0,0 +1,3 @@
+filters:
+ - after:
+ controller: filters/AfterThanks.bsh
View
48 micro-aj/WEB-INF/views/content/confirm.html
@@ -0,0 +1,48 @@
+#if($booking)
+
+ #if($errors)
+ <div class="alert alert-block">
+ <button type="button" class="close" data-dismiss="alert">&times;</button>
+ <h4>Warning!</h4>
+ #foreach($error in $errors)
+ ${error}<br>
+ #end
+ </div>
+
+ #end
+<h3>Confirm Hotel Booking</h3>
+<div class="span6">
+ <pre>
+Hotel name: ${hotel.name}
+ address: ${hotel.address}
+ ${hotel.City}, ${hotel.State} ${hotel.zip}
+ ${hotel.country}
+
+ Checkin: ${checkinDate}
+ Checkout: ${checkoutDate} ;${days} day(s)
+Order date: ${orderDate.toString("yyyy-MM-dd")}
+ --------------------
+ Total: ${total} USD
+ </pre>
+ <form method="post" action="#">
+ ## lol
+ <input type="hidden" name="eh" value="Ido">
+ <input type="hidden" name="checkinDate" value="${checkinDate}">
+ <input type="hidden" name="checkoutDate" value="${checkoutDate}">
+ <input type="hidden" name="beds" value="${booking.beds}">
+ <input type="hidden" name="smoking" value="${booking.smoking}">
+ <input type="hidden" name="creditCard" value="${booking.credit_card}">
+ <input type="hidden" name="creditCardName" value="${booking.credit_card_name}">
+ <input type="hidden" name="creditCardExpiryMonth" value="${booking.credit_card_expiry_month}">
+ <input type="hidden" name="creditCardExpiryYear" value="${booking.credit_card_expiry_year}">
+ <input type="hidden" name="id" value="${hotel.id}">
+ #if($errors)
+ <a href="${request.ContextPath}/book.html?id=${hotel.id}"<button class="btn btn-primary">Go back</button></a>
+ #else
+ <button type="submit" class="btn btn-primary">Confirm</button>
+ #end
+ </form>
+</div>
+#else
+ <h3>Sorry, your ordering session expired.</h3>
+#end
View
30 micro-aj/WEB-INF/views/content/hotel.html
@@ -0,0 +1,30 @@
+$partials.get("hotel_info.html")
+#if($reservations && !$reservations.isEmpty())
+ <div class="span3 pull-right">
+ <span class="label label-info">Your reservation</span><br>
+ </div>
+ <table class="table table-striped">
+ <thead>
+ <tr>
+ <th>Check in</th>
+ <th>Check out</th>
+ <th>Bed</th>
+ <th>&nbsp;</th>
+ </tr>
+ </thead>
+ <tbody>
+ #foreach($reservation in $reservations)
+ <tr id="hotels">
+ <td id="in">$reservation.checkout_date</td>
+ <td id="out">$reservation.checkout_date</td>
+ <td id="beds">$reservation.beds [$reservation.smoking]</td>
+ <td>
+ <a id="view" href="${request.ContextPath}/cancel.html?id=${reservation.id}">
+ cancel
+ </a>
+ </td>
+ </tr>
+ #end
+ </tbody>
+ </table>
+#end
View
52 micro-aj/WEB-INF/views/content/index.html
@@ -0,0 +1,52 @@
+#if($hotels)
+ <h3>Hotels available</h3>
+ <table id="hotelsTable" class="table table-striped">
+ <thead>
+ <tr>
+ <th>Name</th>
+ <th>Address</th>
+ <th>City, State</th>
+ <th>Zip</th>
+ <th>&nbsp;</th>
+ </tr>
+ </thead>
+ <tbody>
+ #foreach($hotel in $hotels)
+ <tr id="hotels">
+ <td data-hotel-id="${hotel.id}"><a href="${request.ContextPath}/hotel.html?id=${hotel.id}">$hotel.name</a></td>
+ <td id="address">$hotel.address</td>
+ <td><span id="city">$hotel.city</span>, <span id="state">$hotel.state</span>, <span id="country">$hotel.country</span></td>
+ <td id="zip">$hotel.zip</td>
+ <td>
+ <a id="view" href="${request.ContextPath}/hotel.html?id=${hotel.id}">
+ <span class="label label-info">info</span>
+ </a>
+ </td>
+ </tr>
+ #end
+ </tbody>
+ </table>
+
+ #if($totalPages)
+ <div id="pagination" class="span8">
+ <div class="pagination pagination-centered">
+ <ul>
+ #foreach($p in [1..$totalPages])
+ #set($disabled = "")
+ #if($p == $currentPage)
+ #set($disabled = "disabled")
+ #end
+ <li class="${disabled}">
+ <a href="${request.ContextPath}?search_string=$!{searchString}&page=$!{p}">$!{p}</a>
+ </li>
+ #end
+ </ul>
+ </div>
+ </div>
+ #end
+
+#else
+<h3>
+ Try to search for some hotels.
+</h3>
+#end
View
50 micro-aj/WEB-INF/views/content/login.html
@@ -0,0 +1,50 @@
+<div class="section">
+ <h1>Log in</h1>
+</div>
+
+#if($error)
+ <div class="alert alert-block">
+ <button type="button" class="close" data-dismiss="alert">&times;</button>
+ <h4>Warning!</h4>
+ ${error}
+ </div>
+#end
+
+<div class="well">
+ <form id="form" class="form form-horizontal" method="POST" action="${request.ContextPath}/login.html">
+ #set($hotelId = $request.getParameter("id"))
+ #if($hotelId)
+ <input type="hidden" name="id" value="$!{hotelId}">
+ #end
+ <fieldset>
+ <div class="control-group">
+ <label class="control-label" for="username">Username:</label>
+ <div class="controls">
+ <input type="text" id="username" name="username" placeholder="username"
+ class="input-medium" required="required"
+ pattern="[A-Za-z0-9]*" data-error="Please enter a correct login.">
+ </div>
+ </div>
+
+ <div class="control-group">
+ <label class="control-label" for="password">Password:</label>
+ <div class="controls">
+ <input type="password" name="password" id="password" placeholder="" required="required"
+ pattern="[A-Za-z0-9]*" data-error="Please enter a correct password.">
+ </div>
+ </div>
+
+ <div class="control-group">
+ <div class="controls">
+ <button type="submit" class="btn btn-primary">Log in</button>
+ </div>
+ </div>
+ </fieldset>
+ </form>
+</div>
+
+<script type="text/javascript">
+ jQuery(document).ready(function() {
+ jQuery('form').form();
+ });
+</script>
View
68 micro-aj/WEB-INF/views/content/register.html
@@ -0,0 +1,68 @@
+#if(!$user)
+ <h1>Sign in</h1>
+ #if($error)
+ <div class="alert alert-block">
+ <button type="button" class="close" data-dismiss="alert">&times;</button>
+ <h4>Warning!</h4>
+ ${error}
+ </div>
+ #end
+
+ <div class="well">
+ <form id="form" class="form form-horizontal" method="POST" action="#">
+ <input type="hidden" name="registration" value="true">
+ <fieldset>
+ <div class="control-group">
+ <label class="control-label" for="username">Username:</label>
+ <div class="controls">
+ <input type="text" id="username" name="username" placeholder="username"
+ class="input-medium" required="required"
+ pattern="[A-Za-z0-9]*" data-error="Please enter a correct login.">
+ </div>
+ </div>
+
+ <div class="control-group">
+ <label class="control-label" for="name">Real name:</label>
+ <div class="controls">
+ <input type="text" id="name" name="name" placeholder="name" required="required"
+ pattern="[A-Za-z0-9 ]*" data-error="Please enter a correct name.">
+ </div>
+ </div>
+
+ <div class="control-group">
+ <label class="control-label" for="password">Password:</label>
+ <div class="controls">
+ <input type="password" name="password" id="password" placeholder="" required="required"
+ pattern="[A-Za-z0-9]*" data-error="Please enter a correct password.">
+ </div>
+ </div>
+
+ <div class="control-group">
+ <label class="control-label" for="verify">Verify Password:</label>
+ <div class="controls">
+ <input type="password" id="verify" name="verify" placeholder="" required="required"
+ pattern="[A-Za-z0-9]*" data-error="">
+ </div>
+ </div>
+
+ <div class="control-group">
+ <div class="controls">
+ <button type="submit" class="btn btn-primary">Sign in</button>
+ </div>
+ </div>
+ </fieldset>
+ </form>
+ </div>
+#else
+ <div class="alert alert-block">
+ <button type="button" class="close" data-dismiss="alert">&times;</button>
+ <h4>Warning!</h4>
+ You are logged in already, please <a href="${request.ContextPath}/logout">logout</a> if you want to log in as a different user.
+ </div>
+#end
+
+<script type="text/javascript">
+ jQuery(document).ready(function() {
+ jQuery('form').form();
+ });
+</script>
View
20 micro-aj/WEB-INF/views/content/thanks.html
@@ -0,0 +1,20 @@
+<div class="span7">
+ <h3>Thank you!</h3>
+ #set($bookingOrder = $request.Session.getAttribute("bookingOrder"))
+ #set($bedTypes = ["", "One king-sized bed", "Two double beds", "Three beds"])
+#if($bookingOrder)
+ <div class="well" data-order-id="${bookingOrder.id}">
+ ## ${bookingOrder}
+<pre>
+We received your order. Your reservation:
+
+ Hotel: ${bookingOrder.hotel.name}
+ Checkin: ${bookingOrder.checkin_date}
+Checkout: ${bookingOrder.checkout_date}
+ beds: $bedTypes[${bookingOrder.beds}]
+ smoking:#if(${bookingOrder.smoking}) YES #else NO #end
+</pre>
+ and you can <a href="${request.ContextPath}/hotel.html?id=${bookingOrder.hotel.id}">cancel</a> it any time.
+ </div>
+#end
+</div>
View
19 micro-aj/WEB-INF/views/partials/footer.html
@@ -0,0 +1,19 @@
+<div class="row">
+ <div class="span6">
+ #i18N("copyright")
+ </div>
+ <div class="span2 offset3" style="white-space: nowrap;">
+ <strong>Powered by </strong><span class="label">micro $!{site.MicroVersion}</span>
+ </div>
+</div>
+
+<div class="row">
+ <div class="span6">
+ Follow us on Twitter: <a href="http://twitter.com/micro_mvc"><strong>@micro_mvc</strong></a>
+ ## <h5><span class="label">todo:</span> ...</h5>
+ </div>
+ <div class="span2 offset3">
+ <span class="muted">ENV: $!{site.MicroEnv}</span>
+ </div>
+
+</div>
View
25 micro-aj/WEB-INF/views/partials/header.html
@@ -0,0 +1,25 @@
+#set($user = $request.Session.getAttribute("user"))
+
+<div class="row">
+ <div class="span8">
+ <a class="brand" href="/" title="Micro">
+ <img src="/images/hotels-logo.png" alt="Hotels booking demo app" />
+ </a>
+ </div>
+ <div class="span4 right">
+ <p><br>
+ #if($user)
+ Hello, <strong>${user.name}</strong>!
+ #else
+ Welcome, please <a href="${request.ContextPath}/register.html">Sign in</a> or
+ <a href="${request.ContextPath}/login.html">Log in</a>
+ #end
+ </p>
+ <a href="/">Home</a> |
+ #if($user)
+ <a href="/logout">Logout</a> |
+ #end
+ <a href="/about.md">About</a>
+ </div>
+
+</div>
View
22 micro-aj/WEB-INF/views/partials/hotel_info.html
@@ -0,0 +1,22 @@
+#if($hotel)
+<div id="hotel_info">
+ <address>
+ <h3>$hotel.name</h3>
+ $hotel.address<br>
+ $hotel.city, $hotel.state $hotel.zip<br>
+ $hotel.country<br>
+ <abbr title="Nightly rate">Nightly rate:</abbr> $hotel.price
+ </address>
+
+ #if(!$booking)
+ <form id="form" method="POST" action="${request.ContextPath}/book.html">
+ <fieldset class="buttonBox">
+ <input type="hidden" name="id" value="$hotel.id"/>
+ <input type="submit" class="btn btn-primary" value="Book Hotel"/>
+ </fieldset>
+ </form>
+ #end
+</div>
+#else
+Hotel not found, sorry!
+#end
View
12 micro-aj/WEB-INF/views/partials/sidebar.html
@@ -0,0 +1,12 @@
+## style="white-space: nowrap;"
+<form method="GET" action="${request.ContextPath}/index.html" id="search_hotels">
+ <fieldset>
+ <legend>Find Hotels</legend>
+ <div class="input-append">
+ <input class="span3" id="appendedInputButton" type="text"
+ name="search_string" placeholder="ex: hotel" value="$!{searchString}">
+ <button id="search" class="btn" type="submit">Search</button>
+ </div>
+ <span class="help-block">Search for hotel names, cities, ZIP codes or addresses. <small><span class="muted">No boolean operators .. yet</span></small>
+ </fieldset>
+</form>
View
30 micro-aj/WEB-INF/views/templates/404.html
@@ -0,0 +1,30 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+ "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+ <title>404 - File not found</title>
+ <link rel="stylesheet" href="/styles/main.css" type="text/css" charset="utf-8" media="screen">
+ <link href="/bootstrap/css/bootstrap.min.css" rel="stylesheet">
+
+ <!--[if lt IE 9]>
+ <script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
+ <![endif]-->
+</head>
+<body>
+
+ <div class="container">
+ <div class="row">
+ <div class="span9 offset1">
+ <h1>404</h1>
+ <h3>
+ Error in path: $!{path}
+ </h3>
+ <p class="text-muted">
+ $!{error}
+ </p>
+ </div>
+ </div>
+ </div>
+
+</body>
+</html>
View
31 micro-aj/WEB-INF/views/templates/500.html
@@ -0,0 +1,31 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+ "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+ <title>500 - Internal server error</title>
+ <link rel="stylesheet" href="/styles/main.css" type="text/css" charset="utf-8" media="screen">
+ <link href="/bootstrap/css/bootstrap.min.css" rel="stylesheet">
+
+ <!--[if lt IE 9]>
+ <script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
+ <![endif]-->
+</head>
+<body>
+
+ <div class="container">
+ <div class="row">
+ <div class="span9 offset1">
+ <h1>500</h1>
+ <h3>
+ Error in path: $!{path}
+ </h3>
+ <p class="text-muted">
+ ${error.Message}
+ ##$!{error.printStackTrace()}
+ </p>
+ </div>
+ </div>
+ </div>
+
+</body>
+</html>
View
81 micro-aj/WEB-INF/views/templates/default.html
@@ -0,0 +1,81 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
+ "http://www.w3.org/TR/html4/strict.dtd">
+
+<html lang="en">
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <meta charset="utf-8">
+ <title>Micro: $!{Tools.PathUtilities.extractName("$path")} </title>
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <meta name="author" content="Florin T.PATRASCU">
+ <link href="/bootstrap/css/bootstrap.min.css" rel="stylesheet">
+ <link href="/bootstrap/css/bootstrap-responsive.min.css" rel="stylesheet">
+ <link href="/styles/bootstrap-form.css" rel="stylesheet">
+ <link href="/datepicker/css/datepicker.css" rel="stylesheet">
+
+ <link href='http://fonts.googleapis.com/css?family=Inconsolata' rel='stylesheet' type='text/css'>
+ <link rel="stylesheet" href="/styles/github.css" type="text/css" charset="utf-8" media="screen">
+ <link rel="stylesheet" href="/styles/main.css" type="text/css" charset="utf-8" media="screen">
+
+ <!--[if lt IE 9]>
+ <script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
+ <![endif]-->
+ <script type="text/javascript" src="http://code.jquery.com/jquery-1.9.0.min.js"></script>
+ <script>
+ jQuery.noConflict();
+ </script>
+
+</head>
+
+#set($user = $request.Session.getAttribute("user"))
+
+<body>
+ <div class="navbar navbar-static-top">
+ <div class="navbar-inner">
+ <div class="container">
+ $partials.get("header.html")
+ </div>
+ </div>
+ </div>
+ <div class="container">
+ <div class="row">
+ #if($user && $user.new)
+ <div class="alert alert-block">
+ <button type="button" class="close" data-dismiss="alert">&times;</button>
+ <h1>Welcome</h1>
+ <strong>Hi ${user.name}, welcome to our Hotels Booking online µ app!</strong>
+ </div>
+ #end
+ </div>
+ <div class="row">
+ <div class="span8">
+ $content.get($path)
+ </div>
+ <div class="span4 right">
+ $partials.get("sidebar.html")
+ </div>
+ </div>
+ </div>
+
+ <footer>
+ <div class="container">
+ $partials.get("footer.html")
+ </div>
+ </footer>
+
+ <!-- Le javascript
+ ================================================== -->
+ <!-- Placed at the end of the document so the pages load faster -->
+ <script type="text/javascript" src="http://platform.twitter.com/widgets.js"></script>
+ <script type="text/javascript" src="/bootstrap/js/bootstrap.min.js"></script>
+ <script type="text/javascript" src="/js/bootstrap-form.js"></script>
+ <script type="text/javascript" src="/datepicker/js/bootstrap-datepicker.js"></script>
+
+
+ ## Include Google analytics if the site runs in production mode
+ #if($site.isProduction())
+ ##$!partials.get("google_analytics.html")
+ #end
+
+</body>
+</html>
View
52 micro-aj/WEB-INF/views/templates/default.md
@@ -0,0 +1,52 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
+ "http://www.w3.org/TR/html4/strict.dtd">
+
+<html lang="en">
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <meta charset="utf-8">
+ <title>Micro: $!{Tools.PathUtilities.extractName("$path")} </title>
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <meta name="author" content="Florin T.PATRASCU">
+ <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" >
+
+ <link href="/bootstrap/css/bootstrap.min.css" rel="stylesheet">
+ <link href="/bootstrap/css/bootstrap-responsive.min.css" rel="stylesheet">
+
+ <link href='http://fonts.googleapis.com/css?family=Inconsolata' rel='stylesheet' type='text/css'>
+ <link rel="stylesheet" href="/styles/github.css" type="text/css" charset="utf-8" media="screen">
+ <link rel="stylesheet" href="/styles/main.css" type="text/css" charset="utf-8" media="screen">
+
+ <!--[if lt IE 9]>
+ <script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
+ <![endif]-->
+
+</head>
+
+<body>
+ <div class="navbar navbar-static-top">
+ <div class="navbar-inner">
+ <div class="container">
+ $partials.get("header.html")
+ </div>
+ </div>
+ </div>
+
+ <div class="container">
+ <div class="row">
+ <div id="main" class="span8 github">
+ $content.get("markdown", $path)
+ </div>
+ <div id="sidebar" class="span4">
+ $partials.get("sidebar.html")
+ </div>
+ </div>
+ </div>
+
+ <footer>
+ <div class="container">
+ $partials.get("footer.html")
+ </div>
+ </footer>
+</body>
+</html>