├── README.adoc ├── application.png ├── scripts ├── add-circuit-breaker.fsh ├── all.sh ├── create-cdstore-scaffold.fsh ├── create-cdstore.fsh ├── create_cdstore.sh ├── db_patch.sh ├── deploy_on_openshift.sh ├── enable-fabric8.fsh ├── enable_circuit_breaker.sh ├── front │ ├── generated │ │ ├── WEB-INF │ │ │ └── web.xml │ │ ├── app.html │ │ ├── fonts │ │ │ ├── glyphicons-halflings-regular.eot │ │ │ ├── glyphicons-halflings-regular.svg │ │ │ ├── glyphicons-halflings-regular.ttf │ │ │ ├── glyphicons-halflings-regular.woff │ │ │ └── glyphicons-halflings-regular.woff2 │ │ ├── img │ │ │ └── forge-logo.png │ │ ├── index.html │ │ ├── scripts │ │ │ ├── app.js │ │ │ ├── controllers │ │ │ │ ├── editCatalogController.js │ │ │ │ ├── flashController.js │ │ │ │ ├── newCatalogController.js │ │ │ │ └── searchCatalogController.js │ │ │ ├── directives │ │ │ │ ├── datepicker.js │ │ │ │ ├── datetimepicker.js │ │ │ │ └── timepicker.js │ │ │ ├── filters │ │ │ │ ├── genericSearchFilter.js │ │ │ │ └── startFromFilter.js │ │ │ ├── offcanvas.js │ │ │ ├── services │ │ │ │ ├── CatalogFactory.js │ │ │ │ ├── flash.js │ │ │ │ └── locationParser.js │ │ │ └── vendor │ │ │ │ ├── angular-resource.js │ │ │ │ ├── angular-route.js │ │ │ │ ├── angular.js │ │ │ │ ├── bootstrap.js │ │ │ │ ├── jquery-2.1.1.js │ │ │ │ └── modernizr-2.8.3.min.js │ │ ├── styles │ │ │ ├── bootstrap-theme.css │ │ │ ├── bootstrap.css │ │ │ └── main.css │ │ └── views │ │ │ ├── Catalog │ │ │ ├── detail.html │ │ │ └── search.html │ │ │ └── landing.html │ └── modified │ │ ├── app.html │ │ ├── fonts │ │ ├── glyphicons-halflings-regular.eot │ │ ├── glyphicons-halflings-regular.svg │ │ ├── glyphicons-halflings-regular.ttf │ │ ├── glyphicons-halflings-regular.woff │ │ └── glyphicons-halflings-regular.woff2 │ │ ├── img │ │ └── forge-logo.png │ │ ├── index.html │ │ ├── scripts │ │ ├── app.js │ │ ├── controllers │ │ │ ├── editCatalogController.js │ │ │ ├── flashController.js │ │ │ ├── newCatalogController.js │ │ │ └── searchCatalogController.js │ │ ├── directives │ │ │ ├── datepicker.js │ │ │ ├── datetimepicker.js │ │ │ └── timepicker.js │ │ ├── filters │ │ │ ├── genericSearchFilter.js │ │ │ └── startFromFilter.js │ │ ├── offcanvas.js │ │ ├── services │ │ │ ├── CatalogFactory.js │ │ │ ├── config.js │ │ │ ├── flash.js │ │ │ └── locationParser.js │ │ └── vendor │ │ │ ├── angular-resource.js │ │ │ ├── angular-route.js │ │ │ ├── angular.js │ │ │ ├── bootstrap.js │ │ │ ├── jquery-2.1.1.js │ │ │ └── modernizr-2.8.3.min.js │ │ ├── service.json │ │ ├── styles │ │ ├── bootstrap-theme.css │ │ ├── bootstrap.css │ │ └── main.css │ │ └── views │ │ ├── Catalog │ │ ├── detail.html │ │ └── search.html │ │ └── landing.html ├── load_and_break_service.sh └── service │ ├── CatalogEndpointCB.java │ ├── data-h2.sql │ └── mysql-persistent-template-with-init.json └── solution ├── cdfront ├── mvnw ├── mvnw.cmd ├── pom.xml └── src │ ├── main │ ├── fabric8 │ │ ├── route.yml │ │ └── svc.yml │ ├── java │ │ └── org │ │ │ └── cdfront │ │ │ └── DemoApplication.java │ └── resources │ │ ├── application.properties │ │ └── static │ │ ├── app.html │ │ ├── fonts │ │ ├── glyphicons-halflings-regular.eot │ │ ├── glyphicons-halflings-regular.svg │ │ ├── glyphicons-halflings-regular.ttf │ │ ├── glyphicons-halflings-regular.woff │ │ └── glyphicons-halflings-regular.woff2 │ │ ├── img │ │ └── forge-logo.png │ │ ├── index.html │ │ ├── scripts │ │ ├── app.js │ │ ├── controllers │ │ │ ├── editCatalogController.js │ │ │ ├── flashController.js │ │ │ ├── newCatalogController.js │ │ │ └── searchCatalogController.js │ │ ├── directives │ │ │ ├── datepicker.js │ │ │ ├── datetimepicker.js │ │ │ └── timepicker.js │ │ ├── filters │ │ │ ├── genericSearchFilter.js │ │ │ └── startFromFilter.js │ │ ├── offcanvas.js │ │ ├── services │ │ │ ├── CatalogFactory.js │ │ │ ├── config.js │ │ │ ├── flash.js │ │ │ └── locationParser.js │ │ └── vendor │ │ │ ├── angular-resource.js │ │ │ ├── angular-route.js │ │ │ ├── angular.js │ │ │ ├── bootstrap.js │ │ │ ├── jquery-2.1.1.js │ │ │ └── modernizr-2.8.3.min.js │ │ ├── service.json │ │ ├── styles │ │ ├── bootstrap-theme.css │ │ ├── bootstrap.css │ │ └── main.css │ │ └── views │ │ ├── Catalog │ │ ├── detail.html │ │ └── search.html │ │ └── landing.html │ └── test │ └── java │ └── org │ └── cdfront │ └── DemoApplicationTests.java ├── cdservice ├── mvnw ├── mvnw.cmd ├── pom.xml └── src │ ├── main │ ├── config-local │ │ ├── application.properties │ │ └── data.sql │ ├── config-openshift │ │ ├── bootstrap.properties │ │ └── data.sql │ ├── fabric8 │ │ ├── configmap.yml │ │ └── route.yml │ └── java │ │ └── org │ │ └── cdservice │ │ ├── DemoApplication.java │ │ ├── model │ │ ├── Catalog.java │ │ ├── CatalogRepository.java │ │ └── RepositoryConfiguration.java │ │ └── rest │ │ ├── CatalogEndpoint.java │ │ ├── NewCrossOriginResourceSharingFilter.java │ │ └── RestApplication.java │ └── test │ └── java │ └── org │ └── cdservice │ └── DemoApplicationTests.java └── pom.xml /application.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redhat-microservices/lab_springboot-openshift/ee23e2cf97de151b437237eb9683ac9c26597493/application.png -------------------------------------------------------------------------------- /scripts/add-circuit-breaker.fsh: -------------------------------------------------------------------------------- 1 | # Add dependencies 2 | project-add-dependencies org.springframework.cloud:spring-cloud-starter-hystrix:1.2.7.RELEASE 3 | project-add-dependencies org.springframework.boot:spring-boot-starter-actuator: 4 | 5 | # Add EnableCircuitBreaker annotation on DemoApplication 6 | java-add-annotation --annotation org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker --target-class org.cdservice.DemoApplication 7 | -------------------------------------------------------------------------------- /scripts/all.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # 4 | # Usage. We assume that the project/namespace 'workshop' doesn't yet exist under your user account before to run the script 5 | # 6 | # ./scripts/all.sh (when using locally minishift and default user & password admin/admin, directory name is workshop) 7 | # ./scripts/all.sh -a https://console.35.187.106.198.nip.io:8443 -u admin -p password 8 | # ./scripts/all.sh -a https://console.35.187.106.198.nip.io:8443 -t TOKEN 9 | # ./scripts/all.sh -a https://console.35.187.106.198.nip.io:8443 -t TOKEN -d /tmp/demo 10 | # 11 | 12 | while getopts a::u::p::t::d:: option 13 | do 14 | case "${option}" 15 | in 16 | a) api=${OPTARG};; 17 | u) user=${OPTARG};; 18 | p) password=${OPTARG};; 19 | t) token=${OPTARG};; 20 | d) directory=${OPTARG};; 21 | esac 22 | done 23 | 24 | if [ -z "$api" ];then 25 | api=$(minishift console --url) 26 | fi 27 | 28 | if [ -z "$user" ];then 29 | user="admin" 30 | fi 31 | 32 | if [ -z "$password" ];then 33 | password="admin" 34 | fi 35 | 36 | if [ -z "$directory" ];then 37 | directory="workshop" 38 | fi 39 | 40 | # Set env var with the location of the scripts dir 41 | export SCRIPTS_DIR=$(pwd)/scripts 42 | 43 | echo "############################" 44 | echo "API : $api" 45 | echo "User : $user" 46 | echo "Password : $password" 47 | echo "Token : $token" 48 | echo "Directory : $directory" 49 | echo "############################" 50 | 51 | echo "Log on to OpenShift Machine" 52 | if [ "$token" != "" ]; then 53 | echo "oc login $api --token=$token" 54 | oc login $api --token=$token 55 | else 56 | echo "oc login $api -u $user -p $password" 57 | oc login $api -u $user -p $password 58 | fi 59 | 60 | echo "##########################################################################" 61 | echo "## Create workshop project and add role view to th serviceacount default. " 62 | echo "##########################################################################" 63 | oc new-project workshop 64 | oc policy add-role-to-user view -n $(oc project -q) -z default 65 | 66 | forge -i io.fabric8.forge:devops,2.3.88 67 | forge -i org.jboss.forge.addon:spring-boot,1.0.0.Alpha4 68 | 69 | echo "##########################################################################" 70 | echo "#### Call script to create cdservice & cdfront for local usage " 71 | echo "##########################################################################" 72 | ./scripts/create_cdstore.sh $directory 73 | 74 | echo "##########################################################################" 75 | echo "#### Call script to refactor project and deploy it on Openshift " 76 | echo "##########################################################################" 77 | ./scripts/deploy_on_openshift.sh $directory 78 | 79 | echo "##########################################################################" 80 | echo "#### Wait till we get a response from the service " 81 | echo "##########################################################################" 82 | sleep 2m 83 | 84 | export APP=$(oc get route cdservice -o json | jq '.spec.host' | tr -d \"\") 85 | while [ $(curl --write-out %{http_code} --silent --output /dev/null $APP/rest/catalogs) != 200 ] 86 | do 87 | echo "Wait till we get http response 200 .... from $APP/rest/catalogs" 88 | sleep 30 89 | done 90 | 91 | echo "##########################################################################" 92 | echo "#### Activate Circuit Breaker pattern and bring down MySQL instance " 93 | echo "##########################################################################" 94 | ./scripts/enable_circuit_breaker.sh $directory 95 | -------------------------------------------------------------------------------- /scripts/create-cdstore-scaffold.fsh: -------------------------------------------------------------------------------- 1 | # ------ CD Store Web Front End [:8081/rest] --------------- 2 | project-new --named cdfront --type spring-boot --create-static-content=true --port 8081 3 | 4 | # Come up to parent project 5 | cd .. 6 | 7 | # Create the CD Service project 8 | # ---------------- CD Service [:8080/rest] --------------- 9 | project-new --named cdservice --type spring-boot 10 | 11 | # Setup JPA connection with H2 in memory DB 12 | jpa-setup 13 | 14 | # create Catalog entity and add fields 15 | jpa-new-entity --named Catalog 16 | jpa-new-field --named artist --target-entity org.cdservice.model.Catalog 17 | jpa-new-field --named title --target-entity org.cdservice.model.Catalog 18 | jpa-new-field --named description --length 2000 --target-entity org.cdservice.model.Catalog 19 | jpa-new-field --named price --type java.lang.Float --target-entity org.cdservice.model.Catalog 20 | jpa-new-field --named publication_date --type java.util.Date --temporalType DATE --target-entity org.cdservice.model.Catalog 21 | 22 | # Create REST endpoints 23 | rest-generate-endpoints-from-entities --targets org.cdservice.model.* --generator SPRING_BOOT_JPA_ENTITY 24 | 25 | # Enable CORS 26 | rest-new-cross-origin-resource-sharing-filter 27 | 28 | # Scaffold code 29 | scaffold-setup --provider AngularJS 30 | scaffold-generate --provider AngularJS --generate-rest-resources --targets org.cdservice.model.* 31 | 32 | # Come up to top level so we can create a new project 33 | cd ~~ 34 | cd .. -------------------------------------------------------------------------------- /scripts/create-cdstore.fsh: -------------------------------------------------------------------------------- 1 | # ------ CD Store Web Front End [:8081/rest] --------------- 2 | project-new --named cdfront --type spring-boot --create-static-content=true --port 8081 3 | 4 | # Come up to parent project 5 | cd .. 6 | 7 | # Create the CD Service project 8 | # ---------------- CD Service [:8080/rest] --------------- 9 | project-new --named cdservice --type spring-boot 10 | 11 | # Setup JPA connection with H2 in memory DB 12 | jpa-setup 13 | 14 | # create Catalog entity and add fields 15 | jpa-new-entity --named Catalog 16 | jpa-new-field --named artist 17 | jpa-new-field --named title 18 | jpa-new-field --named description --length 2000 19 | jpa-new-field --named price --type java.lang.Float 20 | jpa-new-field --named publication_date --type java.util.Date --temporalType DATE 21 | 22 | # Create REST endpoints 23 | rest-generate-endpoints-from-entities --targets org.cdservice.model.* --generator SPRING_BOOT_JPA_ENTITY 24 | 25 | # Enable CORS 26 | rest-new-cross-origin-resource-sharing-filter 27 | 28 | cd ~~ 29 | cd .. 30 | -------------------------------------------------------------------------------- /scripts/create_cdstore.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # 4 | # Usage: ./scripts/create_cdstore.sh 5 | # E.g. 6 | # To scaffold, simply add the true boolean 7 | # ./scripts/create_cdstore.sh demo true 8 | # 9 | # By default, nos scaffolding will take place 10 | # ./scripts/create_cdstore.sh demo 11 | # 12 | # You can also use another JBoss Forge path 13 | # FORGE_HOME=$HOME/.forge ./scripts/create_cdstore.sh demo 14 | # 15 | 16 | PROJECT_DIR=${1:-demo} 17 | SCAFFOLD=${2:-false} 18 | export CURRENT=$(pwd) 19 | 20 | # If no env var has been set for the scripts dir 21 | if [ -z "$SCRIPTS_DIR" ]; then 22 | SCRIPTS_DIR=$(pwd)/scripts 23 | fi 24 | 25 | if [ -d $PROJECT_DIR ]; then 26 | echo "## Deleting $PROJECT_DIR directory ...." 27 | rm -rf $PROJECT_DIR 28 | fi 29 | 30 | echo "##############################################" 31 | echo "## Create Maven Parent POM under $PROJECT_DIR" 32 | echo "##############################################" 33 | mvn archetype:generate -DarchetypeGroupId=org.codehaus.mojo.archetypes -DarchetypeArtifactId=pom-root -DarchetypeVersion=RELEASE -DinteractiveMode=false -DgroupId=org.cdstore -DartifactId=project -Dversion=1.0.0-SNAPSHOT 34 | mv project $PROJECT_DIR && cd $PROJECT_DIR 35 | 36 | pushd $PROJECT_DIR 37 | 38 | if [ $SCAFFOLD = true ]; then 39 | echo "##############################################" 40 | echo "## Run Forge commands to create the project & Scaffold" 41 | echo "##############################################" 42 | forge -e "run $SCRIPTS_DIR/create-cdstore-scaffold.fsh" 43 | else 44 | echo "##############################################" 45 | echo "## Run Forge commands to create the project " 46 | echo "##############################################" 47 | forge -e "run $SCRIPTS_DIR/create-cdstore.fsh" 48 | fi 49 | 50 | popd 51 | 52 | echo "##############################################" 53 | echo "## Copy static content & SQL data for h2 " 54 | echo "##############################################" 55 | cp -r $SCRIPTS_DIR/service/data-h2.sql cdservice/src/main/resources/data.sql 56 | 57 | if [ $SCAFFOLD = true ]; then 58 | mv cdservice/src/main/webapp/* cdfront/src/main/resources/static/ 59 | else 60 | cp -r $SCRIPTS_DIR/front/modified/ cdfront/src/main/resources/static/ 61 | fi 62 | 63 | pushd $PROJECT_DIR 64 | 65 | echo "####################################################" 66 | echo "## Compile project to check if everything works !!!" 67 | echo "####################################################" 68 | mvn clean install 69 | 70 | echo "####################################################" 71 | echo "## Enable F-m-p #" 72 | echo "####################################################" 73 | forge -e "run $SCRIPTS_DIR/enable-fabric8.fsh" 74 | 75 | popd 76 | 77 | cd $CURRENT 78 | 79 | -------------------------------------------------------------------------------- /scripts/db_patch.sh: -------------------------------------------------------------------------------- 1 | oc patch dc mysql -p '{"spec":{"strategy":{"rollingParams":{"post":{"failurePolicy": "ignore","execNewPod":{"containerName":"mysql","command":["/bin/sh","-c","hostname&&sleep 10&&echo $QUERY | /opt/rh/rh-mysql57/root/usr/bin/mysql -h $MYSQL_SERVICE_HOST -u $MYSQL_USER -D $MYSQL_DATABASE -p$MYSQL_PASSWORD -P3306"], "env": [{"name": "QUERY", "value":"$MYQUERY"}]}}}}}}' -------------------------------------------------------------------------------- /scripts/deploy_on_openshift.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # 4 | # Prerequisite : Install jq --> https://stedolan.github.io/jq/download/ 5 | # brew install jq 6 | # ./scripts/deploy_openshift.sh 7 | # PATH of the PROJECT directory 8 | # 9 | 10 | PROJECT_DIR=${1:-workshop} 11 | export CURRENT=$(pwd) 12 | 13 | cd $PROJECT_DIR 14 | 15 | echo "#########################################################" 16 | echo "Add mysql persistent template and deploy the MySQL Server " 17 | echo "#########################################################" 18 | oc create -f $SCRIPTS_DIR/service/mysql-persistent-template-with-init.json 19 | oc new-app --template=mysql-persistent-with-init \ 20 | -p MYSQL_USER=mysql \ 21 | -p MYSQL_PASSWORD=mysql \ 22 | -p MYSQL_DATABASE=catalogdb 23 | 24 | # oc create -f https://raw.githubusercontent.com/openshift/origin/v1.5.1/examples/db-templates/mysql-ephemeral-template.json 25 | # oc new-app --template=mysql-ephemeral \ 26 | # -p MYSQL_USER=mysql \ 27 | # -p MYSQL_PASSWORD=mysql \ 28 | # -p MYSQL_DATABASE=catalogdb 29 | 30 | 31 | 32 | echo "##########################################" 33 | echo "Create missing files, deps (bootstrap.properties/service & route)" 34 | echo "##########################################" 35 | cd cdservice 36 | 37 | mkdir -p src/main/config-local 38 | mkdir -p src/main/config-openshift 39 | mv src/main/resources/application.properties src/main/config-local 40 | mv src/main/resources/data.sql src/main/config-local 41 | 42 | forge -e "project-remove-dependencies com.h2database:h2:" 43 | 44 | touch src/main/config-openshift/bootstrap.properties 45 | cat << 'EOF' > src/main/config-openshift/bootstrap.properties 46 | spring.application.name=cdservice 47 | EOF 48 | 49 | mkdir -p src/main/fabric8 50 | touch src/main/fabric8/configmap.yml 51 | 52 | forge -e "project-add-dependencies org.springframework.cloud:spring-cloud-starter-kubernetes-config:0.2.0.BUILD-SNAPSHOT" 53 | 54 | cat << 'EOF' > src/main/fabric8/configmap.yml 55 | metadata: 56 | name: ${project.artifactId} 57 | data: 58 | application.properties: |- 59 | cxf.jaxrs.component-scan=true 60 | cxf.path=/rest 61 | 62 | spring.datasource.url=jdbc\:mysql\://mysql\:3306/catalogdb 63 | spring.datasource.username=mysql 64 | spring.datasource.password=mysql 65 | 66 | spring.jpa.properties.hibernate.transaction.flush_before_completion=true 67 | spring.jpa.properties.hibernate.show_sql=true 68 | spring.jpa.properties.hibernate.format_sql=true 69 | spring.jpa.properties.hibernate.hbm2ddl.auto=validate 70 | spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQLDialect 71 | EOF 72 | 73 | touch src/main/fabric8/route.yml 74 | cat << 'EOF' > src/main/fabric8/route.yml 75 | apiVersion: v1 76 | kind: Route 77 | metadata: 78 | name: ${project.artifactId} 79 | spec: 80 | port: 81 | targetPort: 8080 82 | to: 83 | kind: Service 84 | name: ${project.artifactId} 85 | EOF 86 | 87 | xml="\ 88 | \ 89 | local\ 90 | \ 91 | \ 92 | com.h2database\ 93 | h2\ 94 | \ 95 | \ 96 | \ 97 | \ 98 | \ 99 | src/main/config-local\ 100 | \ 101 | \ 102 | src/main/resources\ 103 | \ 104 | \ 105 | \ 106 | \ 107 | \ 108 | openshift\ 109 | \ 110 | \ 111 | mysql\ 112 | mysql-connector-java\ 113 | \ 114 | \ 115 | \ 116 | \ 117 | \ 118 | src/main/config-openshift\ 119 | \ 120 | \ 121 | src/main/resources\ 122 | \ 123 | \ 124 | \ 125 | \ 126 | \ 127 | " 128 | 129 | sed -i.bak "s||$xml|" pom.xml 130 | 131 | echo "##########################################" 132 | echo "Install cdservice " 133 | echo "##########################################" 134 | mvn clean compile fabric8:deploy -Popenshift -DskipTests=true 135 | 136 | sleep 1m 137 | 138 | cd ../cdfront 139 | APP=$(oc get route cdservice -o json | jq '.spec.host' | tr -d \"\") 140 | echo "{ \"cd-service\": \"http://$APP/rest/catalogs/\" }" > src/main/resources/static/service.json 141 | 142 | mkdir -p src/main/fabric8/ 143 | touch src/main/fabric8/svc.yml 144 | 145 | cat << 'EOF' > src/main/fabric8/svc.yml 146 | apiVersion: v1 147 | kind: Service 148 | metadata: 149 | name: ${project.artifactId} 150 | spec: 151 | ports: 152 | - protocol: TCP 153 | port: 8080 154 | targetPort: 8081 155 | type: ClusterIP 156 | EOF 157 | 158 | touch src/main/fabric8/route.yml 159 | 160 | cat << 'EOF' > src/main/fabric8/route.yml 161 | apiVersion: v1 162 | kind: Route 163 | metadata: 164 | name: ${project.artifactId} 165 | spec: 166 | port: 167 | targetPort: 8081 168 | to: 169 | kind: Service 170 | name: ${project.artifactId} 171 | EOF 172 | 173 | echo "##########################################" 174 | echo "Install cdfront " 175 | echo "##########################################" 176 | mvn fabric8:deploy 177 | 178 | cd $CURRENT 179 | 180 | -------------------------------------------------------------------------------- /scripts/enable-fabric8.fsh: -------------------------------------------------------------------------------- 1 | cd cdservice 2 | # Add Fabric8 Maven Plugin 3 | fabric8-setup --integration-test=false 4 | 5 | cd ../cdfront 6 | # Add Fabric8 Maven Plugin 7 | fabric8-setup --integration-test=false 8 | 9 | cd .. -------------------------------------------------------------------------------- /scripts/enable_circuit_breaker.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | PROJECT_DIR=${1:-workshop} 4 | export CURRENT=$(pwd) 5 | 6 | cd $PROJECT_DIR 7 | 8 | echo "#########################################################" 9 | echo " Create Hystrix dashboard pod " 10 | echo "#########################################################" 11 | oc create -f http://repo1.maven.org/maven2/io/fabric8/kubeflix/hystrix-dashboard/1.0.28/hystrix-dashboard-1.0.28-openshift.yml 12 | oc expose service hystrix-dashboard --port=8080 13 | 14 | cd cdservice 15 | 16 | # Update project using Forge 17 | forge -e "run $SCRIPTS_DIR/add-circuit-breaker.fsh" 18 | 19 | cat << 'EOF' > src/main/fabric8/svc.yml 20 | apiVersion: v1 21 | kind: Service 22 | metadata: 23 | name: ${project.artifactId} 24 | labels: 25 | hystrix.enabled: true 26 | spec: 27 | ports: 28 | - protocol: TCP 29 | port: 8080 30 | targetPort: 8080 31 | type: ClusterIP 32 | EOF 33 | 34 | cat << 'EOF' >> src/main/fabric8/configmap.yml 35 | management.health.db.enabled=false 36 | management.security.enabled=false 37 | hystrix.command.default.circuitBreaker.requestVolumeThreshold=3 38 | hystrix.command.default.metrics.healthSnapshot.intervalInMilliseconds=100 39 | EOF 40 | 41 | # Replace CatalogEndpoint by modified version 42 | cp $SCRIPTS_DIR/service/CatalogEndpointCB.java src/main/java/org/cdservice/rest/CatalogEndpoint.java 43 | 44 | # Redeploy cdservice 45 | mvn clean compile fabric8:deploy -Popenshift -DskipTests=true 46 | 47 | sleep 10 48 | 49 | $SCRIPTS_DIR/load_and_break_service.sh 50 | 51 | cd $CURRENT -------------------------------------------------------------------------------- /scripts/front/generated/WEB-INF/web.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | cdservice 4 | 5 | 30 6 | 7 | 8 | ico 9 | image/x-icon 10 | 11 | 12 | /index.html 13 | 14 | 15 | -------------------------------------------------------------------------------- /scripts/front/generated/app.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Cdservice 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 27 | 28 |
29 |
30 | 31 | 41 | 42 |
43 | 47 |
48 |
49 |
50 |
51 |
52 |
53 | 54 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /scripts/front/generated/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redhat-microservices/lab_springboot-openshift/ee23e2cf97de151b437237eb9683ac9c26597493/scripts/front/generated/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /scripts/front/generated/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redhat-microservices/lab_springboot-openshift/ee23e2cf97de151b437237eb9683ac9c26597493/scripts/front/generated/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /scripts/front/generated/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redhat-microservices/lab_springboot-openshift/ee23e2cf97de151b437237eb9683ac9c26597493/scripts/front/generated/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /scripts/front/generated/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redhat-microservices/lab_springboot-openshift/ee23e2cf97de151b437237eb9683ac9c26597493/scripts/front/generated/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /scripts/front/generated/img/forge-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redhat-microservices/lab_springboot-openshift/ee23e2cf97de151b437237eb9683ac9c26597493/scripts/front/generated/img/forge-logo.png -------------------------------------------------------------------------------- /scripts/front/generated/index.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /scripts/front/generated/scripts/app.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('cdservice',['ngRoute','ngResource']) 4 | .config(['$routeProvider', function($routeProvider) { 5 | $routeProvider 6 | .when('/',{templateUrl:'views/landing.html',controller:'LandingPageController'}) 7 | .when('/Catalogs',{templateUrl:'views/Catalog/search.html',controller:'SearchCatalogController'}) 8 | .when('/Catalogs/new',{templateUrl:'views/Catalog/detail.html',controller:'NewCatalogController'}) 9 | .when('/Catalogs/edit/:CatalogId',{templateUrl:'views/Catalog/detail.html',controller:'EditCatalogController'}) 10 | .otherwise({ 11 | redirectTo: '/' 12 | }); 13 | }]) 14 | .controller('LandingPageController', function LandingPageController() { 15 | }) 16 | .controller('NavController', function NavController($scope, $location) { 17 | $scope.matchesRoute = function(route) { 18 | var path = $location.path(); 19 | return (path === ("/" + route) || path.indexOf("/" + route + "/") == 0); 20 | }; 21 | }); 22 | -------------------------------------------------------------------------------- /scripts/front/generated/scripts/controllers/editCatalogController.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | angular.module('cdservice').controller('EditCatalogController', function($scope, $routeParams, $location, flash, CatalogResource ) { 4 | var self = this; 5 | $scope.disabled = false; 6 | $scope.$location = $location; 7 | 8 | $scope.get = function() { 9 | var successCallback = function(data){ 10 | self.original = data; 11 | $scope.catalog = new CatalogResource(self.original); 12 | }; 13 | var errorCallback = function() { 14 | flash.setMessage({'type': 'error', 'text': 'The catalog could not be found.'}); 15 | $location.path("/Catalogs"); 16 | }; 17 | CatalogResource.get({CatalogId:$routeParams.CatalogId}, successCallback, errorCallback); 18 | }; 19 | 20 | $scope.isClean = function() { 21 | return angular.equals(self.original, $scope.catalog); 22 | }; 23 | 24 | $scope.save = function() { 25 | var successCallback = function(){ 26 | flash.setMessage({'type':'success','text':'The catalog was updated successfully.'}, true); 27 | $scope.get(); 28 | }; 29 | var errorCallback = function(response) { 30 | if(response && response.data && response.data.message) { 31 | flash.setMessage({'type': 'error', 'text': response.data.message}, true); 32 | } else { 33 | flash.setMessage({'type': 'error', 'text': 'Something broke. Retry, or cancel and start afresh.'}, true); 34 | } 35 | }; 36 | $scope.catalog.$update(successCallback, errorCallback); 37 | }; 38 | 39 | $scope.cancel = function() { 40 | $location.path("/Catalogs"); 41 | }; 42 | 43 | $scope.remove = function() { 44 | var successCallback = function() { 45 | flash.setMessage({'type': 'error', 'text': 'The catalog was deleted.'}); 46 | $location.path("/Catalogs"); 47 | }; 48 | var errorCallback = function(response) { 49 | if(response && response.data && response.data.message) { 50 | flash.setMessage({'type': 'error', 'text': response.data.message}, true); 51 | } else { 52 | flash.setMessage({'type': 'error', 'text': 'Something broke. Retry, or cancel and start afresh.'}, true); 53 | } 54 | }; 55 | $scope.catalog.$remove(successCallback, errorCallback); 56 | }; 57 | 58 | 59 | $scope.get(); 60 | }); -------------------------------------------------------------------------------- /scripts/front/generated/scripts/controllers/flashController.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('cdservice').controller('FlashController', ['$scope','flash', function ($scope, flash) { 4 | $scope.flash = flash; 5 | $scope.showAlert = false; 6 | 7 | $scope.$watch('flash.getMessage()', function(newVal) { 8 | var message = newVal; 9 | if(message && message.text) { 10 | $scope.showAlert = message.text.length > 0; 11 | } else { 12 | $scope.showAlert = false; 13 | } 14 | }); 15 | 16 | $scope.hideAlert = function() { 17 | $scope.showAlert = false; 18 | } 19 | }]); 20 | -------------------------------------------------------------------------------- /scripts/front/generated/scripts/controllers/newCatalogController.js: -------------------------------------------------------------------------------- 1 | 2 | angular.module('cdservice').controller('NewCatalogController', function ($scope, $location, locationParser, flash, CatalogResource ) { 3 | $scope.disabled = false; 4 | $scope.$location = $location; 5 | $scope.catalog = $scope.catalog || {}; 6 | 7 | 8 | $scope.save = function() { 9 | var successCallback = function(data,responseHeaders){ 10 | var id = locationParser(responseHeaders); 11 | flash.setMessage({'type':'success','text':'The catalog was created successfully.'}); 12 | $location.path('/Catalogs'); 13 | }; 14 | var errorCallback = function(response) { 15 | if(response && response.data) { 16 | flash.setMessage({'type': 'error', 'text': response.data.message || response.data}, true); 17 | } else { 18 | flash.setMessage({'type': 'error', 'text': 'Something broke. Retry, or cancel and start afresh.'}, true); 19 | } 20 | }; 21 | CatalogResource.save($scope.catalog, successCallback, errorCallback); 22 | }; 23 | 24 | $scope.cancel = function() { 25 | $location.path("/Catalogs"); 26 | }; 27 | }); -------------------------------------------------------------------------------- /scripts/front/generated/scripts/controllers/searchCatalogController.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | angular.module('cdservice').controller('SearchCatalogController', function($scope, $http, $filter, CatalogResource ) { 4 | 5 | $scope.search={}; 6 | $scope.currentPage = 0; 7 | $scope.pageSize= 10; 8 | $scope.searchResults = []; 9 | $scope.filteredResults = []; 10 | $scope.pageRange = []; 11 | $scope.numberOfPages = function() { 12 | var result = Math.ceil($scope.filteredResults.length/$scope.pageSize); 13 | var max = (result == 0) ? 1 : result; 14 | $scope.pageRange = []; 15 | for(var ctr=0;ctr 0) { 30 | $scope.currentPage--; 31 | } 32 | }; 33 | 34 | $scope.next = function() { 35 | if($scope.currentPage < ($scope.numberOfPages() - 1) ) { 36 | $scope.currentPage++; 37 | } 38 | }; 39 | 40 | $scope.setPage = function(n) { 41 | $scope.currentPage = n; 42 | }; 43 | 44 | $scope.performSearch(); 45 | }); -------------------------------------------------------------------------------- /scripts/front/generated/scripts/directives/datepicker.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var DATE_REGEX = /^([0-2][0-9]{3})\-([0-1][0-9])\-([0-3][0-9])$/; 4 | angular.module('cdservice').directive('date', function($parse, dateFilter) { 5 | return { 6 | restrict : "E", 7 | replace : true, 8 | transclude : false, 9 | require: '?ngModel', 10 | compile : function(element, attrs) { 11 | var modelAccessor = $parse(attrs.ngModel); 12 | 13 | var isRequired = ""; 14 | if(attrs.required) { 15 | isRequired = "required"; 16 | } 17 | var html = ""; 18 | 19 | var $newElem = $(html); 20 | element.replaceWith($newElem); 21 | 22 | var nativeLinker = function(scope, element, attrs, ngModelCtrl) { 23 | if(!ngModelCtrl) return; 24 | 25 | var dateParser = function(value) { 26 | var date; 27 | if(value) { 28 | date = new Date(Date.parse(value)); 29 | } else { 30 | date = value; 31 | } 32 | return date; 33 | } 34 | var dateFormatter = function(value) { 35 | if(value) { 36 | var date = dateFilter(value,"yyyy-MM-dd"); 37 | return date; 38 | } 39 | return; 40 | } 41 | 42 | ngModelCtrl.$parsers.unshift(dateParser); 43 | ngModelCtrl.$formatters.unshift(dateFormatter); 44 | 45 | element.bind("blur keyup change", function() { 46 | scope.$apply(function() { 47 | ngModelCtrl.$setViewValue(element.val()); 48 | }); 49 | }); 50 | 51 | ngModelCtrl.$render = function() { 52 | element.val(ngModelCtrl.$viewValue); 53 | } 54 | } 55 | 56 | var enhancedLinker = function(scope, element, attrs, ngModelCtrl) { 57 | if(!ngModelCtrl) return; 58 | 59 | var dateParser = function(value) { 60 | if(value) { 61 | var d = value.match(DATE_REGEX); 62 | if(d) { 63 | var formattedDate = d[1] + "-" + d[2] + "-" + d[3]; 64 | var date = new Date(Date.parse(formattedDate)); 65 | ngModelCtrl.$setValidity("dateFormat", true); 66 | return date; 67 | } else { 68 | ngModelCtrl.$setValidity("dateFormat", false); 69 | return; 70 | } 71 | } 72 | return; 73 | } 74 | var dateFormatter = function(value) { 75 | if(value) { 76 | var date = dateFilter(value,"yyyy-MM-dd"); 77 | return date; 78 | } 79 | return; 80 | } 81 | 82 | ngModelCtrl.$parsers.unshift(dateParser); 83 | ngModelCtrl.$formatters.unshift(dateFormatter); 84 | 85 | element.bind("blur keyup change", function() { 86 | scope.$apply(function() { 87 | ngModelCtrl.$setViewValue(element.val()); 88 | }); 89 | }); 90 | 91 | ngModelCtrl.$render = function() { 92 | element.val(ngModelCtrl.$viewValue); 93 | } 94 | } 95 | 96 | if(Modernizr.inputtypes["date"]) { 97 | return nativeLinker; 98 | } else { 99 | return enhancedLinker; 100 | } 101 | } 102 | } 103 | }); -------------------------------------------------------------------------------- /scripts/front/generated/scripts/directives/datetimepicker.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var LOCAL_DATETIME_REGEX = /^([0-2][0-9]{3})\-([0-1][0-9])\-([0-3][0-9])\ ([0-5][0-9])\:([0-5][0-9])\:([0-5][0-9])$/; 4 | angular.module('cdservice').directive('datetime', function($parse, dateFilter) { 5 | return { 6 | restrict : "E", 7 | replace : true, 8 | transclude : false, 9 | require: '?ngModel', 10 | compile : function(element, attrs) { 11 | var modelAccessor = $parse(attrs.ngModel); 12 | 13 | var isRequired = ""; 14 | if(attrs.required) { 15 | isRequired = "required"; 16 | } 17 | var html = ""; 18 | 19 | var $newElem = $(html); 20 | element.replaceWith($newElem); 21 | 22 | var nativeLinker = function(scope, element, attrs, ngModelCtrl) { 23 | if(!ngModelCtrl) return; 24 | 25 | var localDateTimeParser = function(value) { 26 | var date; 27 | if(value) { 28 | date = new Date(Date.parse(value)); 29 | date.setTime(date.getTime() + date.getTimezoneOffset()*60000); 30 | } else { 31 | date = value; 32 | } 33 | return date; 34 | } 35 | var localDateTimeFormatter = function(value) { 36 | if(value) { 37 | var date = dateFilter(value,"yyyy-MM-ddTHH:mm:ss"); 38 | return date; 39 | } 40 | return; 41 | } 42 | 43 | ngModelCtrl.$parsers.unshift(localDateTimeParser); 44 | ngModelCtrl.$formatters.unshift(localDateTimeFormatter); 45 | 46 | element.bind("blur keyup change", function() { 47 | scope.$apply(function() { 48 | ngModelCtrl.$setViewValue(element.val()); 49 | }); 50 | }); 51 | 52 | ngModelCtrl.$render = function() { 53 | element.val(ngModelCtrl.$viewValue); 54 | } 55 | } 56 | 57 | var enhancedLinker = function(scope, element, attrs, ngModelCtrl) { 58 | if(!ngModelCtrl) return; 59 | 60 | var localDateTimeParser = function(value) { 61 | if(value) { 62 | var d = value.match(LOCAL_DATETIME_REGEX); 63 | if(d) { 64 | var formattedDate = d[1] + "-" + d[2] + "-" + d[3] + "T" 65 | + d[4] + ":" + d[5] + ":" + d[6]; 66 | var date = new Date(Date.parse(formattedDate)); 67 | ngModelCtrl.$setValidity("datetimeFormat", true); 68 | return date; 69 | } else { 70 | ngModelCtrl.$setValidity("datetimeFormat", false); 71 | return; 72 | } 73 | } 74 | return; 75 | } 76 | var localDateTimeFormatter = function(value) { 77 | if(value) { 78 | var date = dateFilter(value,"yyyy-MM-dd HH:mm:ss"); 79 | return date; 80 | } 81 | return; 82 | } 83 | 84 | ngModelCtrl.$parsers.unshift(localDateTimeParser); 85 | ngModelCtrl.$formatters.unshift(localDateTimeFormatter); 86 | 87 | element.bind("blur keyup change", function() { 88 | scope.$apply(function() { 89 | ngModelCtrl.$setViewValue(element.val()); 90 | }); 91 | }); 92 | 93 | ngModelCtrl.$render = function() { 94 | element.val(ngModelCtrl.$viewValue); 95 | } 96 | } 97 | 98 | if(Modernizr.inputtypes["datetime-local"]) { 99 | return nativeLinker; 100 | } else { 101 | return enhancedLinker; 102 | } 103 | } 104 | } 105 | }); -------------------------------------------------------------------------------- /scripts/front/generated/scripts/directives/timepicker.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var TIME_REGEX = /^([0-5][0-9])\:([0-5][0-9])(?:\:([0-5][0-9]))?$/; 4 | angular.module('cdservice').directive('time', function($parse, dateFilter) { 5 | return { 6 | restrict : "E", 7 | replace : true, 8 | transclude : false, 9 | require: '?ngModel', 10 | compile : function(element, attrs) { 11 | var modelAccessor = $parse(attrs.ngModel); 12 | 13 | var isRequired = ""; 14 | if(attrs.required) { 15 | isRequired = "required"; 16 | } 17 | var html = ""; 18 | 19 | var $newElem = $(html); 20 | element.replaceWith($newElem); 21 | 22 | var nativeLinker = function(scope, element, attrs, ngModelCtrl) { 23 | if(!ngModelCtrl) return; 24 | 25 | var timeParser = function(value) { 26 | var date; 27 | if(value) { 28 | var d = value.match(TIME_REGEX); 29 | if(d) { 30 | date = new Date(0); 31 | if(!d[3]) { 32 | d[3] = "0"; 33 | } 34 | date.setHours(d[1], d[2], d[3]); 35 | } else { 36 | date = value; 37 | } 38 | } else { 39 | date = value; 40 | } 41 | return date; 42 | } 43 | var timeFormatter = function(value) { 44 | if(value) { 45 | var date = dateFilter(value,"HH:mm:ss"); 46 | return date; 47 | } 48 | return; 49 | } 50 | 51 | ngModelCtrl.$parsers.unshift(timeParser); 52 | ngModelCtrl.$formatters.unshift(timeFormatter); 53 | 54 | element.bind("blur keyup change", function() { 55 | scope.$apply(function() { 56 | ngModelCtrl.$setViewValue(element.val()); 57 | }); 58 | }); 59 | 60 | ngModelCtrl.$render = function() { 61 | element.val(ngModelCtrl.$viewValue); 62 | } 63 | } 64 | 65 | var enhancedLinker = function(scope, element, attrs, ngModelCtrl) { 66 | if(!ngModelCtrl) return; 67 | 68 | var timeParser = function(value) { 69 | if(value) { 70 | var d = value.match(TIME_REGEX); 71 | if(d) { 72 | var date = new Date(0); 73 | if(!d[3]) { 74 | d[3] = "0"; 75 | } 76 | date.setHours(d[1], d[2], d[3]); 77 | ngModelCtrl.$setValidity("timeFormat", true); 78 | return date; 79 | } else { 80 | ngModelCtrl.$setValidity("timeFormat", false); 81 | return; 82 | } 83 | } 84 | return; 85 | } 86 | var timeFormatter = function(value) { 87 | if(value) { 88 | var date = dateFilter(value,"HH:mm:ss"); 89 | return date; 90 | } 91 | return; 92 | } 93 | 94 | ngModelCtrl.$parsers.unshift(timeParser); 95 | ngModelCtrl.$formatters.unshift(timeFormatter); 96 | 97 | element.bind("blur keyup change", function() { 98 | scope.$apply(function() { 99 | ngModelCtrl.$setViewValue(element.val()); 100 | }); 101 | }); 102 | 103 | ngModelCtrl.$render = function() { 104 | element.val(ngModelCtrl.$viewValue); 105 | } 106 | } 107 | 108 | if(Modernizr.inputtypes["time"]) { 109 | return nativeLinker; 110 | } else { 111 | return enhancedLinker; 112 | } 113 | } 114 | } 115 | }); -------------------------------------------------------------------------------- /scripts/front/generated/scripts/filters/genericSearchFilter.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('cdservice').filter('searchFilter', function() { 4 | 5 | function matchObjectProperties(expectedObject, actualObject) { 6 | var flag = true; 7 | for(var key in expectedObject) { 8 | if(expectedObject.hasOwnProperty(key)) { 9 | var expectedProperty = expectedObject[key]; 10 | if (expectedProperty == null || expectedProperty === "") { 11 | continue; 12 | } 13 | var actualProperty = actualObject[key]; 14 | if (angular.isUndefined(actualProperty)) { 15 | continue; 16 | } 17 | if (actualProperty == null) { 18 | flag = false; 19 | } else if (angular.isObject(expectedProperty)) { 20 | flag = flag && matchObjectProperties(expectedProperty, actualProperty); 21 | } else { 22 | flag = flag && (actualProperty.toString().indexOf(expectedProperty.toString()) != -1); 23 | } 24 | } 25 | } 26 | return flag; 27 | } 28 | 29 | return function(results, scope) { 30 | 31 | scope.filteredResults = []; 32 | for (var ctr = 0; ctr < results.length; ctr++) { 33 | var flag = true; 34 | var searchCriteria = scope.search; 35 | var result = results[ctr]; 36 | for (var key in searchCriteria) { 37 | if (searchCriteria.hasOwnProperty(key)) { 38 | var expected = searchCriteria[key]; 39 | if (expected == null || expected === "") { 40 | continue; 41 | } 42 | var actual = result[key]; 43 | if (actual == null) { 44 | flag = false; 45 | } else if (angular.isObject(expected)) { 46 | flag = flag && matchObjectProperties(expected, actual); 47 | } else { 48 | flag = flag && (actual.toString().indexOf(expected.toString()) != -1); 49 | } 50 | } 51 | } 52 | if (flag == true) { 53 | scope.filteredResults.push(result); 54 | } 55 | } 56 | scope.numberOfPages(); 57 | return scope.filteredResults; 58 | }; 59 | }); 60 | -------------------------------------------------------------------------------- /scripts/front/generated/scripts/filters/startFromFilter.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('cdservice').filter('startFrom', function() { 4 | return function(input, start) { 5 | start = +start; //parse to int 6 | return input.slice(start); 7 | }; 8 | }); -------------------------------------------------------------------------------- /scripts/front/generated/scripts/offcanvas.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function() { 2 | $('[data-toggle=offcanvas]').click(function() { 3 | $('.row-offcanvas').toggleClass('active'); 4 | }); 5 | }); -------------------------------------------------------------------------------- /scripts/front/generated/scripts/services/CatalogFactory.js: -------------------------------------------------------------------------------- 1 | angular.module('cdservice').factory('CatalogResource', function($resource){ 2 | var resource = $resource('rest/catalogs/:CatalogId',{CatalogId:'@id'},{'queryAll':{method:'GET',isArray:true},'query':{method:'GET',isArray:false},'update':{method:'PUT'}}); 3 | return resource; 4 | }); -------------------------------------------------------------------------------- /scripts/front/generated/scripts/services/flash.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('cdservice').factory('flash', ['$rootScope', function ($rootScope) { 4 | var messages = []; 5 | var currentMessage = {}; 6 | 7 | $rootScope.$on('$routeChangeSuccess', function() { 8 | currentMessage = messages.shift() || {}; 9 | }); 10 | 11 | return { 12 | getMessage: function () { 13 | return currentMessage; 14 | }, 15 | setMessage: function(message, pop) { 16 | switch(message.type) { 17 | case "error" : message.cssClass = "danger"; break; 18 | case "success" : message.cssClass = "success"; break; 19 | case "info" : message.cssClass = "info"; break; 20 | case "warning" : message.cssClass = "warning"; break; 21 | } 22 | messages.push(message); 23 | if(pop) { 24 | currentMessage = messages.shift() || {}; 25 | } 26 | } 27 | }; 28 | }]); 29 | -------------------------------------------------------------------------------- /scripts/front/generated/scripts/services/locationParser.js: -------------------------------------------------------------------------------- 1 | angular.module('cdservice').value('locationParser', function(responseHeaders){ 2 | // Get the Location header and parse it. 3 | var locationHeader = responseHeaders('Location'); 4 | var fragments = locationHeader.split('/'); 5 | var id = fragments[fragments.length -1]; 6 | return id; 7 | }); -------------------------------------------------------------------------------- /scripts/front/generated/scripts/vendor/modernizr-2.8.3.min.js: -------------------------------------------------------------------------------- 1 | /* Modernizr 2.8.3 (Custom Build) | MIT & BSD 2 | * Build: http://modernizr.com/download/#-fontface-backgroundsize-borderimage-borderradius-boxshadow-flexbox-flexboxlegacy-hsla-multiplebgs-opacity-rgba-textshadow-cssanimations-csscolumns-generatedcontent-cssgradients-cssreflections-csstransforms-csstransforms3d-csstransitions-canvas-canvastext-input-inputtypes-geolocation-inlinesvg-smil-svg-svgclippaths-touch-webgl-shiv-mq-cssclasses-teststyles-testprop-testallprops-hasevent-prefixes-domprefixes 3 | */ 4 | ;window.Modernizr=function(a,b,c){function D(a){j.cssText=a}function E(a,b){return D(n.join(a+";")+(b||""))}function F(a,b){return typeof a===b}function G(a,b){return!!~(""+a).indexOf(b)}function H(a,b){for(var d in a){var e=a[d];if(!G(e,"-")&&j[e]!==c)return b=="pfx"?e:!0}return!1}function I(a,b,d){for(var e in a){var f=b[a[e]];if(f!==c)return d===!1?a[e]:F(f,"function")?f.bind(d||b):f}return!1}function J(a,b,c){var d=a.charAt(0).toUpperCase()+a.slice(1),e=(a+" "+p.join(d+" ")+d).split(" ");return F(b,"string")||F(b,"undefined")?H(e,b):(e=(a+" "+q.join(d+" ")+d).split(" "),I(e,b,c))}function K(){e.input=function(c){for(var d=0,e=c.length;d',a,""].join(""),l.id=h,(m?l:n).innerHTML+=f,n.appendChild(l),m||(n.style.background="",n.style.overflow="hidden",k=g.style.overflow,g.style.overflow="hidden",g.appendChild(n)),i=c(l,a),m?l.parentNode.removeChild(l):(n.parentNode.removeChild(n),g.style.overflow=k),!!i},z=function(b){var c=a.matchMedia||a.msMatchMedia;if(c)return c(b)&&c(b).matches||!1;var d;return y("@media "+b+" { #"+h+" { position: absolute; } }",function(b){d=(a.getComputedStyle?getComputedStyle(b,null):b.currentStyle)["position"]=="absolute"}),d},A=function(){function d(d,e){e=e||b.createElement(a[d]||"div"),d="on"+d;var f=d in e;return f||(e.setAttribute||(e=b.createElement("div")),e.setAttribute&&e.removeAttribute&&(e.setAttribute(d,""),f=F(e[d],"function"),F(e[d],"undefined")||(e[d]=c),e.removeAttribute(d))),e=null,f}var a={select:"input",change:"input",submit:"form",reset:"form",error:"img",load:"img",abort:"img"};return d}(),B={}.hasOwnProperty,C;!F(B,"undefined")&&!F(B.call,"undefined")?C=function(a,b){return B.call(a,b)}:C=function(a,b){return b in a&&F(a.constructor.prototype[b],"undefined")},Function.prototype.bind||(Function.prototype.bind=function(b){var c=this;if(typeof c!="function")throw new TypeError;var d=w.call(arguments,1),e=function(){if(this instanceof e){var a=function(){};a.prototype=c.prototype;var f=new a,g=c.apply(f,d.concat(w.call(arguments)));return Object(g)===g?g:f}return c.apply(b,d.concat(w.call(arguments)))};return e}),s.flexbox=function(){return J("flexWrap")},s.flexboxlegacy=function(){return J("boxDirection")},s.canvas=function(){var a=b.createElement("canvas");return!!a.getContext&&!!a.getContext("2d")},s.canvastext=function(){return!!e.canvas&&!!F(b.createElement("canvas").getContext("2d").fillText,"function")},s.webgl=function(){return!!a.WebGLRenderingContext},s.touch=function(){var c;return"ontouchstart"in a||a.DocumentTouch&&b instanceof DocumentTouch?c=!0:y(["@media (",n.join("touch-enabled),("),h,")","{#modernizr{top:9px;position:absolute}}"].join(""),function(a){c=a.offsetTop===9}),c},s.geolocation=function(){return"geolocation"in navigator},s.rgba=function(){return D("background-color:rgba(150,255,150,.5)"),G(j.backgroundColor,"rgba")},s.hsla=function(){return D("background-color:hsla(120,40%,100%,.5)"),G(j.backgroundColor,"rgba")||G(j.backgroundColor,"hsla")},s.multiplebgs=function(){return D("background:url(https://),url(https://),red url(https://)"),/(url\s*\(.*?){3}/.test(j.background)},s.backgroundsize=function(){return J("backgroundSize")},s.borderimage=function(){return J("borderImage")},s.borderradius=function(){return J("borderRadius")},s.boxshadow=function(){return J("boxShadow")},s.textshadow=function(){return b.createElement("div").style.textShadow===""},s.opacity=function(){return E("opacity:.55"),/^0.55$/.test(j.opacity)},s.cssanimations=function(){return J("animationName")},s.csscolumns=function(){return J("columnCount")},s.cssgradients=function(){var a="background-image:",b="gradient(linear,left top,right bottom,from(#9f9),to(white));",c="linear-gradient(left top,#9f9, white);";return D((a+"-webkit- ".split(" ").join(b+a)+n.join(c+a)).slice(0,-a.length)),G(j.backgroundImage,"gradient")},s.cssreflections=function(){return J("boxReflect")},s.csstransforms=function(){return!!J("transform")},s.csstransforms3d=function(){var a=!!J("perspective");return a&&"webkitPerspective"in g.style&&y("@media (transform-3d),(-webkit-transform-3d){#modernizr{left:9px;position:absolute;height:3px;}}",function(b,c){a=b.offsetLeft===9&&b.offsetHeight===3}),a},s.csstransitions=function(){return J("transition")},s.fontface=function(){var a;return y('@font-face {font-family:"font";src:url("https://")}',function(c,d){var e=b.getElementById("smodernizr"),f=e.sheet||e.styleSheet,g=f?f.cssRules&&f.cssRules[0]?f.cssRules[0].cssText:f.cssText||"":"";a=/src/i.test(g)&&g.indexOf(d.split(" ")[0])===0}),a},s.generatedcontent=function(){var a;return y(["#",h,"{font:0/0 a}#",h,':after{content:"',l,'";visibility:hidden;font:3px/1 a}'].join(""),function(b){a=b.offsetHeight>=3}),a},s.svg=function(){return!!b.createElementNS&&!!b.createElementNS(r.svg,"svg").createSVGRect},s.inlinesvg=function(){var a=b.createElement("div");return a.innerHTML="",(a.firstChild&&a.firstChild.namespaceURI)==r.svg},s.smil=function(){return!!b.createElementNS&&/SVGAnimate/.test(m.call(b.createElementNS(r.svg,"animate")))},s.svgclippaths=function(){return!!b.createElementNS&&/SVGClipPath/.test(m.call(b.createElementNS(r.svg,"clipPath")))};for(var L in s)C(s,L)&&(x=L.toLowerCase(),e[x]=s[L](),v.push((e[x]?"":"no-")+x));return e.input||K(),e.addTest=function(a,b){if(typeof a=="object")for(var d in a)C(a,d)&&e.addTest(d,a[d]);else{a=a.toLowerCase();if(e[a]!==c)return e;b=typeof b=="function"?b():b,typeof f!="undefined"&&f&&(g.className+=" "+(b?"":"no-")+a),e[a]=b}return e},D(""),i=k=null,function(a,b){function l(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x",d.insertBefore(c.lastChild,d.firstChild)}function m(){var a=s.elements;return typeof a=="string"?a.split(" "):a}function n(a){var b=j[a[h]];return b||(b={},i++,a[h]=i,j[i]=b),b}function o(a,c,d){c||(c=b);if(k)return c.createElement(a);d||(d=n(c));var g;return d.cache[a]?g=d.cache[a].cloneNode():f.test(a)?g=(d.cache[a]=d.createElem(a)).cloneNode():g=d.createElem(a),g.canHaveChildren&&!e.test(a)&&!g.tagUrn?d.frag.appendChild(g):g}function p(a,c){a||(a=b);if(k)return a.createDocumentFragment();c=c||n(a);var d=c.frag.cloneNode(),e=0,f=m(),g=f.length;for(;e",g="hidden"in a,k=a.childNodes.length==1||function(){b.createElement("a");var a=b.createDocumentFragment();return typeof a.cloneNode=="undefined"||typeof a.createDocumentFragment=="undefined"||typeof a.createElement=="undefined"}()}catch(c){g=!0,k=!0}})();var s={elements:d.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output progress section summary template time video",version:c,shivCSS:d.shivCSS!==!1,supportsUnknownElements:k,shivMethods:d.shivMethods!==!1,type:"default",shivDocument:r,createElement:o,createDocumentFragment:p};a.html5=s,r(b)}(this,b),e._version=d,e._prefixes=n,e._domPrefixes=q,e._cssomPrefixes=p,e.mq=z,e.hasEvent=A,e.testProp=function(a){return H([a])},e.testAllProps=J,e.testStyles=y,g.className=g.className.replace(/(^|\s)no-js(\s|$)/,"$1$2")+(f?" js "+v.join(" "):""),e}(this,this.document); -------------------------------------------------------------------------------- /scripts/front/generated/styles/main.css: -------------------------------------------------------------------------------- 1 | @CHARSET "UTF-8"; 2 | 3 | /* Sticky footer styles 4 | -------------------------------------------------- */ 5 | 6 | html, body { 7 | height: 100%; 8 | /* The html and body elements cannot have any padding or margin. */ 9 | } 10 | 11 | /* Wrapper for page content to push down footer */ 12 | #wrap { 13 | min-height: 100%; 14 | height: auto; 15 | /* Negative indent footer by it's height */ 16 | margin: 0 auto -60px; 17 | /* Pad bottom by footer height */ 18 | padding: 0 0 60px; 19 | } 20 | 21 | #wrap > .container { 22 | padding-top: 50px; 23 | } 24 | 25 | /* Set the fixed height of the footer here */ 26 | #footer { 27 | height: 60px; 28 | } 29 | 30 | #footer { 31 | background-color: #F5F5F5; 32 | text-align: center; 33 | border-top: 1px solid #E5E5E5; 34 | } 35 | 36 | h2 i.icon-check { 37 | vertical-align: middle; 38 | } 39 | 40 | table { 41 | table-layout: fixed; 42 | word-wrap: break-word; 43 | } 44 | 45 | /* Lastly, apply responsive CSS fixes as necessary */ 46 | @media (max-width: 767px) { 47 | table { 48 | table-layout: auto; 49 | } 50 | .row-offcanvas { 51 | position: relative; 52 | transition: all 0.25s ease-out; 53 | } 54 | .row-offcanvas-left .sidebar-offcanvas { 55 | display:none; 56 | } 57 | .row-offcanvas-left.active .sidebar-offcanvas { 58 | display:inherit; 59 | } 60 | .row-offcanvas-left.active .mainarea { 61 | display:none; 62 | } 63 | .sidebar-offcanvas { 64 | position: absolute; 65 | top: 0; 66 | width: 100%; 67 | } 68 | } -------------------------------------------------------------------------------- /scripts/front/generated/views/Catalog/detail.html: -------------------------------------------------------------------------------- 1 |
2 |

Create a new Catalog

3 |

View or edit Catalog

4 |
5 |
6 | 7 | 8 |
9 | 10 |
11 | 12 |
13 |
14 | 15 |
16 | 17 |
18 | 19 |
20 |
21 | 22 |
23 | 24 |
25 | 26 | maximum length is 2000 27 |
28 |
29 | 30 |
31 | 32 |
33 | 34 | not a number 35 |
36 |
37 | 38 |
39 | 40 |
41 | 42 | does not match format "yyyy-MM-dd" (e.g. 2013-12-01) 43 |
44 |
45 | 46 | 47 |
48 |
49 | 50 | 51 | 52 |
53 |
54 |
-------------------------------------------------------------------------------- /scripts/front/generated/views/Catalog/search.html: -------------------------------------------------------------------------------- 1 |
2 |

Create a new Catalog

3 |
4 |
5 | Create 6 |
7 |
8 |
9 |
10 |
11 |

Search for Catalogs

12 |
13 | 14 | 15 |
16 | 17 |
18 | 19 |
20 |
21 | 22 |
23 | 24 |
25 | 26 |
27 |
28 | 29 |
30 | 31 |
32 | 33 |
34 |
35 | 36 |
37 | 38 |
39 | 40 |
41 |
42 | 43 | 44 | 45 |
46 |
47 | Search 48 |
49 |
50 |
51 |
52 |
53 |
54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 |
ArtistTitleDescriptionPricePublication_date
{{result.artist}}{{result.title}}{{result.description}}{{result.price}}{{result.publication_date| date:'mediumDate'}}
74 |
75 | 76 |
    77 |
  • 78 | 79 |
  • 80 |
  • 81 | 1 82 |
  • 83 |
  • 84 | 85 |
  • 86 |
87 | 88 |
-------------------------------------------------------------------------------- /scripts/front/generated/views/landing.html: -------------------------------------------------------------------------------- 1 |

2 | Your application is running. 3 |

4 |

5 | Documentation 7 | | Get Excited!

9 | Forge Project
| User 11 | Forums | Report an issue 13 |

-------------------------------------------------------------------------------- /scripts/front/modified/app.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Cdservice 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 27 | 28 |
29 |
30 | 31 | 41 | 42 |
43 | 47 |
48 |
49 |
50 |
51 |
52 |
53 | 54 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /scripts/front/modified/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redhat-microservices/lab_springboot-openshift/ee23e2cf97de151b437237eb9683ac9c26597493/scripts/front/modified/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /scripts/front/modified/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redhat-microservices/lab_springboot-openshift/ee23e2cf97de151b437237eb9683ac9c26597493/scripts/front/modified/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /scripts/front/modified/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redhat-microservices/lab_springboot-openshift/ee23e2cf97de151b437237eb9683ac9c26597493/scripts/front/modified/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /scripts/front/modified/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redhat-microservices/lab_springboot-openshift/ee23e2cf97de151b437237eb9683ac9c26597493/scripts/front/modified/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /scripts/front/modified/img/forge-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redhat-microservices/lab_springboot-openshift/ee23e2cf97de151b437237eb9683ac9c26597493/scripts/front/modified/img/forge-logo.png -------------------------------------------------------------------------------- /scripts/front/modified/index.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /scripts/front/modified/scripts/app.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('cdservice',['ngRoute','ngResource']) 4 | .config(['$routeProvider', function($routeProvider) { 5 | $routeProvider 6 | .when('/',{templateUrl:'views/landing.html',controller:'LandingPageController'}) 7 | .when('/Catalogs', 8 | { 9 | templateUrl:'views/Catalog/search.html', 10 | controller:'SearchCatalogController', 11 | resolve: { 12 | apiUrl: function(config) { 13 | return config.promise; 14 | } 15 | } 16 | }) 17 | .when('/Catalogs/new',{templateUrl:'views/Catalog/detail.html',controller:'NewCatalogController'}) 18 | .when('/Catalogs/edit/:CatalogId',{templateUrl:'views/Catalog/detail.html',controller:'EditCatalogController'}) 19 | .otherwise({ 20 | redirectTo: '/' 21 | }); 22 | }]) 23 | .controller('LandingPageController', function LandingPageController() { 24 | }) 25 | .controller('NavController', function NavController($scope, $location) { 26 | $scope.matchesRoute = function(route) { 27 | var path = $location.path(); 28 | return (path === ("/" + route) || path.indexOf("/" + route + "/") == 0); 29 | }; 30 | }); 31 | -------------------------------------------------------------------------------- /scripts/front/modified/scripts/controllers/editCatalogController.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | angular.module('cdservice').controller('EditCatalogController', function($scope, $routeParams, $location, flash, CatalogResource ) { 4 | var self = this; 5 | $scope.disabled = false; 6 | $scope.$location = $location; 7 | 8 | $scope.get = function() { 9 | var successCallback = function(data){ 10 | self.original = data; 11 | $scope.catalog = new CatalogResource(self.original); 12 | }; 13 | var errorCallback = function() { 14 | flash.setMessage({'type': 'error', 'text': 'The catalog could not be found.'}); 15 | $location.path("/Catalogs"); 16 | }; 17 | CatalogResource.get({CatalogId:$routeParams.CatalogId}, successCallback, errorCallback); 18 | }; 19 | 20 | $scope.isClean = function() { 21 | return angular.equals(self.original, $scope.catalog); 22 | }; 23 | 24 | $scope.save = function() { 25 | var successCallback = function(){ 26 | flash.setMessage({'type':'success','text':'The catalog was updated successfully.'}, true); 27 | $scope.get(); 28 | }; 29 | var errorCallback = function(response) { 30 | if(response && response.data && response.data.message) { 31 | flash.setMessage({'type': 'error', 'text': response.data.message}, true); 32 | } else { 33 | flash.setMessage({'type': 'error', 'text': 'Something broke. Retry, or cancel and start afresh.'}, true); 34 | } 35 | }; 36 | $scope.catalog.$update(successCallback, errorCallback); 37 | }; 38 | 39 | $scope.cancel = function() { 40 | $location.path("/Catalogs"); 41 | }; 42 | 43 | $scope.remove = function() { 44 | var successCallback = function() { 45 | flash.setMessage({'type': 'error', 'text': 'The catalog was deleted.'}); 46 | $location.path("/Catalogs"); 47 | }; 48 | var errorCallback = function(response) { 49 | if(response && response.data && response.data.message) { 50 | flash.setMessage({'type': 'error', 'text': response.data.message}, true); 51 | } else { 52 | flash.setMessage({'type': 'error', 'text': 'Something broke. Retry, or cancel and start afresh.'}, true); 53 | } 54 | }; 55 | $scope.catalog.$remove(successCallback, errorCallback); 56 | }; 57 | 58 | 59 | $scope.get(); 60 | }); -------------------------------------------------------------------------------- /scripts/front/modified/scripts/controllers/flashController.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('cdservice').controller('FlashController', ['$scope','flash', function ($scope, flash) { 4 | $scope.flash = flash; 5 | $scope.showAlert = false; 6 | 7 | $scope.$watch('flash.getMessage()', function(newVal) { 8 | var message = newVal; 9 | if(message && message.text) { 10 | $scope.showAlert = message.text.length > 0; 11 | } else { 12 | $scope.showAlert = false; 13 | } 14 | }); 15 | 16 | $scope.hideAlert = function() { 17 | $scope.showAlert = false; 18 | } 19 | }]); 20 | -------------------------------------------------------------------------------- /scripts/front/modified/scripts/controllers/newCatalogController.js: -------------------------------------------------------------------------------- 1 | 2 | angular.module('cdservice').controller('NewCatalogController', function ($scope, $location, locationParser, flash, CatalogResource ) { 3 | $scope.disabled = false; 4 | $scope.$location = $location; 5 | $scope.catalog = $scope.catalog || {}; 6 | 7 | 8 | $scope.save = function() { 9 | var successCallback = function(data,responseHeaders){ 10 | var id = locationParser(responseHeaders); 11 | flash.setMessage({'type':'success','text':'The catalog was created successfully.'}); 12 | $location.path('/Catalogs'); 13 | }; 14 | var errorCallback = function(response) { 15 | if(response && response.data) { 16 | flash.setMessage({'type': 'error', 'text': response.data.message || response.data}, true); 17 | } else { 18 | flash.setMessage({'type': 'error', 'text': 'Something broke. Retry, or cancel and start afresh.'}, true); 19 | } 20 | }; 21 | CatalogResource.save($scope.catalog, successCallback, errorCallback); 22 | }; 23 | 24 | $scope.cancel = function() { 25 | $location.path("/Catalogs"); 26 | }; 27 | }); -------------------------------------------------------------------------------- /scripts/front/modified/scripts/controllers/searchCatalogController.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | angular.module('cdservice').controller('SearchCatalogController', function($scope, $http, $filter, CatalogResource ) { 4 | 5 | $scope.search={}; 6 | $scope.currentPage = 0; 7 | $scope.pageSize= 10; 8 | $scope.searchResults = []; 9 | $scope.filteredResults = []; 10 | $scope.pageRange = []; 11 | $scope.numberOfPages = function() { 12 | var result = Math.ceil($scope.filteredResults.length/$scope.pageSize); 13 | var max = (result == 0) ? 1 : result; 14 | $scope.pageRange = []; 15 | for(var ctr=0;ctr 0) { 30 | $scope.currentPage--; 31 | } 32 | }; 33 | 34 | $scope.next = function() { 35 | if($scope.currentPage < ($scope.numberOfPages() - 1) ) { 36 | $scope.currentPage++; 37 | } 38 | }; 39 | 40 | $scope.setPage = function(n) { 41 | $scope.currentPage = n; 42 | }; 43 | 44 | $scope.performSearch(); 45 | }); -------------------------------------------------------------------------------- /scripts/front/modified/scripts/directives/datepicker.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var DATE_REGEX = /^([0-2][0-9]{3})\-([0-1][0-9])\-([0-3][0-9])$/; 4 | angular.module('cdservice').directive('date', function($parse, dateFilter) { 5 | return { 6 | restrict : "E", 7 | replace : true, 8 | transclude : false, 9 | require: '?ngModel', 10 | compile : function(element, attrs) { 11 | var modelAccessor = $parse(attrs.ngModel); 12 | 13 | var isRequired = ""; 14 | if(attrs.required) { 15 | isRequired = "required"; 16 | } 17 | var html = ""; 18 | 19 | var $newElem = $(html); 20 | element.replaceWith($newElem); 21 | 22 | var nativeLinker = function(scope, element, attrs, ngModelCtrl) { 23 | if(!ngModelCtrl) return; 24 | 25 | var dateParser = function(value) { 26 | var date; 27 | if(value) { 28 | date = new Date(Date.parse(value)); 29 | } else { 30 | date = value; 31 | } 32 | return date; 33 | } 34 | var dateFormatter = function(value) { 35 | if(value) { 36 | var date = dateFilter(value,"yyyy-MM-dd"); 37 | return date; 38 | } 39 | return; 40 | } 41 | 42 | ngModelCtrl.$parsers.unshift(dateParser); 43 | ngModelCtrl.$formatters.unshift(dateFormatter); 44 | 45 | element.bind("blur keyup change", function() { 46 | scope.$apply(function() { 47 | ngModelCtrl.$setViewValue(element.val()); 48 | }); 49 | }); 50 | 51 | ngModelCtrl.$render = function() { 52 | element.val(ngModelCtrl.$viewValue); 53 | } 54 | } 55 | 56 | var enhancedLinker = function(scope, element, attrs, ngModelCtrl) { 57 | if(!ngModelCtrl) return; 58 | 59 | var dateParser = function(value) { 60 | if(value) { 61 | var d = value.match(DATE_REGEX); 62 | if(d) { 63 | var formattedDate = d[1] + "-" + d[2] + "-" + d[3]; 64 | var date = new Date(Date.parse(formattedDate)); 65 | ngModelCtrl.$setValidity("dateFormat", true); 66 | return date; 67 | } else { 68 | ngModelCtrl.$setValidity("dateFormat", false); 69 | return; 70 | } 71 | } 72 | return; 73 | } 74 | var dateFormatter = function(value) { 75 | if(value) { 76 | var date = dateFilter(value,"yyyy-MM-dd"); 77 | return date; 78 | } 79 | return; 80 | } 81 | 82 | ngModelCtrl.$parsers.unshift(dateParser); 83 | ngModelCtrl.$formatters.unshift(dateFormatter); 84 | 85 | element.bind("blur keyup change", function() { 86 | scope.$apply(function() { 87 | ngModelCtrl.$setViewValue(element.val()); 88 | }); 89 | }); 90 | 91 | ngModelCtrl.$render = function() { 92 | element.val(ngModelCtrl.$viewValue); 93 | } 94 | } 95 | 96 | if(Modernizr.inputtypes["date"]) { 97 | return nativeLinker; 98 | } else { 99 | return enhancedLinker; 100 | } 101 | } 102 | } 103 | }); -------------------------------------------------------------------------------- /scripts/front/modified/scripts/directives/datetimepicker.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var LOCAL_DATETIME_REGEX = /^([0-2][0-9]{3})\-([0-1][0-9])\-([0-3][0-9])\ ([0-5][0-9])\:([0-5][0-9])\:([0-5][0-9])$/; 4 | angular.module('cdservice').directive('datetime', function($parse, dateFilter) { 5 | return { 6 | restrict : "E", 7 | replace : true, 8 | transclude : false, 9 | require: '?ngModel', 10 | compile : function(element, attrs) { 11 | var modelAccessor = $parse(attrs.ngModel); 12 | 13 | var isRequired = ""; 14 | if(attrs.required) { 15 | isRequired = "required"; 16 | } 17 | var html = ""; 18 | 19 | var $newElem = $(html); 20 | element.replaceWith($newElem); 21 | 22 | var nativeLinker = function(scope, element, attrs, ngModelCtrl) { 23 | if(!ngModelCtrl) return; 24 | 25 | var localDateTimeParser = function(value) { 26 | var date; 27 | if(value) { 28 | date = new Date(Date.parse(value)); 29 | date.setTime(date.getTime() + date.getTimezoneOffset()*60000); 30 | } else { 31 | date = value; 32 | } 33 | return date; 34 | } 35 | var localDateTimeFormatter = function(value) { 36 | if(value) { 37 | var date = dateFilter(value,"yyyy-MM-ddTHH:mm:ss"); 38 | return date; 39 | } 40 | return; 41 | } 42 | 43 | ngModelCtrl.$parsers.unshift(localDateTimeParser); 44 | ngModelCtrl.$formatters.unshift(localDateTimeFormatter); 45 | 46 | element.bind("blur keyup change", function() { 47 | scope.$apply(function() { 48 | ngModelCtrl.$setViewValue(element.val()); 49 | }); 50 | }); 51 | 52 | ngModelCtrl.$render = function() { 53 | element.val(ngModelCtrl.$viewValue); 54 | } 55 | } 56 | 57 | var enhancedLinker = function(scope, element, attrs, ngModelCtrl) { 58 | if(!ngModelCtrl) return; 59 | 60 | var localDateTimeParser = function(value) { 61 | if(value) { 62 | var d = value.match(LOCAL_DATETIME_REGEX); 63 | if(d) { 64 | var formattedDate = d[1] + "-" + d[2] + "-" + d[3] + "T" 65 | + d[4] + ":" + d[5] + ":" + d[6]; 66 | var date = new Date(Date.parse(formattedDate)); 67 | ngModelCtrl.$setValidity("datetimeFormat", true); 68 | return date; 69 | } else { 70 | ngModelCtrl.$setValidity("datetimeFormat", false); 71 | return; 72 | } 73 | } 74 | return; 75 | } 76 | var localDateTimeFormatter = function(value) { 77 | if(value) { 78 | var date = dateFilter(value,"yyyy-MM-dd HH:mm:ss"); 79 | return date; 80 | } 81 | return; 82 | } 83 | 84 | ngModelCtrl.$parsers.unshift(localDateTimeParser); 85 | ngModelCtrl.$formatters.unshift(localDateTimeFormatter); 86 | 87 | element.bind("blur keyup change", function() { 88 | scope.$apply(function() { 89 | ngModelCtrl.$setViewValue(element.val()); 90 | }); 91 | }); 92 | 93 | ngModelCtrl.$render = function() { 94 | element.val(ngModelCtrl.$viewValue); 95 | } 96 | } 97 | 98 | if(Modernizr.inputtypes["datetime-local"]) { 99 | return nativeLinker; 100 | } else { 101 | return enhancedLinker; 102 | } 103 | } 104 | } 105 | }); -------------------------------------------------------------------------------- /scripts/front/modified/scripts/directives/timepicker.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var TIME_REGEX = /^([0-5][0-9])\:([0-5][0-9])(?:\:([0-5][0-9]))?$/; 4 | angular.module('cdservice').directive('time', function($parse, dateFilter) { 5 | return { 6 | restrict : "E", 7 | replace : true, 8 | transclude : false, 9 | require: '?ngModel', 10 | compile : function(element, attrs) { 11 | var modelAccessor = $parse(attrs.ngModel); 12 | 13 | var isRequired = ""; 14 | if(attrs.required) { 15 | isRequired = "required"; 16 | } 17 | var html = ""; 18 | 19 | var $newElem = $(html); 20 | element.replaceWith($newElem); 21 | 22 | var nativeLinker = function(scope, element, attrs, ngModelCtrl) { 23 | if(!ngModelCtrl) return; 24 | 25 | var timeParser = function(value) { 26 | var date; 27 | if(value) { 28 | var d = value.match(TIME_REGEX); 29 | if(d) { 30 | date = new Date(0); 31 | if(!d[3]) { 32 | d[3] = "0"; 33 | } 34 | date.setHours(d[1], d[2], d[3]); 35 | } else { 36 | date = value; 37 | } 38 | } else { 39 | date = value; 40 | } 41 | return date; 42 | } 43 | var timeFormatter = function(value) { 44 | if(value) { 45 | var date = dateFilter(value,"HH:mm:ss"); 46 | return date; 47 | } 48 | return; 49 | } 50 | 51 | ngModelCtrl.$parsers.unshift(timeParser); 52 | ngModelCtrl.$formatters.unshift(timeFormatter); 53 | 54 | element.bind("blur keyup change", function() { 55 | scope.$apply(function() { 56 | ngModelCtrl.$setViewValue(element.val()); 57 | }); 58 | }); 59 | 60 | ngModelCtrl.$render = function() { 61 | element.val(ngModelCtrl.$viewValue); 62 | } 63 | } 64 | 65 | var enhancedLinker = function(scope, element, attrs, ngModelCtrl) { 66 | if(!ngModelCtrl) return; 67 | 68 | var timeParser = function(value) { 69 | if(value) { 70 | var d = value.match(TIME_REGEX); 71 | if(d) { 72 | var date = new Date(0); 73 | if(!d[3]) { 74 | d[3] = "0"; 75 | } 76 | date.setHours(d[1], d[2], d[3]); 77 | ngModelCtrl.$setValidity("timeFormat", true); 78 | return date; 79 | } else { 80 | ngModelCtrl.$setValidity("timeFormat", false); 81 | return; 82 | } 83 | } 84 | return; 85 | } 86 | var timeFormatter = function(value) { 87 | if(value) { 88 | var date = dateFilter(value,"HH:mm:ss"); 89 | return date; 90 | } 91 | return; 92 | } 93 | 94 | ngModelCtrl.$parsers.unshift(timeParser); 95 | ngModelCtrl.$formatters.unshift(timeFormatter); 96 | 97 | element.bind("blur keyup change", function() { 98 | scope.$apply(function() { 99 | ngModelCtrl.$setViewValue(element.val()); 100 | }); 101 | }); 102 | 103 | ngModelCtrl.$render = function() { 104 | element.val(ngModelCtrl.$viewValue); 105 | } 106 | } 107 | 108 | if(Modernizr.inputtypes["time"]) { 109 | return nativeLinker; 110 | } else { 111 | return enhancedLinker; 112 | } 113 | } 114 | } 115 | }); -------------------------------------------------------------------------------- /scripts/front/modified/scripts/filters/genericSearchFilter.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('cdservice').filter('searchFilter', function() { 4 | 5 | function matchObjectProperties(expectedObject, actualObject) { 6 | var flag = true; 7 | for(var key in expectedObject) { 8 | if(expectedObject.hasOwnProperty(key)) { 9 | var expectedProperty = expectedObject[key]; 10 | if (expectedProperty == null || expectedProperty === "") { 11 | continue; 12 | } 13 | var actualProperty = actualObject[key]; 14 | if (angular.isUndefined(actualProperty)) { 15 | continue; 16 | } 17 | if (actualProperty == null) { 18 | flag = false; 19 | } else if (angular.isObject(expectedProperty)) { 20 | flag = flag && matchObjectProperties(expectedProperty, actualProperty); 21 | } else { 22 | flag = flag && (actualProperty.toString().indexOf(expectedProperty.toString()) != -1); 23 | } 24 | } 25 | } 26 | return flag; 27 | } 28 | 29 | return function(results, scope) { 30 | 31 | scope.filteredResults = []; 32 | for (var ctr = 0; ctr < results.length; ctr++) { 33 | var flag = true; 34 | var searchCriteria = scope.search; 35 | var result = results[ctr]; 36 | for (var key in searchCriteria) { 37 | if (searchCriteria.hasOwnProperty(key)) { 38 | var expected = searchCriteria[key]; 39 | if (expected == null || expected === "") { 40 | continue; 41 | } 42 | var actual = result[key]; 43 | if (actual == null) { 44 | flag = false; 45 | } else if (angular.isObject(expected)) { 46 | flag = flag && matchObjectProperties(expected, actual); 47 | } else { 48 | flag = flag && (actual.toString().indexOf(expected.toString()) != -1); 49 | } 50 | } 51 | } 52 | if (flag == true) { 53 | scope.filteredResults.push(result); 54 | } 55 | } 56 | scope.numberOfPages(); 57 | return scope.filteredResults; 58 | }; 59 | }); 60 | -------------------------------------------------------------------------------- /scripts/front/modified/scripts/filters/startFromFilter.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('cdservice').filter('startFrom', function() { 4 | return function(input, start) { 5 | start = +start; //parse to int 6 | return input.slice(start); 7 | }; 8 | }); -------------------------------------------------------------------------------- /scripts/front/modified/scripts/offcanvas.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function() { 2 | $('[data-toggle=offcanvas]').click(function() { 3 | $('.row-offcanvas').toggleClass('active'); 4 | }); 5 | }); -------------------------------------------------------------------------------- /scripts/front/modified/scripts/services/CatalogFactory.js: -------------------------------------------------------------------------------- 1 | angular.module('cdservice').factory('CatalogResource', function ($resource, config) { 2 | return $resource(config.getApiUrl() + ':CatalogId', { CatalogId: '@id' }, { 3 | 'queryAll': { 4 | method: 'GET', 5 | isArray: true 6 | }, 'query': { method: 'GET', isArray: false }, 'update': { method: 'PUT' } 7 | }); 8 | }); -------------------------------------------------------------------------------- /scripts/front/modified/scripts/services/config.js: -------------------------------------------------------------------------------- 1 | angular.module('cdservice').factory('config', function ($http, $q) { 2 | var deferred = $q.defer(); 3 | var apiUrl = null; 4 | $http.get("service.json") 5 | .success(function (data) { 6 | console.log("Resource : " + data['cd-service'] + ':CatalogId'); 7 | deferred.resolve(data['cd-service']); 8 | apiUrl = data['cd-service']; 9 | }) 10 | .error(function () { 11 | deferred.reject('could not find service.json ....'); 12 | }); 13 | 14 | return { 15 | promise: deferred.promise, 16 | getApiUrl: function () { 17 | return apiUrl; 18 | } 19 | }; 20 | }); 21 | -------------------------------------------------------------------------------- /scripts/front/modified/scripts/services/flash.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('cdservice').factory('flash', ['$rootScope', function ($rootScope) { 4 | var messages = []; 5 | var currentMessage = {}; 6 | 7 | $rootScope.$on('$routeChangeSuccess', function() { 8 | currentMessage = messages.shift() || {}; 9 | }); 10 | 11 | return { 12 | getMessage: function () { 13 | return currentMessage; 14 | }, 15 | setMessage: function(message, pop) { 16 | switch(message.type) { 17 | case "error" : message.cssClass = "danger"; break; 18 | case "success" : message.cssClass = "success"; break; 19 | case "info" : message.cssClass = "info"; break; 20 | case "warning" : message.cssClass = "warning"; break; 21 | } 22 | messages.push(message); 23 | if(pop) { 24 | currentMessage = messages.shift() || {}; 25 | } 26 | } 27 | }; 28 | }]); 29 | -------------------------------------------------------------------------------- /scripts/front/modified/scripts/services/locationParser.js: -------------------------------------------------------------------------------- 1 | angular.module('cdservice').value('locationParser', function(responseHeaders){ 2 | // Get the Location header and parse it. 3 | var locationHeader = responseHeaders('Location'); 4 | var fragments = locationHeader.split('/'); 5 | var id = fragments[fragments.length -1]; 6 | return id; 7 | }); -------------------------------------------------------------------------------- /scripts/front/modified/scripts/vendor/modernizr-2.8.3.min.js: -------------------------------------------------------------------------------- 1 | /* Modernizr 2.8.3 (Custom Build) | MIT & BSD 2 | * Build: http://modernizr.com/download/#-fontface-backgroundsize-borderimage-borderradius-boxshadow-flexbox-flexboxlegacy-hsla-multiplebgs-opacity-rgba-textshadow-cssanimations-csscolumns-generatedcontent-cssgradients-cssreflections-csstransforms-csstransforms3d-csstransitions-canvas-canvastext-input-inputtypes-geolocation-inlinesvg-smil-svg-svgclippaths-touch-webgl-shiv-mq-cssclasses-teststyles-testprop-testallprops-hasevent-prefixes-domprefixes 3 | */ 4 | ;window.Modernizr=function(a,b,c){function D(a){j.cssText=a}function E(a,b){return D(n.join(a+";")+(b||""))}function F(a,b){return typeof a===b}function G(a,b){return!!~(""+a).indexOf(b)}function H(a,b){for(var d in a){var e=a[d];if(!G(e,"-")&&j[e]!==c)return b=="pfx"?e:!0}return!1}function I(a,b,d){for(var e in a){var f=b[a[e]];if(f!==c)return d===!1?a[e]:F(f,"function")?f.bind(d||b):f}return!1}function J(a,b,c){var d=a.charAt(0).toUpperCase()+a.slice(1),e=(a+" "+p.join(d+" ")+d).split(" ");return F(b,"string")||F(b,"undefined")?H(e,b):(e=(a+" "+q.join(d+" ")+d).split(" "),I(e,b,c))}function K(){e.input=function(c){for(var d=0,e=c.length;d',a,""].join(""),l.id=h,(m?l:n).innerHTML+=f,n.appendChild(l),m||(n.style.background="",n.style.overflow="hidden",k=g.style.overflow,g.style.overflow="hidden",g.appendChild(n)),i=c(l,a),m?l.parentNode.removeChild(l):(n.parentNode.removeChild(n),g.style.overflow=k),!!i},z=function(b){var c=a.matchMedia||a.msMatchMedia;if(c)return c(b)&&c(b).matches||!1;var d;return y("@media "+b+" { #"+h+" { position: absolute; } }",function(b){d=(a.getComputedStyle?getComputedStyle(b,null):b.currentStyle)["position"]=="absolute"}),d},A=function(){function d(d,e){e=e||b.createElement(a[d]||"div"),d="on"+d;var f=d in e;return f||(e.setAttribute||(e=b.createElement("div")),e.setAttribute&&e.removeAttribute&&(e.setAttribute(d,""),f=F(e[d],"function"),F(e[d],"undefined")||(e[d]=c),e.removeAttribute(d))),e=null,f}var a={select:"input",change:"input",submit:"form",reset:"form",error:"img",load:"img",abort:"img"};return d}(),B={}.hasOwnProperty,C;!F(B,"undefined")&&!F(B.call,"undefined")?C=function(a,b){return B.call(a,b)}:C=function(a,b){return b in a&&F(a.constructor.prototype[b],"undefined")},Function.prototype.bind||(Function.prototype.bind=function(b){var c=this;if(typeof c!="function")throw new TypeError;var d=w.call(arguments,1),e=function(){if(this instanceof e){var a=function(){};a.prototype=c.prototype;var f=new a,g=c.apply(f,d.concat(w.call(arguments)));return Object(g)===g?g:f}return c.apply(b,d.concat(w.call(arguments)))};return e}),s.flexbox=function(){return J("flexWrap")},s.flexboxlegacy=function(){return J("boxDirection")},s.canvas=function(){var a=b.createElement("canvas");return!!a.getContext&&!!a.getContext("2d")},s.canvastext=function(){return!!e.canvas&&!!F(b.createElement("canvas").getContext("2d").fillText,"function")},s.webgl=function(){return!!a.WebGLRenderingContext},s.touch=function(){var c;return"ontouchstart"in a||a.DocumentTouch&&b instanceof DocumentTouch?c=!0:y(["@media (",n.join("touch-enabled),("),h,")","{#modernizr{top:9px;position:absolute}}"].join(""),function(a){c=a.offsetTop===9}),c},s.geolocation=function(){return"geolocation"in navigator},s.rgba=function(){return D("background-color:rgba(150,255,150,.5)"),G(j.backgroundColor,"rgba")},s.hsla=function(){return D("background-color:hsla(120,40%,100%,.5)"),G(j.backgroundColor,"rgba")||G(j.backgroundColor,"hsla")},s.multiplebgs=function(){return D("background:url(https://),url(https://),red url(https://)"),/(url\s*\(.*?){3}/.test(j.background)},s.backgroundsize=function(){return J("backgroundSize")},s.borderimage=function(){return J("borderImage")},s.borderradius=function(){return J("borderRadius")},s.boxshadow=function(){return J("boxShadow")},s.textshadow=function(){return b.createElement("div").style.textShadow===""},s.opacity=function(){return E("opacity:.55"),/^0.55$/.test(j.opacity)},s.cssanimations=function(){return J("animationName")},s.csscolumns=function(){return J("columnCount")},s.cssgradients=function(){var a="background-image:",b="gradient(linear,left top,right bottom,from(#9f9),to(white));",c="linear-gradient(left top,#9f9, white);";return D((a+"-webkit- ".split(" ").join(b+a)+n.join(c+a)).slice(0,-a.length)),G(j.backgroundImage,"gradient")},s.cssreflections=function(){return J("boxReflect")},s.csstransforms=function(){return!!J("transform")},s.csstransforms3d=function(){var a=!!J("perspective");return a&&"webkitPerspective"in g.style&&y("@media (transform-3d),(-webkit-transform-3d){#modernizr{left:9px;position:absolute;height:3px;}}",function(b,c){a=b.offsetLeft===9&&b.offsetHeight===3}),a},s.csstransitions=function(){return J("transition")},s.fontface=function(){var a;return y('@font-face {font-family:"font";src:url("https://")}',function(c,d){var e=b.getElementById("smodernizr"),f=e.sheet||e.styleSheet,g=f?f.cssRules&&f.cssRules[0]?f.cssRules[0].cssText:f.cssText||"":"";a=/src/i.test(g)&&g.indexOf(d.split(" ")[0])===0}),a},s.generatedcontent=function(){var a;return y(["#",h,"{font:0/0 a}#",h,':after{content:"',l,'";visibility:hidden;font:3px/1 a}'].join(""),function(b){a=b.offsetHeight>=3}),a},s.svg=function(){return!!b.createElementNS&&!!b.createElementNS(r.svg,"svg").createSVGRect},s.inlinesvg=function(){var a=b.createElement("div");return a.innerHTML="",(a.firstChild&&a.firstChild.namespaceURI)==r.svg},s.smil=function(){return!!b.createElementNS&&/SVGAnimate/.test(m.call(b.createElementNS(r.svg,"animate")))},s.svgclippaths=function(){return!!b.createElementNS&&/SVGClipPath/.test(m.call(b.createElementNS(r.svg,"clipPath")))};for(var L in s)C(s,L)&&(x=L.toLowerCase(),e[x]=s[L](),v.push((e[x]?"":"no-")+x));return e.input||K(),e.addTest=function(a,b){if(typeof a=="object")for(var d in a)C(a,d)&&e.addTest(d,a[d]);else{a=a.toLowerCase();if(e[a]!==c)return e;b=typeof b=="function"?b():b,typeof f!="undefined"&&f&&(g.className+=" "+(b?"":"no-")+a),e[a]=b}return e},D(""),i=k=null,function(a,b){function l(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x",d.insertBefore(c.lastChild,d.firstChild)}function m(){var a=s.elements;return typeof a=="string"?a.split(" "):a}function n(a){var b=j[a[h]];return b||(b={},i++,a[h]=i,j[i]=b),b}function o(a,c,d){c||(c=b);if(k)return c.createElement(a);d||(d=n(c));var g;return d.cache[a]?g=d.cache[a].cloneNode():f.test(a)?g=(d.cache[a]=d.createElem(a)).cloneNode():g=d.createElem(a),g.canHaveChildren&&!e.test(a)&&!g.tagUrn?d.frag.appendChild(g):g}function p(a,c){a||(a=b);if(k)return a.createDocumentFragment();c=c||n(a);var d=c.frag.cloneNode(),e=0,f=m(),g=f.length;for(;e",g="hidden"in a,k=a.childNodes.length==1||function(){b.createElement("a");var a=b.createDocumentFragment();return typeof a.cloneNode=="undefined"||typeof a.createDocumentFragment=="undefined"||typeof a.createElement=="undefined"}()}catch(c){g=!0,k=!0}})();var s={elements:d.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output progress section summary template time video",version:c,shivCSS:d.shivCSS!==!1,supportsUnknownElements:k,shivMethods:d.shivMethods!==!1,type:"default",shivDocument:r,createElement:o,createDocumentFragment:p};a.html5=s,r(b)}(this,b),e._version=d,e._prefixes=n,e._domPrefixes=q,e._cssomPrefixes=p,e.mq=z,e.hasEvent=A,e.testProp=function(a){return H([a])},e.testAllProps=J,e.testStyles=y,g.className=g.className.replace(/(^|\s)no-js(\s|$)/,"$1$2")+(f?" js "+v.join(" "):""),e}(this,this.document); -------------------------------------------------------------------------------- /scripts/front/modified/service.json: -------------------------------------------------------------------------------- 1 | { "cd-service": "http://localhost:8080/rest/catalogs/" } -------------------------------------------------------------------------------- /scripts/front/modified/styles/main.css: -------------------------------------------------------------------------------- 1 | @CHARSET "UTF-8"; 2 | 3 | /* Sticky footer styles 4 | -------------------------------------------------- */ 5 | 6 | html, body { 7 | height: 100%; 8 | /* The html and body elements cannot have any padding or margin. */ 9 | } 10 | 11 | /* Wrapper for page content to push down footer */ 12 | #wrap { 13 | min-height: 100%; 14 | height: auto; 15 | /* Negative indent footer by it's height */ 16 | margin: 0 auto -60px; 17 | /* Pad bottom by footer height */ 18 | padding: 0 0 60px; 19 | } 20 | 21 | #wrap > .container { 22 | padding-top: 50px; 23 | } 24 | 25 | /* Set the fixed height of the footer here */ 26 | #footer { 27 | height: 60px; 28 | } 29 | 30 | #footer { 31 | background-color: #F5F5F5; 32 | text-align: center; 33 | border-top: 1px solid #E5E5E5; 34 | } 35 | 36 | h2 i.icon-check { 37 | vertical-align: middle; 38 | } 39 | 40 | table { 41 | table-layout: fixed; 42 | word-wrap: break-word; 43 | } 44 | 45 | /* Lastly, apply responsive CSS fixes as necessary */ 46 | @media (max-width: 767px) { 47 | table { 48 | table-layout: auto; 49 | } 50 | .row-offcanvas { 51 | position: relative; 52 | transition: all 0.25s ease-out; 53 | } 54 | .row-offcanvas-left .sidebar-offcanvas { 55 | display:none; 56 | } 57 | .row-offcanvas-left.active .sidebar-offcanvas { 58 | display:inherit; 59 | } 60 | .row-offcanvas-left.active .mainarea { 61 | display:none; 62 | } 63 | .sidebar-offcanvas { 64 | position: absolute; 65 | top: 0; 66 | width: 100%; 67 | } 68 | } -------------------------------------------------------------------------------- /scripts/front/modified/views/Catalog/detail.html: -------------------------------------------------------------------------------- 1 |
2 |

Create a new Catalog

3 |

View or edit Catalog

4 |
5 |
6 | 7 | 8 |
9 | 10 |
11 | 12 |
13 |
14 | 15 |
16 | 17 |
18 | 19 |
20 |
21 | 22 |
23 | 24 |
25 | 26 | maximum length is 2000 27 |
28 |
29 | 30 |
31 | 32 |
33 | 34 | not a number 35 |
36 |
37 | 38 |
39 | 40 |
41 | 42 | does not match format "yyyy-MM-dd hh:mm:ss" (e.g. 2013-12-01 22:00:00) 43 |
44 |
45 | 46 | 47 |
48 |
49 | 50 | 51 | 52 |
53 |
54 |
-------------------------------------------------------------------------------- /scripts/front/modified/views/Catalog/search.html: -------------------------------------------------------------------------------- 1 |
2 |

Create a new Catalog

3 |
4 |
5 | Create 6 |
7 |
8 |
9 |
10 |
11 |

Search for Catalogs

12 |
13 | 14 | 15 |
16 | 17 |
18 | 19 |
20 |
21 | 22 |
23 | 24 |
25 | 26 |
27 |
28 | 29 |
30 | 31 |
32 | 33 |
34 |
35 | 36 |
37 | 38 |
39 | 40 |
41 |
42 | 43 | 44 | 45 |
46 |
47 | Search 48 |
49 |
50 |
51 |
52 |
53 |
54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 |
ArtistTitleDescriptionPricePublication Date
{{result.artist}}{{result.title}}{{result.description}}{{result.price}}{{result.publicationDate| date:'yyyy-MM-dd HH:mm:ss Z'}}
74 |
75 | 76 |
    77 |
  • 78 | 79 |
  • 80 |
  • 81 | 1 82 |
  • 83 |
  • 84 | 85 |
  • 86 |
87 | 88 |
-------------------------------------------------------------------------------- /scripts/front/modified/views/landing.html: -------------------------------------------------------------------------------- 1 |

2 | Your application is running. 3 |

4 |

5 | Documentation 7 | | Get Excited!

9 | Forge Project
| User 11 | Forums | Report an issue 13 |

-------------------------------------------------------------------------------- /scripts/load_and_break_service.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | export ENDPOINT=http://cdservice-workshop.$(minishift ip).nip.io 4 | for i in `seq 1 1500` 5 | do 6 | curl $ENDPOINT/rest/catalogs >/dev/null 2>/dev/null 7 | 8 | if (( $i % 5 == 0 )) 9 | then 10 | echo -n "." 11 | fi 12 | 13 | if (( $i % 250 == 0 )) 14 | then 15 | echo " " 16 | fi 17 | 18 | if (( $i == 250 )) 19 | then 20 | echo "Bring DB down" 21 | oc scale --replicas=0 dc mysql 22 | else 23 | if (( $i == 500 )) 24 | then 25 | echo "Restore DB" 26 | oc scale --replicas=1 dc mysql 27 | fi 28 | fi 29 | done 30 | echo " " -------------------------------------------------------------------------------- /scripts/service/CatalogEndpointCB.java: -------------------------------------------------------------------------------- 1 | package org.cdservice.rest; 2 | 3 | import java.util.Collections; 4 | import java.util.List; 5 | 6 | import javax.persistence.EntityManager; 7 | import javax.persistence.NoResultException; 8 | import javax.persistence.OptimisticLockException; 9 | import javax.persistence.PersistenceContext; 10 | import javax.persistence.TypedQuery; 11 | import javax.ws.rs.Consumes; 12 | import javax.ws.rs.DELETE; 13 | import javax.ws.rs.GET; 14 | import javax.ws.rs.POST; 15 | import javax.ws.rs.PUT; 16 | import javax.ws.rs.Path; 17 | import javax.ws.rs.PathParam; 18 | import javax.ws.rs.Produces; 19 | import javax.ws.rs.QueryParam; 20 | import javax.ws.rs.core.Response; 21 | import javax.ws.rs.core.Response.Status; 22 | import javax.ws.rs.core.UriBuilder; 23 | 24 | import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand; 25 | import org.springframework.stereotype.Component; 26 | import org.springframework.transaction.annotation.Transactional; 27 | import org.cdservice.model.Catalog; 28 | 29 | /** 30 | * 31 | */ 32 | @Path("/catalogs") 33 | @Component 34 | //@Transactional 35 | public class CatalogEndpoint { 36 | @PersistenceContext 37 | private EntityManager em; 38 | 39 | @POST 40 | @Consumes("application/json") 41 | public Response create(Catalog entity) { 42 | em.persist(entity); 43 | return Response.created( 44 | UriBuilder.fromResource(CatalogEndpoint.class) 45 | .path(String.valueOf(entity.getId())).build()).build(); 46 | } 47 | 48 | @DELETE 49 | @Path("/{id:[0-9][0-9]*}") 50 | public Response deleteById(@PathParam("id") Long id) { 51 | Catalog entity = em.find(Catalog.class, id); 52 | if (entity == null) { 53 | return Response.status(Status.NOT_FOUND).build(); 54 | } 55 | em.remove(entity); 56 | return Response.noContent().build(); 57 | } 58 | 59 | @GET 60 | @Path("/{id:[0-9][0-9]*}") 61 | @Produces("application/json") 62 | public Response findById(@PathParam("id") Long id) { 63 | TypedQuery findByIdQuery = em 64 | .createQuery( 65 | "SELECT DISTINCT c FROM Catalog c WHERE c.id = :entityId ORDER BY c.id", 66 | Catalog.class); 67 | findByIdQuery.setParameter("entityId", id); 68 | Catalog entity; 69 | try { 70 | entity = findByIdQuery.getSingleResult(); 71 | } catch (NoResultException nre) { 72 | entity = null; 73 | } 74 | if (entity == null) { 75 | return Response.status(Status.NOT_FOUND).build(); 76 | } 77 | return Response.ok(entity).build(); 78 | } 79 | 80 | @GET 81 | @Produces("application/json") 82 | @HystrixCommand(groupKey = "CatalogGroup", fallbackMethod = "getFallback") 83 | public List listAll(@QueryParam("start") Integer startPosition, @QueryParam("max") Integer maxResult) { 84 | TypedQuery findAllQuery = em 85 | .createQuery("SELECT DISTINCT c FROM Catalog c ORDER BY c.id", Catalog.class); 86 | if (startPosition != null) { 87 | findAllQuery.setFirstResult(startPosition); 88 | } 89 | if (maxResult != null) { 90 | findAllQuery.setMaxResults(maxResult); 91 | } 92 | return findAllQuery.getResultList(); 93 | } 94 | 95 | public List getFallback(Integer StartPosition, Integer maxResult) { 96 | Catalog catalog = new Catalog(); 97 | catalog.setArtist("Fallback"); 98 | catalog.setTitle("Circuit breaker is open as the DB is down !"); 99 | return Collections.singletonList(catalog); 100 | } 101 | 102 | @PUT 103 | @Path("/{id:[0-9][0-9]*}") 104 | @Consumes("application/json") 105 | public Response update(@PathParam("id") Long id, Catalog entity) { 106 | if (entity == null) { 107 | return Response.status(Status.BAD_REQUEST).build(); 108 | } 109 | if (id == null) { 110 | return Response.status(Status.BAD_REQUEST).build(); 111 | } 112 | if (!id.equals(entity.getId())) { 113 | return Response.status(Status.CONFLICT).entity(entity).build(); 114 | } 115 | if (em.find(Catalog.class, id) == null) { 116 | return Response.status(Status.NOT_FOUND).build(); 117 | } 118 | try { 119 | entity = em.merge(entity); 120 | } catch (OptimisticLockException e) { 121 | return Response.status(Response.Status.CONFLICT) 122 | .entity(e.getEntity()).build(); 123 | } 124 | 125 | return Response.noContent().build(); 126 | } 127 | } -------------------------------------------------------------------------------- /scripts/service/data-h2.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO Catalog (id, version, artist, description, price, publication_date, title) VALUES (1001, 1, 'ACDC', 'Australian hard rock band', 15.0, '1980-07-25', 'Back in Black'); 2 | INSERT INTO Catalog (id, version, artist, description, price, publication_date, title) VALUES (1002, 1, 'Abba', 'Swedish pop music group', 12.0, '1976-10-11', 'Arrival'); 3 | INSERT INTO Catalog (id, version, artist, description, price, publication_date, title) VALUES (1003, 1, 'Coldplay', 'British rock band ', 17.0, '2008-07-12', 'Viva la Vida'); 4 | INSERT INTO Catalog (id, version, artist, description, price, publication_date, title) VALUES (1004, 1, 'U2', 'Irish rock band ', 18.0, '1987-03-09', 'The Joshua Tree'); 5 | INSERT INTO Catalog (id, version, artist, description, price, publication_date, title) VALUES (1005, 1, 'Metallica', 'Heavy metal band', 15.0, '1991-08-12', 'Black'); -------------------------------------------------------------------------------- /solution/cdfront/mvnw: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # ---------------------------------------------------------------------------- 3 | # Licensed to the Apache Software Foundation (ASF) under one 4 | # or more contributor license agreements. See the NOTICE file 5 | # distributed with this work for additional information 6 | # regarding copyright ownership. The ASF licenses this file 7 | # to you under the Apache License, Version 2.0 (the 8 | # "License"); you may not use this file except in compliance 9 | # with the License. You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, 14 | # software distributed under the License is distributed on an 15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | # KIND, either express or implied. See the License for the 17 | # specific language governing permissions and limitations 18 | # under the License. 19 | # ---------------------------------------------------------------------------- 20 | 21 | # ---------------------------------------------------------------------------- 22 | # Maven2 Start Up Batch script 23 | # 24 | # Required ENV vars: 25 | # ------------------ 26 | # JAVA_HOME - location of a JDK home dir 27 | # 28 | # Optional ENV vars 29 | # ----------------- 30 | # M2_HOME - location of maven2's installed home dir 31 | # MAVEN_OPTS - parameters passed to the Java VM when running Maven 32 | # e.g. to debug Maven itself, use 33 | # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 34 | # MAVEN_SKIP_RC - flag to disable loading of mavenrc files 35 | # ---------------------------------------------------------------------------- 36 | 37 | if [ -z "$MAVEN_SKIP_RC" ] ; then 38 | 39 | if [ -f /etc/mavenrc ] ; then 40 | . /etc/mavenrc 41 | fi 42 | 43 | if [ -f "$HOME/.mavenrc" ] ; then 44 | . "$HOME/.mavenrc" 45 | fi 46 | 47 | fi 48 | 49 | # OS specific support. $var _must_ be set to either true or false. 50 | cygwin=false; 51 | darwin=false; 52 | mingw=false 53 | case "`uname`" in 54 | CYGWIN*) cygwin=true ;; 55 | MINGW*) mingw=true;; 56 | Darwin*) darwin=true 57 | # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home 58 | # See https://developer.apple.com/library/mac/qa/qa1170/_index.html 59 | if [ -z "$JAVA_HOME" ]; then 60 | if [ -x "/usr/libexec/java_home" ]; then 61 | export JAVA_HOME="`/usr/libexec/java_home`" 62 | else 63 | export JAVA_HOME="/Library/Java/Home" 64 | fi 65 | fi 66 | ;; 67 | esac 68 | 69 | if [ -z "$JAVA_HOME" ] ; then 70 | if [ -r /etc/gentoo-release ] ; then 71 | JAVA_HOME=`java-config --jre-home` 72 | fi 73 | fi 74 | 75 | if [ -z "$M2_HOME" ] ; then 76 | ## resolve links - $0 may be a link to maven's home 77 | PRG="$0" 78 | 79 | # need this for relative symlinks 80 | while [ -h "$PRG" ] ; do 81 | ls=`ls -ld "$PRG"` 82 | link=`expr "$ls" : '.*-> \(.*\)$'` 83 | if expr "$link" : '/.*' > /dev/null; then 84 | PRG="$link" 85 | else 86 | PRG="`dirname "$PRG"`/$link" 87 | fi 88 | done 89 | 90 | saveddir=`pwd` 91 | 92 | M2_HOME=`dirname "$PRG"`/.. 93 | 94 | # make it fully qualified 95 | M2_HOME=`cd "$M2_HOME" && pwd` 96 | 97 | cd "$saveddir" 98 | # echo Using m2 at $M2_HOME 99 | fi 100 | 101 | # For Cygwin, ensure paths are in UNIX format before anything is touched 102 | if $cygwin ; then 103 | [ -n "$M2_HOME" ] && 104 | M2_HOME=`cygpath --unix "$M2_HOME"` 105 | [ -n "$JAVA_HOME" ] && 106 | JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 107 | [ -n "$CLASSPATH" ] && 108 | CLASSPATH=`cygpath --path --unix "$CLASSPATH"` 109 | fi 110 | 111 | # For Migwn, ensure paths are in UNIX format before anything is touched 112 | if $mingw ; then 113 | [ -n "$M2_HOME" ] && 114 | M2_HOME="`(cd "$M2_HOME"; pwd)`" 115 | [ -n "$JAVA_HOME" ] && 116 | JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" 117 | # TODO classpath? 118 | fi 119 | 120 | if [ -z "$JAVA_HOME" ]; then 121 | javaExecutable="`which javac`" 122 | if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then 123 | # readlink(1) is not available as standard on Solaris 10. 124 | readLink=`which readlink` 125 | if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then 126 | if $darwin ; then 127 | javaHome="`dirname \"$javaExecutable\"`" 128 | javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" 129 | else 130 | javaExecutable="`readlink -f \"$javaExecutable\"`" 131 | fi 132 | javaHome="`dirname \"$javaExecutable\"`" 133 | javaHome=`expr "$javaHome" : '\(.*\)/bin'` 134 | JAVA_HOME="$javaHome" 135 | export JAVA_HOME 136 | fi 137 | fi 138 | fi 139 | 140 | if [ -z "$JAVACMD" ] ; then 141 | if [ -n "$JAVA_HOME" ] ; then 142 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 143 | # IBM's JDK on AIX uses strange locations for the executables 144 | JAVACMD="$JAVA_HOME/jre/sh/java" 145 | else 146 | JAVACMD="$JAVA_HOME/bin/java" 147 | fi 148 | else 149 | JAVACMD="`which java`" 150 | fi 151 | fi 152 | 153 | if [ ! -x "$JAVACMD" ] ; then 154 | echo "Error: JAVA_HOME is not defined correctly." >&2 155 | echo " We cannot execute $JAVACMD" >&2 156 | exit 1 157 | fi 158 | 159 | if [ -z "$JAVA_HOME" ] ; then 160 | echo "Warning: JAVA_HOME environment variable is not set." 161 | fi 162 | 163 | CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher 164 | 165 | # traverses directory structure from process work directory to filesystem root 166 | # first directory with .mvn subdirectory is considered project base directory 167 | find_maven_basedir() { 168 | 169 | if [ -z "$1" ] 170 | then 171 | echo "Path not specified to find_maven_basedir" 172 | return 1 173 | fi 174 | 175 | basedir="$1" 176 | wdir="$1" 177 | while [ "$wdir" != '/' ] ; do 178 | if [ -d "$wdir"/.mvn ] ; then 179 | basedir=$wdir 180 | break 181 | fi 182 | # workaround for JBEAP-8937 (on Solaris 10/Sparc) 183 | if [ -d "${wdir}" ]; then 184 | wdir=`cd "$wdir/.."; pwd` 185 | fi 186 | # end of workaround 187 | done 188 | echo "${basedir}" 189 | } 190 | 191 | # concatenates all lines of a file 192 | concat_lines() { 193 | if [ -f "$1" ]; then 194 | echo "$(tr -s '\n' ' ' < "$1")" 195 | fi 196 | } 197 | 198 | BASE_DIR=`find_maven_basedir "$(pwd)"` 199 | if [ -z "$BASE_DIR" ]; then 200 | exit 1; 201 | fi 202 | 203 | export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} 204 | echo $MAVEN_PROJECTBASEDIR 205 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" 206 | 207 | # For Cygwin, switch paths to Windows format before running java 208 | if $cygwin; then 209 | [ -n "$M2_HOME" ] && 210 | M2_HOME=`cygpath --path --windows "$M2_HOME"` 211 | [ -n "$JAVA_HOME" ] && 212 | JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` 213 | [ -n "$CLASSPATH" ] && 214 | CLASSPATH=`cygpath --path --windows "$CLASSPATH"` 215 | [ -n "$MAVEN_PROJECTBASEDIR" ] && 216 | MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` 217 | fi 218 | 219 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 220 | 221 | exec "$JAVACMD" \ 222 | $MAVEN_OPTS \ 223 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ 224 | "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ 225 | ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" 226 | -------------------------------------------------------------------------------- /solution/cdfront/mvnw.cmd: -------------------------------------------------------------------------------- 1 | @REM ---------------------------------------------------------------------------- 2 | @REM Licensed to the Apache Software Foundation (ASF) under one 3 | @REM or more contributor license agreements. See the NOTICE file 4 | @REM distributed with this work for additional information 5 | @REM regarding copyright ownership. The ASF licenses this file 6 | @REM to you under the Apache License, Version 2.0 (the 7 | @REM "License"); you may not use this file except in compliance 8 | @REM with the License. You may obtain a copy of the License at 9 | @REM 10 | @REM http://www.apache.org/licenses/LICENSE-2.0 11 | @REM 12 | @REM Unless required by applicable law or agreed to in writing, 13 | @REM software distributed under the License is distributed on an 14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | @REM KIND, either express or implied. See the License for the 16 | @REM specific language governing permissions and limitations 17 | @REM under the License. 18 | @REM ---------------------------------------------------------------------------- 19 | 20 | @REM ---------------------------------------------------------------------------- 21 | @REM Maven2 Start Up Batch script 22 | @REM 23 | @REM Required ENV vars: 24 | @REM JAVA_HOME - location of a JDK home dir 25 | @REM 26 | @REM Optional ENV vars 27 | @REM M2_HOME - location of maven2's installed home dir 28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands 29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending 30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven 31 | @REM e.g. to debug Maven itself, use 32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files 34 | @REM ---------------------------------------------------------------------------- 35 | 36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' 37 | @echo off 38 | @REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' 39 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% 40 | 41 | @REM set %HOME% to equivalent of $HOME 42 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") 43 | 44 | @REM Execute a user defined script before this one 45 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre 46 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending 47 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" 48 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" 49 | :skipRcPre 50 | 51 | @setlocal 52 | 53 | set ERROR_CODE=0 54 | 55 | @REM To isolate internal variables from possible post scripts, we use another setlocal 56 | @setlocal 57 | 58 | @REM ==== START VALIDATION ==== 59 | if not "%JAVA_HOME%" == "" goto OkJHome 60 | 61 | echo. 62 | echo Error: JAVA_HOME not found in your environment. >&2 63 | echo Please set the JAVA_HOME variable in your environment to match the >&2 64 | echo location of your Java installation. >&2 65 | echo. 66 | goto error 67 | 68 | :OkJHome 69 | if exist "%JAVA_HOME%\bin\java.exe" goto init 70 | 71 | echo. 72 | echo Error: JAVA_HOME is set to an invalid directory. >&2 73 | echo JAVA_HOME = "%JAVA_HOME%" >&2 74 | echo Please set the JAVA_HOME variable in your environment to match the >&2 75 | echo location of your Java installation. >&2 76 | echo. 77 | goto error 78 | 79 | @REM ==== END VALIDATION ==== 80 | 81 | :init 82 | 83 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn". 84 | @REM Fallback to current working directory if not found. 85 | 86 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% 87 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir 88 | 89 | set EXEC_DIR=%CD% 90 | set WDIR=%EXEC_DIR% 91 | :findBaseDir 92 | IF EXIST "%WDIR%"\.mvn goto baseDirFound 93 | cd .. 94 | IF "%WDIR%"=="%CD%" goto baseDirNotFound 95 | set WDIR=%CD% 96 | goto findBaseDir 97 | 98 | :baseDirFound 99 | set MAVEN_PROJECTBASEDIR=%WDIR% 100 | cd "%EXEC_DIR%" 101 | goto endDetectBaseDir 102 | 103 | :baseDirNotFound 104 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR% 105 | cd "%EXEC_DIR%" 106 | 107 | :endDetectBaseDir 108 | 109 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig 110 | 111 | @setlocal EnableExtensions EnableDelayedExpansion 112 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a 113 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% 114 | 115 | :endReadAdditionalConfig 116 | 117 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" 118 | 119 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" 120 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 121 | 122 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* 123 | if ERRORLEVEL 1 goto error 124 | goto end 125 | 126 | :error 127 | set ERROR_CODE=1 128 | 129 | :end 130 | @endlocal & set ERROR_CODE=%ERROR_CODE% 131 | 132 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost 133 | @REM check for post script, once with legacy .bat ending and once with .cmd ending 134 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" 135 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" 136 | :skipRcPost 137 | 138 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' 139 | if "%MAVEN_BATCH_PAUSE%" == "on" pause 140 | 141 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% 142 | 143 | exit /B %ERROR_CODE% 144 | -------------------------------------------------------------------------------- /solution/cdfront/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | org.cdfront 6 | cdfront 7 | 1.0.0-SNAPSHOT 8 | jar 9 | 10 | demo 11 | Demo project for Spring Boot 12 | 13 | 14 | org.springframework.boot 15 | spring-boot-starter-parent 16 | 1.5.3.RELEASE 17 | 18 | 19 | 20 | UTF-8 21 | UTF-8 22 | 1.8 23 | 24 | 25 | 26 | 27 | org.springframework.boot 28 | spring-boot-starter 29 | 30 | 31 | 32 | org.springframework.boot 33 | spring-boot-starter-test 34 | test 35 | 36 | 37 | 38 | org.springframework.boot 39 | spring-boot-starter-web 40 | 41 | 42 | 43 | 44 | 45 | 46 | org.springframework.boot 47 | spring-boot-maven-plugin 48 | 49 | 50 | io.fabric8 51 | fabric8-maven-plugin 52 | 3.2.9 53 | 54 | 55 | fmp 56 | 57 | resource 58 | helm 59 | build 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /solution/cdfront/src/main/fabric8/route.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Route 3 | metadata: 4 | name: ${project.artifactId} 5 | spec: 6 | port: 7 | targetPort: 8081 8 | to: 9 | kind: Service 10 | name: ${project.artifactId} 11 | -------------------------------------------------------------------------------- /solution/cdfront/src/main/fabric8/svc.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: ${project.artifactId} 5 | spec: 6 | ports: 7 | - protocol: TCP 8 | port: 8080 9 | targetPort: 8081 10 | type: ClusterIP 11 | -------------------------------------------------------------------------------- /solution/cdfront/src/main/java/org/cdfront/DemoApplication.java: -------------------------------------------------------------------------------- 1 | package org.cdfront; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.boot.builder.SpringApplicationBuilder; 6 | import org.springframework.boot.web.support.SpringBootServletInitializer; 7 | 8 | @SpringBootApplication 9 | public class DemoApplication extends SpringBootServletInitializer { 10 | 11 | public static void main(String[] args) { 12 | SpringApplication.run(DemoApplication.class, args); 13 | } 14 | 15 | @Override 16 | protected SpringApplicationBuilder configure( 17 | SpringApplicationBuilder application) { 18 | return application.sources(DemoApplication.class); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /solution/cdfront/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | #Tue Jun 13 16:00:58 CEST 2017 2 | server.port=8081 3 | -------------------------------------------------------------------------------- /solution/cdfront/src/main/resources/static/app.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Cdservice 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 27 | 28 |
29 |
30 | 31 | 41 | 42 |
43 | 47 |
48 |
49 |
50 |
51 |
52 |
53 | 54 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /solution/cdfront/src/main/resources/static/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redhat-microservices/lab_springboot-openshift/ee23e2cf97de151b437237eb9683ac9c26597493/solution/cdfront/src/main/resources/static/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /solution/cdfront/src/main/resources/static/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redhat-microservices/lab_springboot-openshift/ee23e2cf97de151b437237eb9683ac9c26597493/solution/cdfront/src/main/resources/static/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /solution/cdfront/src/main/resources/static/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redhat-microservices/lab_springboot-openshift/ee23e2cf97de151b437237eb9683ac9c26597493/solution/cdfront/src/main/resources/static/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /solution/cdfront/src/main/resources/static/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redhat-microservices/lab_springboot-openshift/ee23e2cf97de151b437237eb9683ac9c26597493/solution/cdfront/src/main/resources/static/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /solution/cdfront/src/main/resources/static/img/forge-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redhat-microservices/lab_springboot-openshift/ee23e2cf97de151b437237eb9683ac9c26597493/solution/cdfront/src/main/resources/static/img/forge-logo.png -------------------------------------------------------------------------------- /solution/cdfront/src/main/resources/static/index.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /solution/cdfront/src/main/resources/static/scripts/app.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('cdservice',['ngRoute','ngResource']) 4 | .config(['$routeProvider', function($routeProvider) { 5 | $routeProvider 6 | .when('/',{templateUrl:'views/landing.html',controller:'LandingPageController'}) 7 | .when('/Catalogs', 8 | { 9 | templateUrl:'views/Catalog/search.html', 10 | controller:'SearchCatalogController', 11 | resolve: { 12 | apiUrl: function(config) { 13 | return config.promise; 14 | } 15 | } 16 | }) 17 | .when('/Catalogs/new',{templateUrl:'views/Catalog/detail.html',controller:'NewCatalogController'}) 18 | .when('/Catalogs/edit/:CatalogId',{templateUrl:'views/Catalog/detail.html',controller:'EditCatalogController'}) 19 | .otherwise({ 20 | redirectTo: '/' 21 | }); 22 | }]) 23 | .controller('LandingPageController', function LandingPageController() { 24 | }) 25 | .controller('NavController', function NavController($scope, $location) { 26 | $scope.matchesRoute = function(route) { 27 | var path = $location.path(); 28 | return (path === ("/" + route) || path.indexOf("/" + route + "/") == 0); 29 | }; 30 | }); 31 | -------------------------------------------------------------------------------- /solution/cdfront/src/main/resources/static/scripts/controllers/editCatalogController.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | angular.module('cdservice').controller('EditCatalogController', function($scope, $routeParams, $location, flash, CatalogResource ) { 4 | var self = this; 5 | $scope.disabled = false; 6 | $scope.$location = $location; 7 | 8 | $scope.get = function() { 9 | var successCallback = function(data){ 10 | self.original = data; 11 | $scope.catalog = new CatalogResource(self.original); 12 | }; 13 | var errorCallback = function() { 14 | flash.setMessage({'type': 'error', 'text': 'The catalog could not be found.'}); 15 | $location.path("/Catalogs"); 16 | }; 17 | CatalogResource.get({CatalogId:$routeParams.CatalogId}, successCallback, errorCallback); 18 | }; 19 | 20 | $scope.isClean = function() { 21 | return angular.equals(self.original, $scope.catalog); 22 | }; 23 | 24 | $scope.save = function() { 25 | var successCallback = function(){ 26 | flash.setMessage({'type':'success','text':'The catalog was updated successfully.'}, true); 27 | $scope.get(); 28 | }; 29 | var errorCallback = function(response) { 30 | if(response && response.data && response.data.message) { 31 | flash.setMessage({'type': 'error', 'text': response.data.message}, true); 32 | } else { 33 | flash.setMessage({'type': 'error', 'text': 'Something broke. Retry, or cancel and start afresh.'}, true); 34 | } 35 | }; 36 | $scope.catalog.$update(successCallback, errorCallback); 37 | }; 38 | 39 | $scope.cancel = function() { 40 | $location.path("/Catalogs"); 41 | }; 42 | 43 | $scope.remove = function() { 44 | var successCallback = function() { 45 | flash.setMessage({'type': 'error', 'text': 'The catalog was deleted.'}); 46 | $location.path("/Catalogs"); 47 | }; 48 | var errorCallback = function(response) { 49 | if(response && response.data && response.data.message) { 50 | flash.setMessage({'type': 'error', 'text': response.data.message}, true); 51 | } else { 52 | flash.setMessage({'type': 'error', 'text': 'Something broke. Retry, or cancel and start afresh.'}, true); 53 | } 54 | }; 55 | $scope.catalog.$remove(successCallback, errorCallback); 56 | }; 57 | 58 | 59 | $scope.get(); 60 | }); -------------------------------------------------------------------------------- /solution/cdfront/src/main/resources/static/scripts/controllers/flashController.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('cdservice').controller('FlashController', ['$scope','flash', function ($scope, flash) { 4 | $scope.flash = flash; 5 | $scope.showAlert = false; 6 | 7 | $scope.$watch('flash.getMessage()', function(newVal) { 8 | var message = newVal; 9 | if(message && message.text) { 10 | $scope.showAlert = message.text.length > 0; 11 | } else { 12 | $scope.showAlert = false; 13 | } 14 | }); 15 | 16 | $scope.hideAlert = function() { 17 | $scope.showAlert = false; 18 | } 19 | }]); 20 | -------------------------------------------------------------------------------- /solution/cdfront/src/main/resources/static/scripts/controllers/newCatalogController.js: -------------------------------------------------------------------------------- 1 | 2 | angular.module('cdservice').controller('NewCatalogController', function ($scope, $location, locationParser, flash, CatalogResource ) { 3 | $scope.disabled = false; 4 | $scope.$location = $location; 5 | $scope.catalog = $scope.catalog || {}; 6 | 7 | 8 | $scope.save = function() { 9 | var successCallback = function(data,responseHeaders){ 10 | var id = locationParser(responseHeaders); 11 | flash.setMessage({'type':'success','text':'The catalog was created successfully.'}); 12 | $location.path('/Catalogs'); 13 | }; 14 | var errorCallback = function(response) { 15 | if(response && response.data) { 16 | flash.setMessage({'type': 'error', 'text': response.data.message || response.data}, true); 17 | } else { 18 | flash.setMessage({'type': 'error', 'text': 'Something broke. Retry, or cancel and start afresh.'}, true); 19 | } 20 | }; 21 | CatalogResource.save($scope.catalog, successCallback, errorCallback); 22 | }; 23 | 24 | $scope.cancel = function() { 25 | $location.path("/Catalogs"); 26 | }; 27 | }); -------------------------------------------------------------------------------- /solution/cdfront/src/main/resources/static/scripts/controllers/searchCatalogController.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | angular.module('cdservice').controller('SearchCatalogController', function($scope, $http, $filter, CatalogResource ) { 4 | 5 | $scope.search={}; 6 | $scope.currentPage = 0; 7 | $scope.pageSize= 10; 8 | $scope.searchResults = []; 9 | $scope.filteredResults = []; 10 | $scope.pageRange = []; 11 | $scope.numberOfPages = function() { 12 | var result = Math.ceil($scope.filteredResults.length/$scope.pageSize); 13 | var max = (result == 0) ? 1 : result; 14 | $scope.pageRange = []; 15 | for(var ctr=0;ctr 0) { 30 | $scope.currentPage--; 31 | } 32 | }; 33 | 34 | $scope.next = function() { 35 | if($scope.currentPage < ($scope.numberOfPages() - 1) ) { 36 | $scope.currentPage++; 37 | } 38 | }; 39 | 40 | $scope.setPage = function(n) { 41 | $scope.currentPage = n; 42 | }; 43 | 44 | $scope.performSearch(); 45 | }); -------------------------------------------------------------------------------- /solution/cdfront/src/main/resources/static/scripts/directives/datepicker.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var DATE_REGEX = /^([0-2][0-9]{3})\-([0-1][0-9])\-([0-3][0-9])$/; 4 | angular.module('cdservice').directive('date', function($parse, dateFilter) { 5 | return { 6 | restrict : "E", 7 | replace : true, 8 | transclude : false, 9 | require: '?ngModel', 10 | compile : function(element, attrs) { 11 | var modelAccessor = $parse(attrs.ngModel); 12 | 13 | var isRequired = ""; 14 | if(attrs.required) { 15 | isRequired = "required"; 16 | } 17 | var html = ""; 18 | 19 | var $newElem = $(html); 20 | element.replaceWith($newElem); 21 | 22 | var nativeLinker = function(scope, element, attrs, ngModelCtrl) { 23 | if(!ngModelCtrl) return; 24 | 25 | var dateParser = function(value) { 26 | var date; 27 | if(value) { 28 | date = new Date(Date.parse(value)); 29 | } else { 30 | date = value; 31 | } 32 | return date; 33 | } 34 | var dateFormatter = function(value) { 35 | if(value) { 36 | var date = dateFilter(value,"yyyy-MM-dd"); 37 | return date; 38 | } 39 | return; 40 | } 41 | 42 | ngModelCtrl.$parsers.unshift(dateParser); 43 | ngModelCtrl.$formatters.unshift(dateFormatter); 44 | 45 | element.bind("blur keyup change", function() { 46 | scope.$apply(function() { 47 | ngModelCtrl.$setViewValue(element.val()); 48 | }); 49 | }); 50 | 51 | ngModelCtrl.$render = function() { 52 | element.val(ngModelCtrl.$viewValue); 53 | } 54 | } 55 | 56 | var enhancedLinker = function(scope, element, attrs, ngModelCtrl) { 57 | if(!ngModelCtrl) return; 58 | 59 | var dateParser = function(value) { 60 | if(value) { 61 | var d = value.match(DATE_REGEX); 62 | if(d) { 63 | var formattedDate = d[1] + "-" + d[2] + "-" + d[3]; 64 | var date = new Date(Date.parse(formattedDate)); 65 | ngModelCtrl.$setValidity("dateFormat", true); 66 | return date; 67 | } else { 68 | ngModelCtrl.$setValidity("dateFormat", false); 69 | return; 70 | } 71 | } 72 | return; 73 | } 74 | var dateFormatter = function(value) { 75 | if(value) { 76 | var date = dateFilter(value,"yyyy-MM-dd"); 77 | return date; 78 | } 79 | return; 80 | } 81 | 82 | ngModelCtrl.$parsers.unshift(dateParser); 83 | ngModelCtrl.$formatters.unshift(dateFormatter); 84 | 85 | element.bind("blur keyup change", function() { 86 | scope.$apply(function() { 87 | ngModelCtrl.$setViewValue(element.val()); 88 | }); 89 | }); 90 | 91 | ngModelCtrl.$render = function() { 92 | element.val(ngModelCtrl.$viewValue); 93 | } 94 | } 95 | 96 | if(Modernizr.inputtypes["date"]) { 97 | return nativeLinker; 98 | } else { 99 | return enhancedLinker; 100 | } 101 | } 102 | } 103 | }); -------------------------------------------------------------------------------- /solution/cdfront/src/main/resources/static/scripts/directives/datetimepicker.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var LOCAL_DATETIME_REGEX = /^([0-2][0-9]{3})\-([0-1][0-9])\-([0-3][0-9])\ ([0-5][0-9])\:([0-5][0-9])\:([0-5][0-9])$/; 4 | angular.module('cdservice').directive('datetime', function($parse, dateFilter) { 5 | return { 6 | restrict : "E", 7 | replace : true, 8 | transclude : false, 9 | require: '?ngModel', 10 | compile : function(element, attrs) { 11 | var modelAccessor = $parse(attrs.ngModel); 12 | 13 | var isRequired = ""; 14 | if(attrs.required) { 15 | isRequired = "required"; 16 | } 17 | var html = ""; 18 | 19 | var $newElem = $(html); 20 | element.replaceWith($newElem); 21 | 22 | var nativeLinker = function(scope, element, attrs, ngModelCtrl) { 23 | if(!ngModelCtrl) return; 24 | 25 | var localDateTimeParser = function(value) { 26 | var date; 27 | if(value) { 28 | date = new Date(Date.parse(value)); 29 | date.setTime(date.getTime() + date.getTimezoneOffset()*60000); 30 | } else { 31 | date = value; 32 | } 33 | return date; 34 | } 35 | var localDateTimeFormatter = function(value) { 36 | if(value) { 37 | var date = dateFilter(value,"yyyy-MM-ddTHH:mm:ss"); 38 | return date; 39 | } 40 | return; 41 | } 42 | 43 | ngModelCtrl.$parsers.unshift(localDateTimeParser); 44 | ngModelCtrl.$formatters.unshift(localDateTimeFormatter); 45 | 46 | element.bind("blur keyup change", function() { 47 | scope.$apply(function() { 48 | ngModelCtrl.$setViewValue(element.val()); 49 | }); 50 | }); 51 | 52 | ngModelCtrl.$render = function() { 53 | element.val(ngModelCtrl.$viewValue); 54 | } 55 | } 56 | 57 | var enhancedLinker = function(scope, element, attrs, ngModelCtrl) { 58 | if(!ngModelCtrl) return; 59 | 60 | var localDateTimeParser = function(value) { 61 | if(value) { 62 | var d = value.match(LOCAL_DATETIME_REGEX); 63 | if(d) { 64 | var formattedDate = d[1] + "-" + d[2] + "-" + d[3] + "T" 65 | + d[4] + ":" + d[5] + ":" + d[6]; 66 | var date = new Date(Date.parse(formattedDate)); 67 | ngModelCtrl.$setValidity("datetimeFormat", true); 68 | return date; 69 | } else { 70 | ngModelCtrl.$setValidity("datetimeFormat", false); 71 | return; 72 | } 73 | } 74 | return; 75 | } 76 | var localDateTimeFormatter = function(value) { 77 | if(value) { 78 | var date = dateFilter(value,"yyyy-MM-dd HH:mm:ss"); 79 | return date; 80 | } 81 | return; 82 | } 83 | 84 | ngModelCtrl.$parsers.unshift(localDateTimeParser); 85 | ngModelCtrl.$formatters.unshift(localDateTimeFormatter); 86 | 87 | element.bind("blur keyup change", function() { 88 | scope.$apply(function() { 89 | ngModelCtrl.$setViewValue(element.val()); 90 | }); 91 | }); 92 | 93 | ngModelCtrl.$render = function() { 94 | element.val(ngModelCtrl.$viewValue); 95 | } 96 | } 97 | 98 | if(Modernizr.inputtypes["datetime-local"]) { 99 | return nativeLinker; 100 | } else { 101 | return enhancedLinker; 102 | } 103 | } 104 | } 105 | }); -------------------------------------------------------------------------------- /solution/cdfront/src/main/resources/static/scripts/directives/timepicker.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var TIME_REGEX = /^([0-5][0-9])\:([0-5][0-9])(?:\:([0-5][0-9]))?$/; 4 | angular.module('cdservice').directive('time', function($parse, dateFilter) { 5 | return { 6 | restrict : "E", 7 | replace : true, 8 | transclude : false, 9 | require: '?ngModel', 10 | compile : function(element, attrs) { 11 | var modelAccessor = $parse(attrs.ngModel); 12 | 13 | var isRequired = ""; 14 | if(attrs.required) { 15 | isRequired = "required"; 16 | } 17 | var html = ""; 18 | 19 | var $newElem = $(html); 20 | element.replaceWith($newElem); 21 | 22 | var nativeLinker = function(scope, element, attrs, ngModelCtrl) { 23 | if(!ngModelCtrl) return; 24 | 25 | var timeParser = function(value) { 26 | var date; 27 | if(value) { 28 | var d = value.match(TIME_REGEX); 29 | if(d) { 30 | date = new Date(0); 31 | if(!d[3]) { 32 | d[3] = "0"; 33 | } 34 | date.setHours(d[1], d[2], d[3]); 35 | } else { 36 | date = value; 37 | } 38 | } else { 39 | date = value; 40 | } 41 | return date; 42 | } 43 | var timeFormatter = function(value) { 44 | if(value) { 45 | var date = dateFilter(value,"HH:mm:ss"); 46 | return date; 47 | } 48 | return; 49 | } 50 | 51 | ngModelCtrl.$parsers.unshift(timeParser); 52 | ngModelCtrl.$formatters.unshift(timeFormatter); 53 | 54 | element.bind("blur keyup change", function() { 55 | scope.$apply(function() { 56 | ngModelCtrl.$setViewValue(element.val()); 57 | }); 58 | }); 59 | 60 | ngModelCtrl.$render = function() { 61 | element.val(ngModelCtrl.$viewValue); 62 | } 63 | } 64 | 65 | var enhancedLinker = function(scope, element, attrs, ngModelCtrl) { 66 | if(!ngModelCtrl) return; 67 | 68 | var timeParser = function(value) { 69 | if(value) { 70 | var d = value.match(TIME_REGEX); 71 | if(d) { 72 | var date = new Date(0); 73 | if(!d[3]) { 74 | d[3] = "0"; 75 | } 76 | date.setHours(d[1], d[2], d[3]); 77 | ngModelCtrl.$setValidity("timeFormat", true); 78 | return date; 79 | } else { 80 | ngModelCtrl.$setValidity("timeFormat", false); 81 | return; 82 | } 83 | } 84 | return; 85 | } 86 | var timeFormatter = function(value) { 87 | if(value) { 88 | var date = dateFilter(value,"HH:mm:ss"); 89 | return date; 90 | } 91 | return; 92 | } 93 | 94 | ngModelCtrl.$parsers.unshift(timeParser); 95 | ngModelCtrl.$formatters.unshift(timeFormatter); 96 | 97 | element.bind("blur keyup change", function() { 98 | scope.$apply(function() { 99 | ngModelCtrl.$setViewValue(element.val()); 100 | }); 101 | }); 102 | 103 | ngModelCtrl.$render = function() { 104 | element.val(ngModelCtrl.$viewValue); 105 | } 106 | } 107 | 108 | if(Modernizr.inputtypes["time"]) { 109 | return nativeLinker; 110 | } else { 111 | return enhancedLinker; 112 | } 113 | } 114 | } 115 | }); -------------------------------------------------------------------------------- /solution/cdfront/src/main/resources/static/scripts/filters/genericSearchFilter.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('cdservice').filter('searchFilter', function() { 4 | 5 | function matchObjectProperties(expectedObject, actualObject) { 6 | var flag = true; 7 | for(var key in expectedObject) { 8 | if(expectedObject.hasOwnProperty(key)) { 9 | var expectedProperty = expectedObject[key]; 10 | if (expectedProperty == null || expectedProperty === "") { 11 | continue; 12 | } 13 | var actualProperty = actualObject[key]; 14 | if (angular.isUndefined(actualProperty)) { 15 | continue; 16 | } 17 | if (actualProperty == null) { 18 | flag = false; 19 | } else if (angular.isObject(expectedProperty)) { 20 | flag = flag && matchObjectProperties(expectedProperty, actualProperty); 21 | } else { 22 | flag = flag && (actualProperty.toString().indexOf(expectedProperty.toString()) != -1); 23 | } 24 | } 25 | } 26 | return flag; 27 | } 28 | 29 | return function(results, scope) { 30 | 31 | scope.filteredResults = []; 32 | for (var ctr = 0; ctr < results.length; ctr++) { 33 | var flag = true; 34 | var searchCriteria = scope.search; 35 | var result = results[ctr]; 36 | for (var key in searchCriteria) { 37 | if (searchCriteria.hasOwnProperty(key)) { 38 | var expected = searchCriteria[key]; 39 | if (expected == null || expected === "") { 40 | continue; 41 | } 42 | var actual = result[key]; 43 | if (actual == null) { 44 | flag = false; 45 | } else if (angular.isObject(expected)) { 46 | flag = flag && matchObjectProperties(expected, actual); 47 | } else { 48 | flag = flag && (actual.toString().indexOf(expected.toString()) != -1); 49 | } 50 | } 51 | } 52 | if (flag == true) { 53 | scope.filteredResults.push(result); 54 | } 55 | } 56 | scope.numberOfPages(); 57 | return scope.filteredResults; 58 | }; 59 | }); 60 | -------------------------------------------------------------------------------- /solution/cdfront/src/main/resources/static/scripts/filters/startFromFilter.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('cdservice').filter('startFrom', function() { 4 | return function(input, start) { 5 | start = +start; //parse to int 6 | return input.slice(start); 7 | }; 8 | }); -------------------------------------------------------------------------------- /solution/cdfront/src/main/resources/static/scripts/offcanvas.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function() { 2 | $('[data-toggle=offcanvas]').click(function() { 3 | $('.row-offcanvas').toggleClass('active'); 4 | }); 5 | }); -------------------------------------------------------------------------------- /solution/cdfront/src/main/resources/static/scripts/services/CatalogFactory.js: -------------------------------------------------------------------------------- 1 | angular.module('cdservice').factory('CatalogResource', function ($resource, config) { 2 | return $resource(config.getApiUrl() + ':CatalogId', { CatalogId: '@id' }, { 3 | 'queryAll': { 4 | method: 'GET', 5 | isArray: true 6 | }, 'query': { method: 'GET', isArray: false }, 'update': { method: 'PUT' } 7 | }); 8 | }); -------------------------------------------------------------------------------- /solution/cdfront/src/main/resources/static/scripts/services/config.js: -------------------------------------------------------------------------------- 1 | angular.module('cdservice').factory('config', function ($http, $q) { 2 | var deferred = $q.defer(); 3 | var apiUrl = null; 4 | $http.get("service.json") 5 | .success(function (data) { 6 | console.log("Resource : " + data['cd-service'] + ':CatalogId'); 7 | deferred.resolve(data['cd-service']); 8 | apiUrl = data['cd-service']; 9 | }) 10 | .error(function () { 11 | deferred.reject('could not find service.json ....'); 12 | }); 13 | 14 | return { 15 | promise: deferred.promise, 16 | getApiUrl: function () { 17 | return apiUrl; 18 | } 19 | }; 20 | }); 21 | -------------------------------------------------------------------------------- /solution/cdfront/src/main/resources/static/scripts/services/flash.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('cdservice').factory('flash', ['$rootScope', function ($rootScope) { 4 | var messages = []; 5 | var currentMessage = {}; 6 | 7 | $rootScope.$on('$routeChangeSuccess', function() { 8 | currentMessage = messages.shift() || {}; 9 | }); 10 | 11 | return { 12 | getMessage: function () { 13 | return currentMessage; 14 | }, 15 | setMessage: function(message, pop) { 16 | switch(message.type) { 17 | case "error" : message.cssClass = "danger"; break; 18 | case "success" : message.cssClass = "success"; break; 19 | case "info" : message.cssClass = "info"; break; 20 | case "warning" : message.cssClass = "warning"; break; 21 | } 22 | messages.push(message); 23 | if(pop) { 24 | currentMessage = messages.shift() || {}; 25 | } 26 | } 27 | }; 28 | }]); 29 | -------------------------------------------------------------------------------- /solution/cdfront/src/main/resources/static/scripts/services/locationParser.js: -------------------------------------------------------------------------------- 1 | angular.module('cdservice').value('locationParser', function(responseHeaders){ 2 | // Get the Location header and parse it. 3 | var locationHeader = responseHeaders('Location'); 4 | var fragments = locationHeader.split('/'); 5 | var id = fragments[fragments.length -1]; 6 | return id; 7 | }); -------------------------------------------------------------------------------- /solution/cdfront/src/main/resources/static/service.json: -------------------------------------------------------------------------------- 1 | { "cd-service": "http://cdservice-workshop.apps.35.187.106.198.nip.io/rest/catalogs/" } 2 | -------------------------------------------------------------------------------- /solution/cdfront/src/main/resources/static/styles/main.css: -------------------------------------------------------------------------------- 1 | @CHARSET "UTF-8"; 2 | 3 | /* Sticky footer styles 4 | -------------------------------------------------- */ 5 | 6 | html, body { 7 | height: 100%; 8 | /* The html and body elements cannot have any padding or margin. */ 9 | } 10 | 11 | /* Wrapper for page content to push down footer */ 12 | #wrap { 13 | min-height: 100%; 14 | height: auto; 15 | /* Negative indent footer by it's height */ 16 | margin: 0 auto -60px; 17 | /* Pad bottom by footer height */ 18 | padding: 0 0 60px; 19 | } 20 | 21 | #wrap > .container { 22 | padding-top: 50px; 23 | } 24 | 25 | /* Set the fixed height of the footer here */ 26 | #footer { 27 | height: 60px; 28 | } 29 | 30 | #footer { 31 | background-color: #F5F5F5; 32 | text-align: center; 33 | border-top: 1px solid #E5E5E5; 34 | } 35 | 36 | h2 i.icon-check { 37 | vertical-align: middle; 38 | } 39 | 40 | table { 41 | table-layout: fixed; 42 | word-wrap: break-word; 43 | } 44 | 45 | /* Lastly, apply responsive CSS fixes as necessary */ 46 | @media (max-width: 767px) { 47 | table { 48 | table-layout: auto; 49 | } 50 | .row-offcanvas { 51 | position: relative; 52 | transition: all 0.25s ease-out; 53 | } 54 | .row-offcanvas-left .sidebar-offcanvas { 55 | display:none; 56 | } 57 | .row-offcanvas-left.active .sidebar-offcanvas { 58 | display:inherit; 59 | } 60 | .row-offcanvas-left.active .mainarea { 61 | display:none; 62 | } 63 | .sidebar-offcanvas { 64 | position: absolute; 65 | top: 0; 66 | width: 100%; 67 | } 68 | } -------------------------------------------------------------------------------- /solution/cdfront/src/main/resources/static/views/Catalog/detail.html: -------------------------------------------------------------------------------- 1 |
2 |

Create a new Catalog

3 |

View or edit Catalog

4 |
5 |
6 | 7 | 8 |
9 | 10 |
11 | 12 |
13 |
14 | 15 |
16 | 17 |
18 | 19 |
20 |
21 | 22 |
23 | 24 |
25 | 26 | maximum length is 2000 27 |
28 |
29 | 30 |
31 | 32 |
33 | 34 | not a number 35 |
36 |
37 | 38 |
39 | 40 |
41 | 42 | does not match format "yyyy-MM-dd hh:mm:ss" (e.g. 2013-12-01 22:00:00) 43 |
44 |
45 | 46 | 47 |
48 |
49 | 50 | 51 | 52 |
53 |
54 |
-------------------------------------------------------------------------------- /solution/cdfront/src/main/resources/static/views/Catalog/search.html: -------------------------------------------------------------------------------- 1 |
2 |

Create a new Catalog

3 |
4 |
5 | Create 6 |
7 |
8 |
9 |
10 |
11 |

Search for Catalogs

12 |
13 | 14 | 15 |
16 | 17 |
18 | 19 |
20 |
21 | 22 |
23 | 24 |
25 | 26 |
27 |
28 | 29 |
30 | 31 |
32 | 33 |
34 |
35 | 36 |
37 | 38 |
39 | 40 |
41 |
42 | 43 | 44 | 45 |
46 |
47 | Search 48 |
49 |
50 |
51 |
52 |
53 |
54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 |
ArtistTitleDescriptionPricePublication Date
{{result.artist}}{{result.title}}{{result.description}}{{result.price}}{{result.publicationDate| date:'yyyy-MM-dd HH:mm:ss Z'}}
74 |
75 | 76 |
    77 |
  • 78 | 79 |
  • 80 |
  • 81 | 1 82 |
  • 83 |
  • 84 | 85 |
  • 86 |
87 | 88 |
-------------------------------------------------------------------------------- /solution/cdfront/src/main/resources/static/views/landing.html: -------------------------------------------------------------------------------- 1 |

2 | Your application is running. 3 |

4 |

5 | Documentation 7 | | Get Excited!

9 | Forge Project
| User 11 | Forums | Report an issue 13 |

-------------------------------------------------------------------------------- /solution/cdfront/src/test/java/org/cdfront/DemoApplicationTests.java: -------------------------------------------------------------------------------- 1 | package org.cdfront; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class DemoApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /solution/cdservice/mvnw: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # ---------------------------------------------------------------------------- 3 | # Licensed to the Apache Software Foundation (ASF) under one 4 | # or more contributor license agreements. See the NOTICE file 5 | # distributed with this work for additional information 6 | # regarding copyright ownership. The ASF licenses this file 7 | # to you under the Apache License, Version 2.0 (the 8 | # "License"); you may not use this file except in compliance 9 | # with the License. You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, 14 | # software distributed under the License is distributed on an 15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | # KIND, either express or implied. See the License for the 17 | # specific language governing permissions and limitations 18 | # under the License. 19 | # ---------------------------------------------------------------------------- 20 | 21 | # ---------------------------------------------------------------------------- 22 | # Maven2 Start Up Batch script 23 | # 24 | # Required ENV vars: 25 | # ------------------ 26 | # JAVA_HOME - location of a JDK home dir 27 | # 28 | # Optional ENV vars 29 | # ----------------- 30 | # M2_HOME - location of maven2's installed home dir 31 | # MAVEN_OPTS - parameters passed to the Java VM when running Maven 32 | # e.g. to debug Maven itself, use 33 | # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 34 | # MAVEN_SKIP_RC - flag to disable loading of mavenrc files 35 | # ---------------------------------------------------------------------------- 36 | 37 | if [ -z "$MAVEN_SKIP_RC" ] ; then 38 | 39 | if [ -f /etc/mavenrc ] ; then 40 | . /etc/mavenrc 41 | fi 42 | 43 | if [ -f "$HOME/.mavenrc" ] ; then 44 | . "$HOME/.mavenrc" 45 | fi 46 | 47 | fi 48 | 49 | # OS specific support. $var _must_ be set to either true or false. 50 | cygwin=false; 51 | darwin=false; 52 | mingw=false 53 | case "`uname`" in 54 | CYGWIN*) cygwin=true ;; 55 | MINGW*) mingw=true;; 56 | Darwin*) darwin=true 57 | # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home 58 | # See https://developer.apple.com/library/mac/qa/qa1170/_index.html 59 | if [ -z "$JAVA_HOME" ]; then 60 | if [ -x "/usr/libexec/java_home" ]; then 61 | export JAVA_HOME="`/usr/libexec/java_home`" 62 | else 63 | export JAVA_HOME="/Library/Java/Home" 64 | fi 65 | fi 66 | ;; 67 | esac 68 | 69 | if [ -z "$JAVA_HOME" ] ; then 70 | if [ -r /etc/gentoo-release ] ; then 71 | JAVA_HOME=`java-config --jre-home` 72 | fi 73 | fi 74 | 75 | if [ -z "$M2_HOME" ] ; then 76 | ## resolve links - $0 may be a link to maven's home 77 | PRG="$0" 78 | 79 | # need this for relative symlinks 80 | while [ -h "$PRG" ] ; do 81 | ls=`ls -ld "$PRG"` 82 | link=`expr "$ls" : '.*-> \(.*\)$'` 83 | if expr "$link" : '/.*' > /dev/null; then 84 | PRG="$link" 85 | else 86 | PRG="`dirname "$PRG"`/$link" 87 | fi 88 | done 89 | 90 | saveddir=`pwd` 91 | 92 | M2_HOME=`dirname "$PRG"`/.. 93 | 94 | # make it fully qualified 95 | M2_HOME=`cd "$M2_HOME" && pwd` 96 | 97 | cd "$saveddir" 98 | # echo Using m2 at $M2_HOME 99 | fi 100 | 101 | # For Cygwin, ensure paths are in UNIX format before anything is touched 102 | if $cygwin ; then 103 | [ -n "$M2_HOME" ] && 104 | M2_HOME=`cygpath --unix "$M2_HOME"` 105 | [ -n "$JAVA_HOME" ] && 106 | JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 107 | [ -n "$CLASSPATH" ] && 108 | CLASSPATH=`cygpath --path --unix "$CLASSPATH"` 109 | fi 110 | 111 | # For Migwn, ensure paths are in UNIX format before anything is touched 112 | if $mingw ; then 113 | [ -n "$M2_HOME" ] && 114 | M2_HOME="`(cd "$M2_HOME"; pwd)`" 115 | [ -n "$JAVA_HOME" ] && 116 | JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" 117 | # TODO classpath? 118 | fi 119 | 120 | if [ -z "$JAVA_HOME" ]; then 121 | javaExecutable="`which javac`" 122 | if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then 123 | # readlink(1) is not available as standard on Solaris 10. 124 | readLink=`which readlink` 125 | if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then 126 | if $darwin ; then 127 | javaHome="`dirname \"$javaExecutable\"`" 128 | javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" 129 | else 130 | javaExecutable="`readlink -f \"$javaExecutable\"`" 131 | fi 132 | javaHome="`dirname \"$javaExecutable\"`" 133 | javaHome=`expr "$javaHome" : '\(.*\)/bin'` 134 | JAVA_HOME="$javaHome" 135 | export JAVA_HOME 136 | fi 137 | fi 138 | fi 139 | 140 | if [ -z "$JAVACMD" ] ; then 141 | if [ -n "$JAVA_HOME" ] ; then 142 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 143 | # IBM's JDK on AIX uses strange locations for the executables 144 | JAVACMD="$JAVA_HOME/jre/sh/java" 145 | else 146 | JAVACMD="$JAVA_HOME/bin/java" 147 | fi 148 | else 149 | JAVACMD="`which java`" 150 | fi 151 | fi 152 | 153 | if [ ! -x "$JAVACMD" ] ; then 154 | echo "Error: JAVA_HOME is not defined correctly." >&2 155 | echo " We cannot execute $JAVACMD" >&2 156 | exit 1 157 | fi 158 | 159 | if [ -z "$JAVA_HOME" ] ; then 160 | echo "Warning: JAVA_HOME environment variable is not set." 161 | fi 162 | 163 | CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher 164 | 165 | # traverses directory structure from process work directory to filesystem root 166 | # first directory with .mvn subdirectory is considered project base directory 167 | find_maven_basedir() { 168 | 169 | if [ -z "$1" ] 170 | then 171 | echo "Path not specified to find_maven_basedir" 172 | return 1 173 | fi 174 | 175 | basedir="$1" 176 | wdir="$1" 177 | while [ "$wdir" != '/' ] ; do 178 | if [ -d "$wdir"/.mvn ] ; then 179 | basedir=$wdir 180 | break 181 | fi 182 | # workaround for JBEAP-8937 (on Solaris 10/Sparc) 183 | if [ -d "${wdir}" ]; then 184 | wdir=`cd "$wdir/.."; pwd` 185 | fi 186 | # end of workaround 187 | done 188 | echo "${basedir}" 189 | } 190 | 191 | # concatenates all lines of a file 192 | concat_lines() { 193 | if [ -f "$1" ]; then 194 | echo "$(tr -s '\n' ' ' < "$1")" 195 | fi 196 | } 197 | 198 | BASE_DIR=`find_maven_basedir "$(pwd)"` 199 | if [ -z "$BASE_DIR" ]; then 200 | exit 1; 201 | fi 202 | 203 | export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} 204 | echo $MAVEN_PROJECTBASEDIR 205 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" 206 | 207 | # For Cygwin, switch paths to Windows format before running java 208 | if $cygwin; then 209 | [ -n "$M2_HOME" ] && 210 | M2_HOME=`cygpath --path --windows "$M2_HOME"` 211 | [ -n "$JAVA_HOME" ] && 212 | JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` 213 | [ -n "$CLASSPATH" ] && 214 | CLASSPATH=`cygpath --path --windows "$CLASSPATH"` 215 | [ -n "$MAVEN_PROJECTBASEDIR" ] && 216 | MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` 217 | fi 218 | 219 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 220 | 221 | exec "$JAVACMD" \ 222 | $MAVEN_OPTS \ 223 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ 224 | "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ 225 | ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" 226 | -------------------------------------------------------------------------------- /solution/cdservice/mvnw.cmd: -------------------------------------------------------------------------------- 1 | @REM ---------------------------------------------------------------------------- 2 | @REM Licensed to the Apache Software Foundation (ASF) under one 3 | @REM or more contributor license agreements. See the NOTICE file 4 | @REM distributed with this work for additional information 5 | @REM regarding copyright ownership. The ASF licenses this file 6 | @REM to you under the Apache License, Version 2.0 (the 7 | @REM "License"); you may not use this file except in compliance 8 | @REM with the License. You may obtain a copy of the License at 9 | @REM 10 | @REM http://www.apache.org/licenses/LICENSE-2.0 11 | @REM 12 | @REM Unless required by applicable law or agreed to in writing, 13 | @REM software distributed under the License is distributed on an 14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | @REM KIND, either express or implied. See the License for the 16 | @REM specific language governing permissions and limitations 17 | @REM under the License. 18 | @REM ---------------------------------------------------------------------------- 19 | 20 | @REM ---------------------------------------------------------------------------- 21 | @REM Maven2 Start Up Batch script 22 | @REM 23 | @REM Required ENV vars: 24 | @REM JAVA_HOME - location of a JDK home dir 25 | @REM 26 | @REM Optional ENV vars 27 | @REM M2_HOME - location of maven2's installed home dir 28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands 29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending 30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven 31 | @REM e.g. to debug Maven itself, use 32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files 34 | @REM ---------------------------------------------------------------------------- 35 | 36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' 37 | @echo off 38 | @REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' 39 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% 40 | 41 | @REM set %HOME% to equivalent of $HOME 42 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") 43 | 44 | @REM Execute a user defined script before this one 45 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre 46 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending 47 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" 48 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" 49 | :skipRcPre 50 | 51 | @setlocal 52 | 53 | set ERROR_CODE=0 54 | 55 | @REM To isolate internal variables from possible post scripts, we use another setlocal 56 | @setlocal 57 | 58 | @REM ==== START VALIDATION ==== 59 | if not "%JAVA_HOME%" == "" goto OkJHome 60 | 61 | echo. 62 | echo Error: JAVA_HOME not found in your environment. >&2 63 | echo Please set the JAVA_HOME variable in your environment to match the >&2 64 | echo location of your Java installation. >&2 65 | echo. 66 | goto error 67 | 68 | :OkJHome 69 | if exist "%JAVA_HOME%\bin\java.exe" goto init 70 | 71 | echo. 72 | echo Error: JAVA_HOME is set to an invalid directory. >&2 73 | echo JAVA_HOME = "%JAVA_HOME%" >&2 74 | echo Please set the JAVA_HOME variable in your environment to match the >&2 75 | echo location of your Java installation. >&2 76 | echo. 77 | goto error 78 | 79 | @REM ==== END VALIDATION ==== 80 | 81 | :init 82 | 83 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn". 84 | @REM Fallback to current working directory if not found. 85 | 86 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% 87 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir 88 | 89 | set EXEC_DIR=%CD% 90 | set WDIR=%EXEC_DIR% 91 | :findBaseDir 92 | IF EXIST "%WDIR%"\.mvn goto baseDirFound 93 | cd .. 94 | IF "%WDIR%"=="%CD%" goto baseDirNotFound 95 | set WDIR=%CD% 96 | goto findBaseDir 97 | 98 | :baseDirFound 99 | set MAVEN_PROJECTBASEDIR=%WDIR% 100 | cd "%EXEC_DIR%" 101 | goto endDetectBaseDir 102 | 103 | :baseDirNotFound 104 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR% 105 | cd "%EXEC_DIR%" 106 | 107 | :endDetectBaseDir 108 | 109 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig 110 | 111 | @setlocal EnableExtensions EnableDelayedExpansion 112 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a 113 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% 114 | 115 | :endReadAdditionalConfig 116 | 117 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" 118 | 119 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" 120 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 121 | 122 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* 123 | if ERRORLEVEL 1 goto error 124 | goto end 125 | 126 | :error 127 | set ERROR_CODE=1 128 | 129 | :end 130 | @endlocal & set ERROR_CODE=%ERROR_CODE% 131 | 132 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost 133 | @REM check for post script, once with legacy .bat ending and once with .cmd ending 134 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" 135 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" 136 | :skipRcPost 137 | 138 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' 139 | if "%MAVEN_BATCH_PAUSE%" == "on" pause 140 | 141 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% 142 | 143 | exit /B %ERROR_CODE% 144 | -------------------------------------------------------------------------------- /solution/cdservice/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | org.cdservice 6 | cdservice 7 | 1.0.0-SNAPSHOT 8 | jar 9 | 10 | demo 11 | Demo project for Spring Boot 12 | 13 | 14 | org.springframework.boot 15 | spring-boot-starter-parent 16 | 1.5.3.RELEASE 17 | 18 | 19 | 20 | UTF-8 21 | UTF-8 22 | 1.8 23 | 24 | 25 | 26 | 27 | org.springframework.boot 28 | spring-boot-starter 29 | 30 | 31 | 32 | org.springframework.boot 33 | spring-boot-starter-test 34 | test 35 | 36 | 37 | 38 | org.springframework.boot 39 | spring-boot-starter-data-jpa 40 | 41 | 42 | 43 | org.springframework.boot 44 | spring-boot-starter-web 45 | 46 | 47 | 48 | org.apache.cxf 49 | cxf-spring-boot-starter-jaxrs 50 | 3.1.11 51 | 52 | 53 | 54 | com.fasterxml.jackson.jaxrs 55 | jackson-jaxrs-json-provider 56 | 57 | 58 | 59 | org.jboss.spec.javax.servlet 60 | jboss-servlet-api_3.0_spec 61 | provided 62 | 63 | 64 | 65 | org.jboss.spec.javax.ws.rs 66 | jboss-jaxrs-api_1.1_spec 67 | provided 68 | 69 | 70 | 71 | org.springframework.cloud 72 | spring-cloud-starter-kubernetes-config 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | org.jboss.spec 82 | jboss-javaee-6.0 83 | 3.0.3.Final 84 | pom 85 | import 86 | 87 | 88 | org.springframework.cloud 89 | spring-cloud-starter-kubernetes-config 90 | 0.2.0.BUILD-SNAPSHOT 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | org.springframework.boot 99 | spring-boot-maven-plugin 100 | 101 | 102 | io.fabric8 103 | fabric8-maven-plugin 104 | 3.2.9 105 | 106 | 107 | fmp 108 | 109 | resource 110 | helm 111 | build 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | local com.h2database h2 src/main/config-local src/main/resources openshift mysql mysql-connector-java src/main/config-openshift src/main/resources 121 | -------------------------------------------------------------------------------- /solution/cdservice/src/main/config-local/application.properties: -------------------------------------------------------------------------------- 1 | #Tue Jun 13 16:01:04 CEST 2017 2 | spring.jpa.properties.hibernate.transaction.flush_before_completion=true 3 | spring.jpa.properties.hibernate.show_sql=true 4 | cxf.jaxrs.component-scan=true 5 | spring.jpa.properties.hibernate.format_sql=true 6 | cxf.path=/rest 7 | spring.jpa.properties.hibernate.hbm2ddl.auto=create-drop 8 | spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect 9 | -------------------------------------------------------------------------------- /solution/cdservice/src/main/config-local/data.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO Catalog (id, version, artist, description, price, publication_date, title) VALUES (1001, 1, 'ACDC', 'Australian hard rock band', 15.0, '1980-07-25', 'Back in Black'); 2 | INSERT INTO Catalog (id, version, artist, description, price, publication_date, title) VALUES (1002, 1, 'Abba', 'Swedish pop music group', 12.0, '1976-10-11', 'Arrival'); 3 | INSERT INTO Catalog (id, version, artist, description, price, publication_date, title) VALUES (1003, 1, 'Coldplay', 'British rock band ', 17.0, '2008-07-12', 'Viva la Vida'); 4 | INSERT INTO Catalog (id, version, artist, description, price, publication_date, title) VALUES (1004, 1, 'U2', 'Irish rock band ', 18.0, '1987-03-09', 'The Joshua Tree'); 5 | INSERT INTO Catalog (id, version, artist, description, price, publication_date, title) VALUES (1005, 1, 'Metallica', 'Heavy metal band', 15.0, '1991-08-12', 'Black'); -------------------------------------------------------------------------------- /solution/cdservice/src/main/config-openshift/bootstrap.properties: -------------------------------------------------------------------------------- 1 | spring.application.name=cdservice 2 | -------------------------------------------------------------------------------- /solution/cdservice/src/main/config-openshift/data.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO catalog (id, version, artist, description, price, publication_date, title) VALUES (1001, 1, 'ACDC', 'Australian hard rock band', 15.0, '1980-07-25', 'Back in Black'); 2 | INSERT INTO catalog (id, version, artist, description, price, publication_date, title) VALUES (1002, 1, 'Abba', 'Swedish pop music group', 12.0, '1976-10-11', 'Arrival'); 3 | INSERT INTO catalog (id, version, artist, description, price, publication_date, title) VALUES (1003, 1, 'Coldplay', 'British rock band ', 17.0, '2008-07-12', 'Viva la Vida'); 4 | INSERT INTO catalog (id, version, artist, description, price, publication_date, title) VALUES (1004, 1, 'U2', 'Irish rock band ', 18.0, '1987-03-09', 'The Joshua Tree'); 5 | INSERT INTO catalog (id, version, artist, description, price, publication_date, title) VALUES (1005, 1, 'Metallica', 'Heavy metal band', 15.0, '1991-08-12', 'Black'); -------------------------------------------------------------------------------- /solution/cdservice/src/main/fabric8/configmap.yml: -------------------------------------------------------------------------------- 1 | metadata: 2 | name: ${project.artifactId} 3 | data: 4 | application.properties: |- 5 | cxf.jaxrs.component-scan=true 6 | cxf.path=/rest 7 | 8 | spring.datasource.url=jdbc\:mysql\://mysql\:3306/catalogdb 9 | spring.datasource.username=mysql 10 | spring.datasource.password=mysql 11 | 12 | spring.jpa.properties.hibernate.transaction.flush_before_completion=true 13 | spring.jpa.properties.hibernate.show_sql=true 14 | spring.jpa.properties.hibernate.format_sql=true 15 | spring.jpa.properties.hibernate.hbm2ddl.auto=create-drop 16 | spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQLDialect 17 | -------------------------------------------------------------------------------- /solution/cdservice/src/main/fabric8/route.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Route 3 | metadata: 4 | name: ${project.artifactId} 5 | spec: 6 | port: 7 | targetPort: 8080 8 | to: 9 | kind: Service 10 | name: ${project.artifactId} 11 | -------------------------------------------------------------------------------- /solution/cdservice/src/main/java/org/cdservice/DemoApplication.java: -------------------------------------------------------------------------------- 1 | package org.cdservice; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider; 6 | import org.springframework.context.annotation.Bean; 7 | 8 | @SpringBootApplication 9 | public class DemoApplication { 10 | 11 | public static void main(String[] args) { 12 | SpringApplication.run(DemoApplication.class, args); 13 | } 14 | 15 | @Bean 16 | public JacksonJsonProvider config() { 17 | return new JacksonJsonProvider(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /solution/cdservice/src/main/java/org/cdservice/model/Catalog.java: -------------------------------------------------------------------------------- 1 | package org.cdservice.model; 2 | 3 | import javax.persistence.Entity; 4 | import java.io.Serializable; 5 | import javax.persistence.Id; 6 | import javax.persistence.GeneratedValue; 7 | import javax.persistence.GenerationType; 8 | import javax.persistence.Column; 9 | import javax.persistence.Version; 10 | import java.util.Date; 11 | import javax.persistence.Temporal; 12 | import javax.persistence.TemporalType; 13 | import javax.xml.bind.annotation.XmlRootElement; 14 | 15 | @Entity 16 | @XmlRootElement 17 | public class Catalog implements Serializable { 18 | 19 | private static final long serialVersionUID = 1L; 20 | @Id 21 | @GeneratedValue(strategy = GenerationType.AUTO) 22 | @Column(name = "id", updatable = false, nullable = false) 23 | private Long id; 24 | @Version 25 | @Column(name = "version") 26 | private int version; 27 | 28 | @Column 29 | private String artist; 30 | 31 | @Column 32 | private String title; 33 | 34 | @Column(length = 2000) 35 | private String description; 36 | 37 | @Column 38 | private Float price; 39 | 40 | @Column 41 | @Temporal(TemporalType.DATE) 42 | private Date publication_date; 43 | 44 | public Long getId() { 45 | return this.id; 46 | } 47 | 48 | public void setId(final Long id) { 49 | this.id = id; 50 | } 51 | 52 | public int getVersion() { 53 | return this.version; 54 | } 55 | 56 | public void setVersion(final int version) { 57 | this.version = version; 58 | } 59 | 60 | @Override 61 | public boolean equals(Object obj) { 62 | if (this == obj) { 63 | return true; 64 | } 65 | if (!(obj instanceof Catalog)) { 66 | return false; 67 | } 68 | Catalog other = (Catalog) obj; 69 | if (id != null) { 70 | if (!id.equals(other.id)) { 71 | return false; 72 | } 73 | } 74 | return true; 75 | } 76 | 77 | @Override 78 | public int hashCode() { 79 | final int prime = 31; 80 | int result = 1; 81 | result = prime * result + ((id == null) ? 0 : id.hashCode()); 82 | return result; 83 | } 84 | 85 | public String getArtist() { 86 | return artist; 87 | } 88 | 89 | public void setArtist(String artist) { 90 | this.artist = artist; 91 | } 92 | 93 | public String getTitle() { 94 | return title; 95 | } 96 | 97 | public void setTitle(String title) { 98 | this.title = title; 99 | } 100 | 101 | public String getDescription() { 102 | return description; 103 | } 104 | 105 | public void setDescription(String description) { 106 | this.description = description; 107 | } 108 | 109 | public Float getPrice() { 110 | return price; 111 | } 112 | 113 | public void setPrice(Float price) { 114 | this.price = price; 115 | } 116 | 117 | public Date getPublication_date() { 118 | return publication_date; 119 | } 120 | 121 | public void setPublication_date(Date publication_date) { 122 | this.publication_date = publication_date; 123 | } 124 | 125 | @Override 126 | public String toString() { 127 | String result = getClass().getSimpleName() + " "; 128 | if (id != null) 129 | result += "id: " + id; 130 | result += ", version: " + version; 131 | if (artist != null && !artist.trim().isEmpty()) 132 | result += ", artist: " + artist; 133 | if (title != null && !title.trim().isEmpty()) 134 | result += ", title: " + title; 135 | if (description != null && !description.trim().isEmpty()) 136 | result += ", description: " + description; 137 | if (price != null) 138 | result += ", price: " + price; 139 | if (publication_date != null) 140 | result += ", publication_date: " + publication_date; 141 | return result; 142 | } 143 | } -------------------------------------------------------------------------------- /solution/cdservice/src/main/java/org/cdservice/model/CatalogRepository.java: -------------------------------------------------------------------------------- 1 | package org.cdservice.model; 2 | 3 | import org.springframework.data.repository.CrudRepository; 4 | 5 | public interface CatalogRepository extends CrudRepository { 6 | } -------------------------------------------------------------------------------- /solution/cdservice/src/main/java/org/cdservice/model/RepositoryConfiguration.java: -------------------------------------------------------------------------------- 1 | package org.cdservice.model; 2 | 3 | import org.springframework.context.annotation.Configuration; 4 | import org.springframework.boot.autoconfigure.EnableAutoConfiguration; 5 | import org.springframework.transaction.annotation.EnableTransactionManagement; 6 | import org.springframework.boot.autoconfigure.domain.EntityScan; 7 | import org.springframework.data.jpa.repository.config.EnableJpaRepositories; 8 | 9 | @Configuration 10 | @EnableAutoConfiguration 11 | @EnableTransactionManagement 12 | @EntityScan(basePackages = "org.cdservice.model") 13 | @EnableJpaRepositories(basePackages = "org.cdservice.model") 14 | public class RepositoryConfiguration { 15 | } -------------------------------------------------------------------------------- /solution/cdservice/src/main/java/org/cdservice/rest/CatalogEndpoint.java: -------------------------------------------------------------------------------- 1 | package org.cdservice.rest; 2 | 3 | import java.util.List; 4 | 5 | import javax.persistence.EntityManager; 6 | import javax.persistence.NoResultException; 7 | import javax.persistence.OptimisticLockException; 8 | import javax.persistence.PersistenceContext; 9 | import javax.persistence.TypedQuery; 10 | import javax.ws.rs.Consumes; 11 | import javax.ws.rs.DELETE; 12 | import javax.ws.rs.GET; 13 | import javax.ws.rs.POST; 14 | import javax.ws.rs.PUT; 15 | import javax.ws.rs.Path; 16 | import javax.ws.rs.PathParam; 17 | import javax.ws.rs.Produces; 18 | import javax.ws.rs.QueryParam; 19 | import javax.ws.rs.core.Response; 20 | import javax.ws.rs.core.Response.Status; 21 | import javax.ws.rs.core.UriBuilder; 22 | 23 | import org.springframework.stereotype.Component; 24 | import org.springframework.transaction.annotation.Transactional; 25 | import org.cdservice.model.Catalog; 26 | 27 | /** 28 | * 29 | */ 30 | @Path("/catalogs") 31 | @Component 32 | @Transactional 33 | public class CatalogEndpoint { 34 | @PersistenceContext 35 | private EntityManager em; 36 | 37 | @POST 38 | @Consumes("application/json") 39 | public Response create(Catalog entity) { 40 | em.persist(entity); 41 | return Response.created( 42 | UriBuilder.fromResource(CatalogEndpoint.class) 43 | .path(String.valueOf(entity.getId())).build()).build(); 44 | } 45 | 46 | @DELETE 47 | @Path("/{id:[0-9][0-9]*}") 48 | public Response deleteById(@PathParam("id") Long id) { 49 | Catalog entity = em.find(Catalog.class, id); 50 | if (entity == null) { 51 | return Response.status(Status.NOT_FOUND).build(); 52 | } 53 | em.remove(entity); 54 | return Response.noContent().build(); 55 | } 56 | 57 | @GET 58 | @Path("/{id:[0-9][0-9]*}") 59 | @Produces("application/json") 60 | public Response findById(@PathParam("id") Long id) { 61 | TypedQuery findByIdQuery = em 62 | .createQuery( 63 | "SELECT DISTINCT c FROM Catalog c WHERE c.id = :entityId ORDER BY c.id", 64 | Catalog.class); 65 | findByIdQuery.setParameter("entityId", id); 66 | Catalog entity; 67 | try { 68 | entity = findByIdQuery.getSingleResult(); 69 | } catch (NoResultException nre) { 70 | entity = null; 71 | } 72 | if (entity == null) { 73 | return Response.status(Status.NOT_FOUND).build(); 74 | } 75 | return Response.ok(entity).build(); 76 | } 77 | 78 | @GET 79 | @Produces("application/json") 80 | public List listAll(@QueryParam("start") Integer startPosition, 81 | @QueryParam("max") Integer maxResult) { 82 | TypedQuery findAllQuery = em 83 | .createQuery("SELECT DISTINCT c FROM Catalog c ORDER BY c.id", 84 | Catalog.class); 85 | if (startPosition != null) { 86 | findAllQuery.setFirstResult(startPosition); 87 | } 88 | if (maxResult != null) { 89 | findAllQuery.setMaxResults(maxResult); 90 | } 91 | final List results = findAllQuery.getResultList(); 92 | return results; 93 | } 94 | 95 | @PUT 96 | @Path("/{id:[0-9][0-9]*}") 97 | @Consumes("application/json") 98 | public Response update(@PathParam("id") Long id, Catalog entity) { 99 | if (entity == null) { 100 | return Response.status(Status.BAD_REQUEST).build(); 101 | } 102 | if (id == null) { 103 | return Response.status(Status.BAD_REQUEST).build(); 104 | } 105 | if (!id.equals(entity.getId())) { 106 | return Response.status(Status.CONFLICT).entity(entity).build(); 107 | } 108 | if (em.find(Catalog.class, id) == null) { 109 | return Response.status(Status.NOT_FOUND).build(); 110 | } 111 | try { 112 | entity = em.merge(entity); 113 | } catch (OptimisticLockException e) { 114 | return Response.status(Response.Status.CONFLICT) 115 | .entity(e.getEntity()).build(); 116 | } 117 | 118 | return Response.noContent().build(); 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /solution/cdservice/src/main/java/org/cdservice/rest/NewCrossOriginResourceSharingFilter.java: -------------------------------------------------------------------------------- 1 | package org.cdservice.rest; 2 | 3 | import javax.ws.rs.ext.Provider; 4 | import javax.ws.rs.container.ContainerResponseFilter; 5 | import javax.ws.rs.container.ContainerRequestContext; 6 | import javax.ws.rs.container.ContainerResponseContext; 7 | import org.springframework.stereotype.Component; 8 | 9 | @Provider 10 | @Component 11 | public class NewCrossOriginResourceSharingFilter 12 | implements 13 | ContainerResponseFilter { 14 | 15 | @Override 16 | public void filter(ContainerRequestContext request, 17 | ContainerResponseContext response) { 18 | response.getHeaders().putSingle("Access-Control-Allow-Origin", "*"); 19 | response.getHeaders().putSingle("Access-Control-Expose-Headers", 20 | "Location"); 21 | response.getHeaders().putSingle("Access-Control-Allow-Methods", 22 | "GET, POST, PUT, DELETE"); 23 | response.getHeaders() 24 | .putSingle("Access-Control-Allow-Headers", 25 | "Content-Type, User-Agent, X-Requested-With, X-Requested-By, Cache-Control"); 26 | response.getHeaders().putSingle("Access-Control-Allow-Credentials", 27 | "true"); 28 | } 29 | } -------------------------------------------------------------------------------- /solution/cdservice/src/main/java/org/cdservice/rest/RestApplication.java: -------------------------------------------------------------------------------- 1 | package org.cdservice.rest; 2 | 3 | import javax.ws.rs.core.Application; 4 | import javax.ws.rs.ApplicationPath; 5 | 6 | @ApplicationPath("/rest") 7 | public class RestApplication extends Application { 8 | } -------------------------------------------------------------------------------- /solution/cdservice/src/test/java/org/cdservice/DemoApplicationTests.java: -------------------------------------------------------------------------------- 1 | package org.cdservice; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class DemoApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /solution/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | org.cdstore 5 | project 6 | 1.0.0-SNAPSHOT 7 | pom 8 | project 9 | 10 | cdfront 11 | cdservice 12 | 13 | 14 | --------------------------------------------------------------------------------