Commit f5c55dc2 authored by Administrator's avatar Administrator

Adds the JSF and EAR projects

This commit adds the JSF project with a web application that allows the
management of owners (by the administrators) and pets (by the owners).
The JSF project includes the functional tests for the owners management
page.

The EAR project only contains a POM that creates an EAR distribution of
the system.
parent 7d038626
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>es.uvigo.esei.xcs</groupId>
<artifactId>sample</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>ear</artifactId>
<packaging>ear</packaging>
<name>EAR</name>
<description>XCS Sample - EAR</description>
<dependencies>
<dependency>
<groupId>es.uvigo.esei.xcs</groupId>
<artifactId>domain</artifactId>
</dependency>
<dependency>
<groupId>es.uvigo.esei.xcs</groupId>
<artifactId>service</artifactId>
<version>${project.version}</version>
<type>ejb</type>
</dependency>
<dependency>
<groupId>es.uvigo.esei.xcs</groupId>
<artifactId>rest</artifactId>
<version>${project.version}</version>
<type>war</type>
</dependency>
<dependency>
<groupId>es.uvigo.esei.xcs</groupId>
<artifactId>jsf</artifactId>
<version>${project.version}</version>
<type>war</type>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-ear-plugin</artifactId>
<configuration>
<defaultLibBundleDir>lib/</defaultLibBundleDir>
<skinnyWars>true</skinnyWars>
</configuration>
</plugin>
</plugins>
</build>
</project>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>es.uvigo.esei.xcs</groupId>
<artifactId>sample</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>jsf</artifactId>
<packaging>war</packaging>
<name>JSF</name>
<description>XCS Sample - JSF</description>
<dependencies>
<!-- General -->
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>es.uvigo.esei.xcs</groupId>
<artifactId>service</artifactId>
<scope>provided</scope>
</dependency>
<!-- Testing -->
<dependency>
<groupId>es.uvigo.esei.xcs</groupId>
<artifactId>tests</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>java-hamcrest</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.easymock</groupId>
<artifactId>easymock</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jboss.arquillian.junit</groupId>
<artifactId>arquillian-junit-container</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jboss.arquillian.extension</groupId>
<artifactId>arquillian-persistence-dbunit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jboss.arquillian.graphene</groupId>
<artifactId>graphene-webdriver</artifactId>
<type>pom</type>
<scope>test</scope>
</dependency>
</dependencies>
</project>
\ No newline at end of file
# Connect to Wildfly instance
connect
# Create Oracle JDBC Driver Module
# If the module already exists, Wildfly will output a message saying that the module already exists and the script exits.
module add \
--name=org.postgre \
--resources=${settings.localRepository}/org/postgresql/postgresql/9.3-1102-jdbc41/postgresql-9.3-1102-jdbc41.jar \
--dependencies=javax.api,javax.transaction.api
# Add Driver Properties
/subsystem=datasources/jdbc-driver=postgre: \
add( \
driver-name="postgre", \
driver-module-name="org.postgre")
\ No newline at end of file
package es.uvigo.esei.xcs.jsf;
import java.security.Principal;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.context.FacesContext;
import javax.inject.Inject;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
@ManagedBean(name = "login")
@RequestScoped
public class LoginManagedBean {
@Inject
private Principal currentUserPrincipal;
@Inject
private HttpServletRequest request;
private String login;
private String password;
private boolean error = false;
public String getLogin() {
return login;
}
public void setLogin(String login) {
this.login = login;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public boolean isError() {
return error;
}
public String doLogin() {
try {
request.login(this.getLogin(), this.getPassword());
this.error = false;
if (this.isAdmin()) {
return redirectTo(this.getAdminViewId());
} else if (this.isOwner()) {
return redirectTo(this.getOwnerViewId());
} else {
return redirectTo(this.getViewId());
}
} catch (ServletException e) {
this.error = true;
return this.getViewId();
}
}
public String doLogout() throws ServletException {
request.logout();
return redirectTo("/index.xhtml");
}
public Principal getCurrentUser() {
return this.currentUserPrincipal;
}
private String redirectTo(String url) {
return url + "?faces-redirect=true";
}
private String getViewId() {
return FacesContext.getCurrentInstance().getViewRoot().getViewId();
}
private String getOwnerViewId() {
return "/owner/pets.xhtml";
}
private String getAdminViewId() {
return "/admin/owners.xhtml";
}
private boolean isAdmin() {
return this.isUserInRole("ADMIN");
}
private boolean isOwner() {
return this.isUserInRole("OWNER");
}
private boolean isUserInRole(String role) {
return FacesContext.getCurrentInstance().getExternalContext()
.isUserInRole(role);
}
}
\ No newline at end of file
package es.uvigo.esei.xcs.jsf;
import static java.util.stream.Collectors.joining;
import java.util.List;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;
import javax.inject.Inject;
import es.uvigo.esei.xcs.domain.entities.Owner;
import es.uvigo.esei.xcs.domain.entities.Pet;
import es.uvigo.esei.xcs.service.OwnerService;
@ManagedBean(name = "owner")
@SessionScoped
public class OwnerManagerdBean {
@Inject
private OwnerService service;
private String login;
private String password;
private Owner currentOwner;
private String errorMessage;
public String getLogin() {
return login;
}
public void setLogin(String name) {
this.login = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getErrorMessage() {
return errorMessage;
}
public boolean isError() {
return this.errorMessage != null;
}
public boolean isEditing() {
return this.currentOwner != null;
}
public List<Owner> getOwners() {
return this.service.list();
}
public String getPetNames(String login) {
return this.service.getPets(login).stream()
.map(Pet::getName)
.collect(joining(", "));
}
public String edit(Owner owner) {
this.currentOwner = owner;
this.login = this.currentOwner.getLogin();
return this.getViewId();
}
public String cancelEditing() {
this.clear();
return this.getViewId();
}
public String remove(String login) {
this.service.remove(login);
return redirectTo(this.getViewId());
}
public String store() {
try {
if (this.isEditing()) {
this.currentOwner.changePassword(this.password);
this.service.update(this.currentOwner);
} else {
this.service.create(new Owner(login, password));
}
this.clear();
return redirectTo(this.getViewId());
} catch (Throwable t) {
this.errorMessage = t.getMessage();
return this.getViewId();
}
}
private void clear() {
this.login = null;
this.password = null;
this.errorMessage = null;
this.currentOwner = null;
}
private String redirectTo(String url) {
return url + "?faces-redirect=true";
}
private String getViewId() {
return FacesContext.getCurrentInstance().getViewRoot().getViewId();
}
}
package es.uvigo.esei.xcs.jsf;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;
import javax.inject.Inject;
import es.uvigo.esei.xcs.domain.entities.AnimalType;
import es.uvigo.esei.xcs.domain.entities.Pet;
import es.uvigo.esei.xcs.service.PetService;
@ManagedBean(name = "pet")
@SessionScoped
public class PetManagedBean {
@Inject
private PetService service;
private String name;
private Date birth;
private AnimalType animal;
private Pet currentPet;
private String errorMessage;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getBirth() {
return birth;
}
public void setBirth(Date birth) {
this.birth = birth;
}
public String getAnimal() {
return Optional.ofNullable(this.animal)
.map(AnimalType::name)
.orElse(null);
}
public void setAnimal(String animal) {
this.animal = AnimalType.valueOf(animal);
}
public String getErrorMessage() {
return errorMessage;
}
public boolean isError() {
return this.errorMessage != null;
}
public boolean isEditing() {
return this.currentPet != null;
}
public List<Pet> getPets() {
return this.service.list();
}
public String edit(Pet pet) {
this.currentPet = pet;
this.name = this.currentPet.getName();
this.birth = this.currentPet.getBirth();
this.animal = this.currentPet.getAnimal();
return this.getViewId();
}
public String cancelEditing() {
this.clear();
return this.getViewId();
}
public String remove(int id) {
this.service.remove(id);
return redirectTo(this.getViewId());
}
public String store() {
try {
if (this.isEditing()) {
this.currentPet.setName(this.name);
this.currentPet.setBirth(this.birth);
this.currentPet.setAnimal(this.animal);
this.service.update(this.currentPet);
} else {
this.service.create(new Pet(name, animal, birth));
}
this.clear();
return redirectTo(this.getViewId());
} catch (Throwable t) {
this.errorMessage = t.getMessage();
return this.getViewId();
}
}
private void clear() {
this.currentPet = null;
this.name = null;
this.birth = null;
this.animal = null;
this.errorMessage = null;
}
private String redirectTo(String url) {
return url + "?faces-redirect=true";
}
private String getViewId() {
return FacesContext.getCurrentInstance().getViewRoot().getViewId();
}
}
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"
version="2.1">
<persistence-unit name="runtime">
<jta-data-source>java:jboss/datasources/xcs</jta-data-source>
<class>es.uvigo.esei.xcs.domain.entities.Owner</class>
<class>es.uvigo.esei.xcs.domain.entities.Pet</class>
<class>es.uvigo.esei.xcs.domain.entities.Administrator</class>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
<property name="hibernate.hbm2ddl.auto" value="update"/>
<property name="hibernate.show_sql" value="false"/>
</properties>
</persistence-unit>
</persistence>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
bean-discovery-mode="all">
</beans>
<?xml version="1.0" encoding="UTF-8"?>
<jboss-web>
<security-domain>xcs-sample-security-domain</security-domain>
</jboss-web>
\ No newline at end of file
<html lang="en" xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:a="http://xmlns.jcp.org/jsf/passthrough">
<h:head>
<title>Pet Store</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" />
</h:head>
<h:body>
<div class="container">
<nav class="navbar navbar-default">
<div class="container-fluid">
<div class="navbar-header">
<a class="navbar-brand" href="#">Pet Store</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<h:form rendered="#{login.currentUser.name != 'anonymous'}" class="navbar-form navbar-right">
<span>Current User: #{login.currentUser}</span>
<h:commandButton id="submit" class="btn btn-success" value="Logout" action="#{login.doLogout}" />
</h:form>
<h:form id="login-form" class="navbar-form navbar-right" rendered="#{login.currentUser == 'anonymous'}">
<div class="form-group">
<h:inputText id="login-field" class="#{login.currentUser == 'anonymous' and !login.error ? 'form-control' : 'form-control alert-danger'}"
value="#{login.login}" a:placeholder="login"></h:inputText>
<h:inputSecret id="password-field" class="#{login.currentUser == 'anonymous' and !login.error ? 'form-control' : 'form-control alert-danger'}"
value="#{login.password}" a:placeholder="password"></h:inputSecret>
</div>
<h:commandButton id="submit" class="btn btn-success" value="Login" action="#{login.doLogin}" />
</h:form>
</div>
</div>
</nav>
<div class="jumbotron">
<ui:insert name="jumbotron"/>
</div>
<div class="row marketing">
<ui:insert name="content"/>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
</h:body>
</html>
\ No newline at end of file
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<display-name>Pet Store JSF</display-name>
<welcome-file-list>
<welcome-file>/faces/index.xhtml</welcome-file>
</welcome-file-list>
<!--Defining security constraint for type of roles available -->
<security-constraint>
<web-resource-collection>
<web-resource-name>admin</web-resource-name>
<url-pattern>/faces/admin/*</url-pattern>
<http-method>POST</http-method>
<http-method>GET</http-method>
<http-method>PUT</http-method>
<http-method>DELETE</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>ADMIN</role-name>
</auth-constraint>
</security-constraint>
<security-constraint>
<web-resource-collection>
<web-resource-name>owner</web-resource-name>
<url-pattern>/faces/owner/*</url-pattern>
<http-method>POST</http-method>
<http-method>GET</http-method>
<http-method>PUT</http-method>
<http-method>DELETE</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>OWNER</role-name>
</auth-constraint>
</security-constraint>
<!--Defining security constraint for type of roles available -->
<!--Denining security role -->
<security-role>
<role-name>ADMIN</role-name>
</security-role>
<security-role>
<role-name>OWNER</role-name>
</security-role>
<!--Denining security role -->
</web-app>
\ No newline at end of file
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:a="http://xmlns.jcp.org/jsf/passthrough">
<head>
<title>Pet Store - Owners</title>
</head>
<body>
<ui:composition template="../WEB-INF/template.xhtml">
<ui:define name="jumbotron">
<h2>Owner</h2>
<h:panelGroup class="row">
<h:form id="owner-form">
<h:outputLabel for="name-field">Name</h:outputLabel>
<h:inputText id="name-field" class="form-control" a:placeholder="Owner name" value="#{owner.login}" readonly="#{owner.editing}"></h:inputText>
<h:outputLabel for="password-field">Password</h:outputLabel>
<h:inputSecret id="password-field" class="form-control" a:placeholder="Owner password" value="#{owner.password}"></h:inputSecret>
<h:commandButton id="submit-button" class="btn btn-default" value="Store" action="#{owner.store}" />
<h:commandButton id="cancel-button" class="btn btn-default" value="Cancel" action="#{owner.cancelEditing()}" rendered="#{owner.editing}"/>
</h:form>
</h:panelGroup>
<div class="row">
<h:panelGroup id="store-error" class="alert alert-danger" role="alert" rendered="#{owner.error}">
<span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span>
Error: #{owner.errorMessage}
</h:panelGroup>
</div>
</ui:define>
<ui:define name="content">
<h:dataTable id="owners-table"
value="#{owner.owners}" var="c"
styleClass="table table-striped table-bordered"
columnClasses="owners-table-login,owners-table-password,owners-table-pets,owners-table-options"
>
<h:column>
<f:facet name="header">Login</f:facet>
#{c.login}
</h:column>
<h:column>
<f:facet name="header">Password</f:facet>
#{c.password}
</h:column>
<h:column>
<f:facet name="header">Pets</f:facet>
#{owner.getPetNames(c.login)}
</h:column>
<h:column>
<h:form>
<h:commandButton class="owners-table-remove" value="Remove" action="#{owner.remove(c.login)}"/>
<h:commandButton class="owners-table-edit" value="Edit" action="#{owner.edit(c)}"/>
</h:form>
</h:column>
</h:dataTable>
</ui:define>
</ui:composition>
</body>
</html>
\ No newline at end of file
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:a="http://xmlns.jcp.org/jsf/passthrough">
<head>
<title>Pet Store - Index</title>
</head>
<body>
<ui:composition template="./WEB-INF/template.xhtml">
<ui:define name="jumbotron">
<h2>Welcome!</h2>
<div>This is the Pet Store web page, where you can manage your pets. Please, login to continue.</div>
</ui:define>
</ui:composition>
</body>
</html>
\ No newline at end of file
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:a="http://xmlns.jcp.org/jsf/passthrough">
<head>
<title>Pet Store - Pets</title>
</head>
<body>
<ui:composition template="../WEB-INF/template.xhtml">
<ui:define name="jumbotron">
<h2>New Pet</h2>
<h:panelGroup class="row">
<h:form>
<h:inputText class="form-control" a:placeholder="Pet name" value="#{pet.name}"></h:inputText>
<h:inputText value="#{pet.birth}" size="20" required="true" label="Receipt Date" class="form-control">
<f:convertDateTime pattern="yyyy-M-d hh:mm:ss" />
</h:inputText>
<h:selectOneMenu value="#{pet.animal}" class="form-control" a:placeholder="Birth (YYYY-MM-DD hh:mm:ss)">
<f:selectItem itemValue="BIRD" itemLabel="Bird" />
<f:selectItem itemValue="CAT" itemLabel="Cat" />
<f:selectItem itemValue="DOG" itemLabel="Dog" />
</h:selectOneMenu>
<h:commandButton id="submit" class="btn btn-default" value="Store" action="#{pet.store()}" />
<h:commandButton id="cancel" class="btn btn-default" value="Cancel" action="#{pet.cancelEditing()}" rendered="#{pet.editing}"/>
</h:form>
</h:panelGroup>
<div class="row">
<h:panelGroup class="alert alert-danger" role="alert" rendered="#{pet.error}">
<span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span>
Error: #{pet.errorMessage}
</h:panelGroup>
</div>
</ui:define>
<ui:define name="content">
<h:dataTable value="#{pet.pets}" var="p" styleClass="table table-striped table-bordered">
<h:column>
<f:facet name="header">Name</f:facet>
#{p.name}
</h:column>
<h:column>
<f:facet name="header">Birth</f:facet>
<h:outputText value="#{p.birth}">
<f:convertDateTime pattern="yyyy-M-d hh:mm:ss" />
</h:outputText>
</h:column>
<h:column>
<f:facet name="header">Type</f:facet>
#{p.animal}
</h:column>
<h:column>
<h:form>
<h:commandButton value="Remove" type="submit" action="#{pet.remove(p.id)}"/>
<h:commandButton value="Edit" action="#{pet.edit(p)}"/>
</h:form>
</h:column>
</h:dataTable>
</ui:define>
</ui:composition>
</body>
</html>
\ No newline at end of file
This diff is collapsed.
package es.uvigo.esei.xcs.jsf.pages;
import static org.jboss.arquillian.graphene.Graphene.guardHttp;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
public class LoginForm {
@FindBy(id = "login-form:login-field")
private WebElement inputLogin;
@FindBy(id = "login-form:password-field")
private WebElement inputPassword;
@FindBy(id = "login-form:submit")
private WebElement buttonSubmit;
public void login(String login, String password) {
inputLogin.clear();
inputPassword.clear();
inputLogin.sendKeys(login);
inputPassword.sendKeys(password);
guardHttp(buttonSubmit).click();
}
}
package es.uvigo.esei.xcs.jsf.pages;
import static org.hamcrest.core.StringContains.containsString;
import static org.junit.Assert.assertThat;
import org.jboss.arquillian.drone.api.annotation.Drone;
import org.jboss.arquillian.graphene.page.Location;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.support.FindBy;
@Location("faces/index.xhtml")
public class LoginPage {
@Drone
private WebDriver browser;
@FindBy(id = "login-form")
private LoginForm loginForm;
public void login(String login, String password) {
this.loginForm.login(login, password);
}
public void assertOnLoginPage() {
assertThat(browser.getCurrentUrl(), containsString("/faces/index.xhtml"));
}
}
package es.uvigo.esei.xcs.jsf.pages;
import static org.jboss.arquillian.graphene.Graphene.guardHttp;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
public class OwnerForm {
@FindBy(id = "owner-form:name-field")
private WebElement fieldName;
@FindBy(id = "owner-form:password-field")
private WebElement fieldPassword;
@FindBy(id = "owner-form:submit-button")
private WebElement buttonSubmit;
@FindBy(id = "owner-form:cancel-button")
private WebElement buttonCancel;
public void setName(String name) {
this.fieldName.sendKeys(name);
}
public void setPassword(String password) {
this.fieldPassword.sendKeys(password);
}
public String getName() {
return this.fieldName.getText();
}
public String getPassword() {
return this.fieldPassword.getText();
}
public void submit() {
guardHttp(this.buttonSubmit).click();
}
public void cancel() {
guardHttp(this.buttonCancel).click();
}
public boolean isEditing() {
return this.fieldName.getAttribute("readonly") != null;
}
}
package es.uvigo.esei.xcs.jsf.pages;
import static org.hamcrest.core.StringContains.containsString;
import static org.junit.Assert.assertThat;
import org.jboss.arquillian.drone.api.annotation.Drone;
import org.jboss.arquillian.graphene.GrapheneElement;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.support.FindBy;
import es.uvigo.esei.xcs.domain.entities.Owner;
public class OwnersPage {
@Drone
private WebDriver browser;
@FindBy(id = "owner-form")
private OwnerForm formOwner;
@FindBy(id = "owners-table")
private OwnersTable tableOwners;
// GrapheneElement adds "isPresent()" to WebElement.
@FindBy(id = "store-error")
private GrapheneElement storeError;
public void assertOnOwnersPage() {
assertThat(browser.getCurrentUrl(), containsString("/faces/admin/owners.xhtml"));
}
public boolean areOwnersInTable(Owner ... owners) {
for (Owner owner : owners) {
if (!this.isOwnerInTable(owner))
return false;
}
return true;
}
public boolean isOwnerInTable(Owner owner) {
return this.tableOwners.hasOwner(owner);
}
public void createOwner(String login, String password) {
this.formOwner.setName(login);
this.formOwner.setPassword(password);
this.formOwner.submit();
}
public void removeOwner(Owner owner) {
this.tableOwners.remove(owner);
}
public void editOwner(Owner owner) {
this.tableOwners.edit(owner);
}
public void changePassword(String password) {
this.formOwner.setPassword(password);
this.formOwner.submit();
}
public boolean isErrorMessageVisible() {
return storeError.isPresent();
}
public boolean isEditing() {
return this.formOwner.isEditing();
}
public void cancelEdit() {
this.formOwner.cancel();
}
}
package es.uvigo.esei.xcs.jsf.pages;
import static org.jboss.arquillian.graphene.Graphene.guardHttp;
import java.util.Collection;
import java.util.List;
import org.jboss.arquillian.graphene.findby.FindByJQuery;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import es.uvigo.esei.xcs.domain.entities.Owner;
import es.uvigo.esei.xcs.domain.entities.Pet;
public class OwnersTable {
@FindByJQuery("tbody tr")
private List<OwnerRow> trOwner;
public boolean hasOwner(Owner owner) {
for (OwnerRow row : trOwner) {
if (row.hasOwner(owner))
return true;
}
return false;
}
public OwnerRow getOwnerRow(Owner owner) {
for (OwnerRow row : trOwner) {
if (row.hasOwner(owner))
return row;
}
throw new IllegalArgumentException("No row for owner: " + owner.getLogin());
}
public void remove(Owner owner) {
guardHttp(this.getOwnerRow(owner).getButtonRemove()).click();
}
public void edit(Owner owner) {
guardHttp(this.getOwnerRow(owner).getButtonEdit()).click();
}
public static class OwnerRow {
@FindBy(className = "owners-table-login")
private WebElement tdLogin;
@FindBy(className = "owners-table-password")
private WebElement tdPassword;
@FindBy(className = "owners-table-pets")
private WebElement tdPets;
@FindBy(className = "owners-table-remove")
private WebElement buttonRemove;
@FindBy(className = "owners-table-edit")
private WebElement buttonEdit;
public boolean hasOwner(Owner owner) {
return this.getLoginText().equals(owner.getLogin())
&& this.getPasswordText().equals(owner.getPassword())
&& arePetNamesInTest(owner.getPets(), this.getPetsText());
}
private String getLoginText() {
return this.tdLogin.getText().trim();
}
private String getPasswordText() {
return this.tdPassword.getText().trim();
}
private String getPetsText() {
return this.tdPets.getText().trim();
}
public WebElement getButtonRemove() {
return this.buttonRemove;
}
public WebElement getButtonEdit() {
return this.buttonEdit;
}
private static boolean arePetNamesInTest(Collection<Pet> pets, String text) {
return pets.stream()
.map(Pet::getName)
.allMatch(text::contains);
}
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
bean-discovery-mode="all">
<alternatives>
<class>es.uvigo.esei.xcs.service.util.security.TestPrincipal</class>
</alternatives>
</beans>
ALTER TABLE Pet ALTER COLUMN id RESTART WITH 1;
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<jboss-web>
<security-domain>xcs-sample-security-domain</security-domain>
</jboss-web>
\ No newline at end of file
This diff is collapsed.
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"
version="2.1">
<persistence-unit name="test">
<jta-data-source>java:jboss/datasources/ExampleDS</jta-data-source>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
<property name="hibernate.hbm2ddl.auto" value="create-drop"/>
<property name="hibernate.show_sql" value="true"/>
</properties>
</persistence-unit>
</persistence>
\ No newline at end of file
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<display-name>Pet Store JSF</display-name>
<welcome-file-list>
<welcome-file>/faces/index.xhtml</welcome-file>
</welcome-file-list>
<!--Defining security constraint for type of roles available -->
<security-constraint>
<web-resource-collection>
<web-resource-name>admin</web-resource-name>
<url-pattern>/api/owner/*</url-pattern>
<http-method-omission>OPTIONS</http-method-omission>
</web-resource-collection>
<auth-constraint>
<role-name>ADMIN</role-name>
</auth-constraint>
</security-constraint>
<security-constraint>
<web-resource-collection>
<web-resource-name>owner</web-resource-name>
<url-pattern>/api/pet/*</url-pattern>
<http-method-omission>OPTIONS</http-method-omission>
</web-resource-collection>
<auth-constraint>
<role-name>OWNER</role-name>
</auth-constraint>
</security-constraint>
<!--Defining security constraint for type of roles available -->
<!--Denining security role -->
<security-role>
<role-name>ADMIN</role-name>
</security-role>
<security-role>
<role-name>OWNER</role-name>
</security-role>
<!--Denining security role -->
</web-app>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
bean-discovery-mode="all">
<alternatives>
<class>es.uvigo.esei.xcs.service.util.security.TestPrincipal</class>
</alternatives>
</beans>
ALTER TABLE Pet AUTO_INCREMENT = 1;
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<jboss-web>
<security-domain>xcs-sample-security-domain</security-domain>
</jboss-web>
\ No newline at end of file
<datasources xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.ironjacamar.org/doc/schema"
xsi:schemaLocation="http://www.ironjacamar.org/doc/schema http://www.ironjacamar.org/doc/schema/datasources_1_1.xsd">
<datasource jndi-name="java:jboss/datasources/xcs" pool-name="MySQLPool">
<connection-url>jdbc:mysql://localhost:3306/xcs</connection-url>
<driver>mysql-connector-java-${mysql.version}.jar</driver>
<pool>
<max-pool-size>30</max-pool-size>
</pool>
<security>
<user-name>xcs</user-name>
<password>xcs</password>
</security>
</datasource>
</datasources>
\ No newline at end of file
This diff is collapsed.
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"
version="2.1">
<persistence-unit name="test">
<jta-data-source>java:jboss/datasources/xcs</jta-data-source>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
<property name="hibernate.hbm2ddl.auto" value="create-drop"/>
<property name="hibernate.show_sql" value="true"/>
</properties>
</persistence-unit>
</persistence>
\ No newline at end of file
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<display-name>Pet Store JSF</display-name>
<welcome-file-list>
<welcome-file>/faces/index.xhtml</welcome-file>
</welcome-file-list>
<!--Defining security constraint for type of roles available -->
<security-constraint>
<web-resource-collection>
<web-resource-name>admin</web-resource-name>
<url-pattern>/api/owner/*</url-pattern>
<http-method-omission>OPTIONS</http-method-omission>
</web-resource-collection>
<auth-constraint>
<role-name>ADMIN</role-name>
</auth-constraint>
</security-constraint>
<security-constraint>
<web-resource-collection>
<web-resource-name>owner</web-resource-name>
<url-pattern>/api/pet/*</url-pattern>
<http-method-omission>OPTIONS</http-method-omission>
</web-resource-collection>
<auth-constraint>
<role-name>OWNER</role-name>
</auth-constraint>
</security-constraint>
<!--Defining security constraint for type of roles available -->
<!--Denining security role -->
<security-role>
<role-name>ADMIN</role-name>
</security-role>
<security-role>
<role-name>OWNER</role-name>
</security-role>
<!--Denining security role -->
</web-app>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<arquillian xmlns="http://jboss.org/schema/arquillian"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://jboss.org/schema/arquillian
http://jboss.org/schema/arquillian/arquillian_1_0.xsd">
<extension qualifier="persistence">
<property name="defaultDataSeedStrategy">CLEAN_INSERT</property>
</extension>
<container qualifier="wildfly-embedded-h2" default="true">
<configuration>
<property name="jbossHome">target/wildfly-${wildfly.version}</property>
<property name="modulePath">target/wildfly-${wildfly.version}/modules</property>
</configuration>
</container>
<container qualifier="wildfly-embedded-mysql">
<configuration>
<property name="jbossHome">target/wildfly-${wildfly.version}</property>
<property name="modulePath">target/wildfly-${wildfly.version}/modules</property>
</configuration>
</container>
</arquillian>
\ No newline at end of file
......@@ -13,6 +13,8 @@
<module>tests</module>
<module>service</module>
<module>rest</module>
<module>jsf</module>
<module>ear</module>
</modules>
<properties>
......@@ -22,17 +24,17 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<failOnMissingWebXml>false</failOnMissingWebXml>
<!-- BOM versions -->
<javaee.api.version>7.0</javaee.api.version>
<arquillian.version>1.1.9.Final</arquillian.version>
<arquillian.rest.version>1.0.0.Alpha3</arquillian.rest.version>
<arquillian.selenium.version>2.47.1</arquillian.selenium.version>
<arquillian.selenium.version>2.48.2</arquillian.selenium.version>
<!-- Dependencies versions -->
<wildfly.version>8.2.1.Final</wildfly.version>
<commons.lang3.version>3.4</commons.lang3.version>
<!-- Testing dependecies versions -->
<junit.version>4.12</junit.version>
<hamcrest.version>2.0.0.0</hamcrest.version>
......@@ -41,13 +43,14 @@
<slf4j.version>1.5.10</slf4j.version>
<easymock.version>3.4</easymock.version>
<resteasy.version>3.0.13.Final</resteasy.version>
<graphene.webdrive.version>2.1.0.Alpha2</graphene.webdrive.version>
<graphene.webdrive.version>2.1.0.Alpha3</graphene.webdrive.version>
<!-- Plugins versions -->
<wildfly.maven.plugin.version>1.1.0.Alpha1</wildfly.maven.plugin.version>
<wildfly.maven.plugin.version>1.1.0.Alpha4</wildfly.maven.plugin.version>
<maven.dependency.plugin.version>2.10</maven.dependency.plugin.version>
<maven.surefire.plugin.version>2.18.1</maven.surefire.plugin.version>
<maven.resources.plugin.version>2.7</maven.resources.plugin.version>
<maven.ear.plugin>2.10.1</maven.ear.plugin>
</properties>
<dependencyManagement>
......@@ -72,7 +75,7 @@
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- Modules -->
<dependency>
<groupId>${project.groupId}</groupId>
......@@ -89,20 +92,25 @@
<artifactId>rest</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>jsf</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>tests</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<!-- General -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>${commons.lang3.version}</version>
</dependency>
<!-- Testing -->
<dependency>
<groupId>junit</groupId>
......@@ -197,7 +205,13 @@
<artifactId>wildfly-maven-plugin</artifactId>
<version>${wildfly.maven.plugin.version}</version>
</plugin>
<!--This plugin's configuration is used to store Eclipse m2e settings only. It has no influence on the Maven build itself.-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-ear-plugin</artifactId>
<version>${maven.ear.plugin}</version>
</plugin>
<!--This plugin's configuration is used to store Eclipse m2e settings
only. It has no influence on the Maven build itself. -->
<plugin>
<groupId>org.eclipse.m2e</groupId>
<artifactId>lifecycle-mapping</artifactId>
......@@ -335,7 +349,7 @@
</plugins>
</build>
</profile>
<profile>
<id>wildfly-embedded-mysql</id>
<dependencies>
......
......@@ -22,6 +22,7 @@
<dependency>
<groupId>es.uvigo.esei.xcs</groupId>
<artifactId>service</artifactId>
<scope>provided</scope>
</dependency>
<!-- Testing -->
......
package es.uvigo.esei.xcs.domain.entities;
import static java.util.Arrays.asList;
import static java.util.Arrays.stream;
import static java.util.stream.Collectors.toSet;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
......@@ -47,6 +49,33 @@ public class OwnersDataset {
};
}
public static Owner[] ownersAnd(Owner ... additionalOwners) {
final Owner[] owners = owners();
final Owner[] ownersWithNewOwner = new Owner[owners.length + additionalOwners.length];
System.arraycopy(owners, 0, ownersWithNewOwner, 0, owners.length);
System.arraycopy(additionalOwners, 0, ownersWithNewOwner, owners.length, additionalOwners.length);
return ownersWithNewOwner;
}
public static Owner[] ownersWithout(Owner ... removeOwners) {
final List<Owner> owners = new ArrayList<>(asList(owners()));
for (Owner owner : removeOwners) {
final Iterator<Owner> itOwner = owners.iterator();
while (itOwner.hasNext()) {
if (itOwner.next().getLogin().equals(owner.getLogin())) {
itOwner.remove();
break;
}
}
}
return owners.toArray(new Owner[owners.size()]);
}
public static String petNameWithMultipleOwners() {
return "Max";
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment