diff --git a/apptest/build.gradle b/apptest/build.gradle new file mode 100644 index 0000000..e1559bd --- /dev/null +++ b/apptest/build.gradle @@ -0,0 +1,16 @@ +group 'rs' +version '1.0-SNAPSHOT' + +apply plugin: 'java' +apply plugin: 'war' + +sourceCompatibility = 1.8 + +repositories { + mavenCentral() +} + +dependencies { + providedCompile 'javax.servlet:javax.servlet-api:3.1.0' + testCompile group: 'junit', name: 'junit', version: '4.12' +} diff --git a/wild-docker-files/.env b/wild-docker-files/.env new file mode 100644 index 0000000..d43c36e --- /dev/null +++ b/wild-docker-files/.env @@ -0,0 +1 @@ +COMPOSE_PROJECT_NAME=wfcluster \ No newline at end of file diff --git a/wild-docker-files/Dockerfile b/wild-docker-files/Dockerfile index 4998f6a..2452619 100755 --- a/wild-docker-files/Dockerfile +++ b/wild-docker-files/Dockerfile @@ -1,17 +1,31 @@ FROM jboss/wildfly # Environment variable with default value -ARG APP_FILE=appfile.war +ARG WAR_FILE_FROM=appfile.war +ARG WAR_FILE_DEPLOY=${WAR_FILE_FROM} -RUN echo ${APP_FILE} +#RUN echo ${APP_FILE} -# Add your application to the deployment folder -ADD ${APP_FILE} /opt/jboss/wildfly/standalone/deployments/${APP_FILE} +USER root +# RUN yum install net-tools -y + +#setup zk module(8.0.2.2) +RUN mkdir -p /zk_lib && \ +mkdir -p /opt/jboss/wildfly/modules/system/layers/base/org/zkoss/zk/main && \ +curl -#L https://www.zkoss.org/zkdownload/downloadEvalFile?id=1884780989 | bsdtar -xf- -C /zk_lib && \ +find /zk_lib/zk-bin-8.0.2.2/dist/lib -name '*.jar' | xargs -I{} cp {} /opt/jboss/wildfly/modules/system/layers/base/org/zkoss/zk/main && \ +rm -rf ./zk_lib +COPY module_zk8.xml /opt/jboss/wildfly/modules/system/layers/base/org/zkoss/zk/main/module.xml -# Add standalone-ha.xml - set your own network settings -ADD standalone-ha-1.xml /opt/jboss/wildfly/standalone/configuration/standalone-ha-1.xml -ADD standalone-ha-2.xml /opt/jboss/wildfly/standalone/configuration/standalone-ha-2.xml -ADD standalone-ha-3.xml /opt/jboss/wildfly/standalone/configuration/standalone-ha-3.xml +# Add your application to the deployment folder +COPY ${WAR_FILE_FROM} /opt/jboss/wildfly/standalone/deployments/${WAR_FILE_DEPLOY} +COPY standalone-ha.xml /opt/jboss/wildfly/standalone/configuration/standalone-ha.xml +COPY startwf-ha.sh /opt/jboss/wildfly/bin/startwf-ha.sh # Add user for adminstration purpose RUN /opt/jboss/wildfly/bin/add-user.sh admin admin123 --silent +USER jboss + +EXPOSE 8080 9990 45688 + +CMD ["sh","-c","/opt/jboss/wildfly/bin/startwf-ha.sh"] \ No newline at end of file diff --git a/wild-docker-files/build.sh b/wild-docker-files/build.sh index 917213e..d664e70 100755 --- a/wild-docker-files/build.sh +++ b/wild-docker-files/build.sh @@ -1 +1,16 @@ -docker build -t wildfly-cluster --build-arg APP_FILE=apptest.war . +#!/bin/sh +warFrom="zkweb100.war" +warTo="zkweb.war" + +if [ "$1" != "" ] +then + warFrom=$1 +fi + +if [ "$2" != "" ] +then + warTo=$2 +fi +echo "$warFrom => $warTo" + +docker build -t shihxuancheng/wildfly-cluster --build-arg WAR_FILE_FROM=$warFrom --build-arg WAR_FILE_DEPLOY=$warTo . diff --git a/wild-docker-files/cleanup.sh b/wild-docker-files/cleanup.sh new file mode 100755 index 0000000..3a57856 --- /dev/null +++ b/wild-docker-files/cleanup.sh @@ -0,0 +1,3 @@ +docker image prune -f +docker volume prune -f +docker network prune -f \ No newline at end of file diff --git a/wild-docker-files/docker-compose.yml b/wild-docker-files/docker-compose.yml new file mode 100644 index 0000000..ba82746 --- /dev/null +++ b/wild-docker-files/docker-compose.yml @@ -0,0 +1,57 @@ +version: '3' +services: + # wildfly cluster node-1 + wild1: + hostname: wild1 + image: shihxuancheng/wildfly-cluster + # container_name: "wild1" + restart: always + networks: + - "wildnetwork" + labels: + - "traefik.backend=wild1" + - "traefik.frontend.rule=PathPrefix:/zkweb" + - "traefik.backend.loadbalancer.method=drr" + # - "traefik.backend.loadbalancer.stickiness=true" + +# wildfly cluster node-2 + wild2: + hostname: wild2 + image: shihxuancheng/wildfly-cluster + # container_name: "wild2" + restart: always + networks: + - "wildnetwork" + labels: + - "traefik.backend=wild1" + - "traefik.frontend.rule=PathPrefix:/zkweb" + - "traefik.backend.loadbalancer.method=drr" + # - "traefik.backend.loadbalancer.stickiness=true" + +# frontend lod balance(traefik) + wild-balancer: + image: traefik + hostname: wild-balancer + container_name: "wild-balancer" + command: --web --docker --docker.domain=docker.localhost --logLevel=DEBUG + ports: + - "80:80" + - "9090:8080" + volumes: + - /var/run/docker.sock:/var/run/docker.sock + #- ./traefik.toml:/traefik.toml + networks: + - "wildnetwork" + labels: + - "traefik.frontend.rule=PathPrefix:/zkweb" + - "traefik.enable=false" +networks: + wildnetwork: + driver: bridge + ipam: + driver: default + config: + - subnet: 172.28.0.0/16 + + + diff --git a/wild-docker-files/env.list b/wild-docker-files/env.list deleted file mode 100755 index 690f28a..0000000 --- a/wild-docker-files/env.list +++ /dev/null @@ -1,10 +0,0 @@ -# automatically created environment variables (docker links) -TOMCAT_1_PORT_8080_TCP_ADDR=wild1 -TOMCAT_2_PORT_8080_TCP_ADDR=wild2 -TOMCAT_3_PORT_8080_TCP_ADDR=wild3 - -# special environment variables -TOMCAT_PATH=/apptest -TOMCAT_REMOTE_PORT=8080 -TOMCAT_REMOTE_PATH=/apptest -TOMCAT_HOSTNAME=wild-balancer diff --git a/wild-docker-files/module_zk8.xml b/wild-docker-files/module_zk8.xml new file mode 100644 index 0000000..80b6e86 --- /dev/null +++ b/wild-docker-files/module_zk8.xml @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/wild-docker-files/network-create.sh b/wild-docker-files/network-create.sh deleted file mode 100755 index c462cf5..0000000 --- a/wild-docker-files/network-create.sh +++ /dev/null @@ -1,7 +0,0 @@ -docker network rm wildnetwork -docker network create \ - --driver=bridge \ - --subnet=172.28.0.0/16 \ - --ip-range=172.28.5.0/24 \ - --gateway=172.28.5.254 \ - wildnetwork diff --git a/wild-docker-files/remove.sh b/wild-docker-files/remove.sh deleted file mode 100755 index 9d7358c..0000000 --- a/wild-docker-files/remove.sh +++ /dev/null @@ -1,7 +0,0 @@ -docker rm -f wild1 -docker rm -f wild2 -docker rm -f wild3 -docker rm -f wild-balancer -docker rmi -f wildfly-cluster -docker rmi -f jboss/wildfly -docker rmi -f jasonwyatt/nginx-loadbalancer \ No newline at end of file diff --git a/wild-docker-files/run.sh b/wild-docker-files/run.sh deleted file mode 100755 index d393634..0000000 --- a/wild-docker-files/run.sh +++ /dev/null @@ -1,5 +0,0 @@ -docker run -d --name wild1 -h wild1 -p 8080:8080 -p 9990:9990 --network=wildnetwork --ip 172.28.5.1 wildfly-cluster /opt/jboss/wildfly/bin/standalone.sh -c standalone-ha-1.xml -u 230.0.0.4 -docker run -d --name wild2 -h wild2 -p 8081:8080 -p 9991:9990 --network=wildnetwork --ip 172.28.5.2 wildfly-cluster /opt/jboss/wildfly/bin/standalone.sh -c standalone-ha-2.xml -u 230.0.0.4 -docker run -d --name wild3 -h wild3 -p 8082:8080 -p 9992:9990 --network=wildnetwork --ip 172.28.5.3 wildfly-cluster /opt/jboss/wildfly/bin/standalone.sh -c standalone-ha-3.xml -u 230.0.0.4 - -docker run -d --name wild-balancer -p 80:80 --link wild1:wild1 --link wild2:wild2 --link wild3:wild3 --env-file ./env.list --network=wildnetwork --ip 172.28.5.4 jasonwyatt/nginx-loadbalancer diff --git a/wild-docker-files/standalone-ha-2.xml b/wild-docker-files/standalone-ha-2.xml deleted file mode 100755 index 8d73c9b..0000000 --- a/wild-docker-files/standalone-ha-2.xml +++ /dev/null @@ -1,468 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE - h2 - - sa - sa - - - - - org.h2.jdbcx.JdbcDataSource - - - - - - - - - false - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ${jboss.bind.address:127.0.0.1} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/wild-docker-files/standalone-ha-3.xml b/wild-docker-files/standalone-ha-3.xml deleted file mode 100755 index 31be5d0..0000000 --- a/wild-docker-files/standalone-ha-3.xml +++ /dev/null @@ -1,468 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE - h2 - - sa - sa - - - - - org.h2.jdbcx.JdbcDataSource - - - - - - - - - false - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ${jboss.bind.address:127.0.0.1} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/wild-docker-files/standalone-ha-1.xml b/wild-docker-files/standalone-ha.xml similarity index 70% rename from wild-docker-files/standalone-ha-1.xml rename to wild-docker-files/standalone-ha.xml index 2416ad5..4dbd945 100755 --- a/wild-docker-files/standalone-ha-1.xml +++ b/wild-docker-files/standalone-ha.xml @@ -1,6 +1,6 @@ - + - + @@ -27,6 +27,8 @@ + + @@ -72,7 +74,8 @@ - + + @@ -125,7 +128,7 @@ - + @@ -137,7 +140,8 @@ - + + jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE @@ -175,7 +179,7 @@ - + @@ -202,7 +206,12 @@ - + + + + @@ -213,12 +222,114 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + @@ -226,18 +337,15 @@ - + - - - - + @@ -249,7 +357,7 @@ - + @@ -258,7 +366,7 @@ - + @@ -278,16 +386,16 @@ - + - + - + @@ -300,10 +408,10 @@ - + - - + + @@ -323,12 +431,12 @@ - + - + @@ -339,11 +447,11 @@ - + - + @@ -353,7 +461,7 @@ - + @@ -392,15 +500,16 @@ - + + - + @@ -410,6 +519,7 @@ + @@ -420,7 +530,7 @@ - + @@ -434,17 +544,17 @@ - + - + - + - + @@ -455,10 +565,8 @@ - - - + diff --git a/wild-docker-files/start.sh b/wild-docker-files/start.sh deleted file mode 100755 index 9b9ed50..0000000 --- a/wild-docker-files/start.sh +++ /dev/null @@ -1,3 +0,0 @@ -./network-create.sh -./build.sh -./run.sh \ No newline at end of file diff --git a/wild-docker-files/startwf-ha.sh b/wild-docker-files/startwf-ha.sh new file mode 100755 index 0000000..528ddef --- /dev/null +++ b/wild-docker-files/startwf-ha.sh @@ -0,0 +1,11 @@ +# IPADDRESS=$(ifconfig | grep -A 1 'eth0' | tail -1 | awk -F ' ' '{print $2}') +IPADDRESS=$(hostname -i) +MCASTADDRESS=234.0.0.4 +/opt/jboss/wildfly/bin/standalone.sh -c standalone-ha.xml \ +-u ${MCASTADDRESS} \ +-b ${IPADDRESS} \ +-Djboss.bind.address=${IPADDRESS} \ +-Djboss.bind.address.management=${IPADDRESS} \ +-Djboss.bind.address.private=${IPADDRESS} \ +-Djboss.node.name=$(hostname) \ +-u=${MCASTADDRESS} \ No newline at end of file diff --git a/wild-docker-files/stop.sh b/wild-docker-files/stop.sh deleted file mode 100644 index bff0bda..0000000 --- a/wild-docker-files/stop.sh +++ /dev/null @@ -1,4 +0,0 @@ -docker stop wild1 -docker stop wild2 -docker stop wild3 -docker stop wild-balance \ No newline at end of file diff --git a/wild-docker-files/traefik.toml b/wild-docker-files/traefik.toml new file mode 100644 index 0000000..3702a19 --- /dev/null +++ b/wild-docker-files/traefik.toml @@ -0,0 +1,138 @@ +################################################################ +# Global configuration +################################################################ + +# Enable debug mode +# +# Optional +# Default: false +# +# debug = true + +# Log level +# +# Optional +# Default: "ERROR" +# +logLevel = "ERROR" + +# Entrypoints to be used by frontends that do not specify any entrypoint. +# Each frontend can specify its own entrypoints. +# +# Optional +# Default: ["http"] +# +defaultEntryPoints = ["http", "https"] + +# Entrypoints definition +# +# Optional +# Default: +[entryPoints] + [entryPoints.http] + address = ":80" + +# Traefik logs +# Enabled by default and log to stdout +# +# Optional +# +# [traefikLog] + +# Sets the filepath for the traefik log. If not specified, stdout will be used. +# Intermediate directories are created if necessary. +# +# Optional +# Default: os.Stdout +# +# filePath = "log/traefik.log" + +# Format is either "json" or "common". +# +# Optional +# Default: "common" +# +# format = "common" + +# Enable access logs +# By default it will write to stdout and produce logs in the textual +# Common Log Format (CLF), extended with additional fields. +# +# Optional +# +# [accessLog] + +# Sets the file path for the access log. If not specified, stdout will be used. +# Intermediate directories are created if necessary. +# +# Optional +# Default: os.Stdout +# +# filePath = "/path/to/log/log.txt" + +# Format is either "json" or "common". +# +# Optional +# Default: "common" +# +# format = "common" + +################################################################ +# Web configuration backend +################################################################ + +# Enable web configuration backend +[web] + +# Web administration port +# +# Required +# +address = ":8080" + +################################################################ +# Docker configuration backend +################################################################ + +# Enable Docker configuration backend +[docker] + +# Docker server endpoint. Can be a tcp or a unix socket endpoint. +# +# Required +# Default: "unix:///var/run/docker.sock" +# +# endpoint = "tcp://10.10.10.10:2375" + +# Default domain used. +# Can be overridden by setting the "traefik.domain" label on a container. +# +# Optional +# Default: "" +# +domain = "docker.localhost" + +# Expose containers by default in traefik +# +# Optional +# Default: true +# +exposedbydefault = true + +# Enable watch docker changes. +# +# Optional +# +watch=true + +# Use the IP address from the binded port instead of the inner network one. +# For specific use-case :) +# +# Optional +# Default: false +# +# usebindportip = true + +################################################################ +# frontends definitation +################################################################ \ No newline at end of file diff --git a/wild-docker-files/update.sh b/wild-docker-files/update.sh new file mode 100755 index 0000000..b78342b --- /dev/null +++ b/wild-docker-files/update.sh @@ -0,0 +1,7 @@ +#!/bin/bash +for x in $(docker ps -q -f "ancestor=shihxuancheng/wildfly-cluster") +do + docker stop $x + docker cp ./$1 $x:/opt/jboss/wildfly/standalone/deployments/$2 + docker start $x +done \ No newline at end of file diff --git a/wild-docker-files/zkweb100.war b/wild-docker-files/zkweb100.war new file mode 100644 index 0000000..893bc4d Binary files /dev/null and b/wild-docker-files/zkweb100.war differ diff --git a/wild-docker-files/zkweb101.war b/wild-docker-files/zkweb101.war new file mode 100644 index 0000000..ac1ea7c Binary files /dev/null and b/wild-docker-files/zkweb101.war differ diff --git a/zkweb/src/main/java/com/wanhai/zk/TestVM.java b/zkweb/src/main/java/com/wanhai/zk/TestVM.java new file mode 100644 index 0000000..9605355 --- /dev/null +++ b/zkweb/src/main/java/com/wanhai/zk/TestVM.java @@ -0,0 +1,77 @@ +package com.wanhai.zk; + +import org.zkoss.Version; +import org.zkoss.bind.annotation.AfterCompose; +import org.zkoss.bind.annotation.Command; +import org.zkoss.bind.annotation.ContextParam; +import org.zkoss.bind.annotation.Init; +import org.zkoss.zk.ui.Executions; +import org.zkoss.zk.ui.Session; +import org.zkoss.zk.ui.Sessions; +import org.zkoss.zk.ui.util.Clients; + +import javax.servlet.http.HttpSession; +import java.io.Serializable; +import java.net.InetAddress; + +/** + * Created by shihxuancheng on 2017/12/6. + */ +public class TestVM implements Serializable { + @Init + public void init() { + } + + @AfterCompose + public void afterCompose() { + } + + public String getServerIP() { +// HttpServletRequest request = (HttpServletRequest)Executions.getCurrent().getNativeRequest(); + try { +// return Executions.getCurrent().getLocalAddr(); + return InetAddress.getLocalHost().getHostAddress(); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + public String getHostName() { + try { +// return Executions.getCurrent().getServerName(); + return InetAddress.getLocalHost().getCanonicalHostName(); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + public String getSessionId() { + return ((HttpSession) Executions.getCurrent().getSession().getNativeSession()).getId(); + } + + public String getGuestName() { + return String.valueOf(Sessions.getCurrent().getAttribute("user")); + } + + public void setGuestName(String guestName) { + Sessions.getCurrent(true).setAttribute("user",guestName); + } + + @Command("test") + public void onTest() { + try { + StringBuilder strMsg = new StringBuilder(); + strMsg.append("Requset handled by: ") + .append(InetAddress.getLocalHost().getCanonicalHostName() + "/" + InetAddress.getLocalHost().getHostAddress()) + .append("\n") + .append("SessionId: ") + .append(((HttpSession) Executions.getCurrent().getSession().getNativeSession()).getId()); + Clients.showNotification(strMsg.toString()); + } catch (Exception e) { + e.printStackTrace(); + } + } + +} diff --git a/zkweb/src/main/webapp/WEB-INF/jboss-deployment-structure.xml b/zkweb/src/main/webapp/WEB-INF/jboss-deployment-structure.xml new file mode 100644 index 0000000..abb0992 --- /dev/null +++ b/zkweb/src/main/webapp/WEB-INF/jboss-deployment-structure.xml @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/zkweb/src/main/webapp/WEB-INF/jboss-web.xml b/zkweb/src/main/webapp/WEB-INF/jboss-web.xml new file mode 100644 index 0000000..e993100 --- /dev/null +++ b/zkweb/src/main/webapp/WEB-INF/jboss-web.xml @@ -0,0 +1,3 @@ + + /zkweb + diff --git a/zkweb/src/main/webapp/WEB-INF/web.xml b/zkweb/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000..8e532dc --- /dev/null +++ b/zkweb/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,195 @@ + + + + + + MyApp + + + + + ZK listener for session cleanup + org.zkoss.zk.ui.http.HttpSessionListener + + + ZK loader for ZUML pages + zkLoader + org.zkoss.zk.ui.http.DHtmlLayoutServlet + + + + update-uri + /zkau + + + + 1 + + + zkLoader + *.zul + + + zkLoader + *.zhtml + + + + The asynchronous update engine for ZK + auEngine + org.zkoss.zk.au.http.DHtmlUpdateServlet + + + + + + auEngine + /zkau/* + + + + + + + + + + 60 + + + + + doc + application/vnd.ms-word + + + gif + image/gif + + + htm + text/html + + + html + text/html + + + jpeg + image/jpeg + + + jpg + image/jpeg + + + js + text/javascript + + + pdf + application/pdf + + + png + image/png + + + txt + text/plain + + + xls + application/vnd.ms-excel + + + xml + text/xml + + + zhtml + text/html + + + zul + text/html + + + + index.zul + index.zhtml + index.html + index.htm + + + \ No newline at end of file diff --git a/zkweb/src/main/webapp/WEB-INF/zk.xml b/zkweb/src/main/webapp/WEB-INF/zk.xml new file mode 100644 index 0000000..fe2f7ba --- /dev/null +++ b/zkweb/src/main/webapp/WEB-INF/zk.xml @@ -0,0 +1,5 @@ + + + org.zkoss.zk.ui.http.SerializableUiFactory + + \ No newline at end of file diff --git a/zkweb/src/main/webapp/index.zul b/zkweb/src/main/webapp/index.zul new file mode 100644 index 0000000..d2e755c --- /dev/null +++ b/zkweb/src/main/webapp/index.zul @@ -0,0 +1,48 @@ + + + + + + + + + + + + Server IP: + + + + + + + Server Name: + + + + + + + Session: + + + + + + + + + + + + + +