From 4193ad9e7ad887464bc7649a4393fcd9b7898706 Mon Sep 17 00:00:00 2001 From: Pete Muir Date: Thu, 19 Sep 2013 15:03:03 +0100 Subject: [PATCH] Add angularjs-tasks example Thanks to @wesbos for help with the UI --- tasks-angularjs/README.md | 237 ++++++++++++++++ tasks-angularjs/pom.xml | 259 ++++++++++++++++++ .../quickstarts/tasksrs/model/Resources.java | 48 ++++ .../as/quickstarts/tasksrs/model/Task.java | 92 +++++++ .../as/quickstarts/tasksrs/model/TaskDao.java | 75 +++++ .../as/quickstarts/tasksrs/model/User.java | 97 +++++++ .../as/quickstarts/tasksrs/model/UserDao.java | 51 ++++ .../tasksrs/service/JaxRsActivator.java | 33 +++ .../tasksrs/service/TaskRESTService.java | 150 ++++++++++ .../main/resources/META-INF/persistence.xml | 31 +++ .../src/main/webapp/WEB-INF/beans.xml | 17 ++ .../src/main/webapp/WEB-INF/tasks-rs-ds.xml | 33 +++ tasks-angularjs/src/main/webapp/css/todo.css | 167 +++++++++++ .../src/main/webapp/img/notepad-main.jpg | Bin 0 -> 6014 bytes .../src/main/webapp/img/notepad-margin.jpg | Bin 0 -> 2180 bytes tasks-angularjs/src/main/webapp/index.html | 80 ++++++ tasks-angularjs/src/main/webapp/js/app.js | 31 +++ .../src/main/webapp/js/controllers.js | 138 ++++++++++ .../src/main/webapp/js/services.js | 21 ++ .../src/main/webapp/partials/home.html | 76 +++++ .../tasksrs/DefaultDeployment.java | 55 ++++ .../as/quickstarts/tasksrs/TaskDaoTest.java | 128 +++++++++ .../as/quickstarts/tasksrs/UserDaoTest.java | 92 +++++++ .../resources/META-INF/test-persistence.xml | 36 +++ .../src/test/resources/arquillian.xml | 39 +++ tasks-angularjs/src/test/resources/import.sql | 26 ++ .../src/test/resources/test-ds.xml | 36 +++ 27 files changed, 2048 insertions(+) create mode 100644 tasks-angularjs/README.md create mode 100644 tasks-angularjs/pom.xml create mode 100644 tasks-angularjs/src/main/java/org/jboss/as/quickstarts/tasksrs/model/Resources.java create mode 100644 tasks-angularjs/src/main/java/org/jboss/as/quickstarts/tasksrs/model/Task.java create mode 100644 tasks-angularjs/src/main/java/org/jboss/as/quickstarts/tasksrs/model/TaskDao.java create mode 100644 tasks-angularjs/src/main/java/org/jboss/as/quickstarts/tasksrs/model/User.java create mode 100644 tasks-angularjs/src/main/java/org/jboss/as/quickstarts/tasksrs/model/UserDao.java create mode 100644 tasks-angularjs/src/main/java/org/jboss/as/quickstarts/tasksrs/service/JaxRsActivator.java create mode 100644 tasks-angularjs/src/main/java/org/jboss/as/quickstarts/tasksrs/service/TaskRESTService.java create mode 100644 tasks-angularjs/src/main/resources/META-INF/persistence.xml create mode 100644 tasks-angularjs/src/main/webapp/WEB-INF/beans.xml create mode 100644 tasks-angularjs/src/main/webapp/WEB-INF/tasks-rs-ds.xml create mode 100644 tasks-angularjs/src/main/webapp/css/todo.css create mode 100644 tasks-angularjs/src/main/webapp/img/notepad-main.jpg create mode 100644 tasks-angularjs/src/main/webapp/img/notepad-margin.jpg create mode 100644 tasks-angularjs/src/main/webapp/index.html create mode 100644 tasks-angularjs/src/main/webapp/js/app.js create mode 100644 tasks-angularjs/src/main/webapp/js/controllers.js create mode 100644 tasks-angularjs/src/main/webapp/js/services.js create mode 100644 tasks-angularjs/src/main/webapp/partials/home.html create mode 100644 tasks-angularjs/src/test/java/org/jboss/as/quickstarts/tasksrs/DefaultDeployment.java create mode 100644 tasks-angularjs/src/test/java/org/jboss/as/quickstarts/tasksrs/TaskDaoTest.java create mode 100644 tasks-angularjs/src/test/java/org/jboss/as/quickstarts/tasksrs/UserDaoTest.java create mode 100644 tasks-angularjs/src/test/resources/META-INF/test-persistence.xml create mode 100644 tasks-angularjs/src/test/resources/arquillian.xml create mode 100644 tasks-angularjs/src/test/resources/import.sql create mode 100644 tasks-angularjs/src/test/resources/test-ds.xml diff --git a/tasks-angularjs/README.md b/tasks-angularjs/README.md new file mode 100644 index 00000000..64937672 --- /dev/null +++ b/tasks-angularjs/README.md @@ -0,0 +1,237 @@ +tasks-rs: JAX-RS, JPA quickstart +============================== +Author: Pete Muir, Mike Musgrove +Level: Intermediate +Technologies: JPA, JAX-RS +Summary: Demonstrates how to use JAX-RS and JPA together +Prerequisites: tasks +Target Product: EAP +Source: + +What is it? +----------- + +This project demonstrates how to implement a JAX-RS service that uses JPA 2.0 persistence. + +* The client uses HTTP to interact with the service. It builds on the *tasks* quickstarts which provide simple Task management with secure login. + +* The service interface is implemented using JAX-RS. The SecurityContext JAX-RS annotation is used to inject the security details into each REST method. + +The application manages User and Task JPA entities. A user represents an authenticated principal and is associated with zero or more Tasks. Service methods validate that there is an authenticated principal and the first time a principal is seen, a JPA User entity is created to correspond to the principal. JAX-RS annotated methods are provided for associating Tasks with this User and for listing and removing Tasks. + + +System requirements +------------------- + +All you need to build this project is Java 6.0 (Java SDK 1.6) or better, Maven 3.0 or better. + +The application this project produces is designed to be run on JBoss Enterprise Application Platform 6 or JBoss AS 7. + + +Configure Maven +------------- + +If you have not yet done so, you must [Configure Maven](../README.md#configure-maven) before testing the quickstarts. + + + +Add an Application User +--------------- + +This quickstart uses a secured management interface and requires that you create an application user to access the running application. Instructions to set up an Application user can be found here: [Add an Application User](../README.md#add-an-application-user). After following these instructions. you should have created a user called `quickstartUser` with password `quickstartPwd1!`, belonging to the `guest` role. + + +Start JBoss Enterprise Application Platform 6 or JBoss AS 7 with the Web Profile +------------------------- + +1. Open a command line and navigate to the root of the JBoss server directory. +2. The following shows the command line to start the server with the web profile: + + For Linux: JBOSS_HOME/bin/standalone.sh + For Windows: JBOSS_HOME\bin\standalone.bat + + +Build and Deploy the Quickstart +------------------------- + +_NOTE: The following build command assumes you have configured your Maven user settings. If you have not, you must include Maven setting arguments on the command line. See [Build and Deploy the Quickstarts](../README.md#build-and-deploy-the-quickstarts) for complete instructions and additional options._ + +1. Make sure you have started the JBoss Server as described above. +2. Open a command line and navigate to the root directory of this quickstart. +3. Type this command to build and deploy the archive: + + mvn clean package jboss-as:deploy + +4. This will deploy `target/jboss-as-tasks-angluarjs.war` to the running instance of the server. + + +Access the Application Resources +--------------------- + +Application resources for this quickstart are prefixed with the URL http://localhost:8080/jboss-as-tasks-angluarjs/ and can be accessed by an HTTP client. + +* For methods that accept *GET*, a web browser can be used. +* Otherwise, you must use cURL or some other command line tool that supports HTTP *POST* and *DELETE* methods. + +Below you will find instructions to create, display, and delete tasks. + +### Create a Task + +To associate a task called `task1` with the user `quickstartUser`, you must authenticate as user `quickstartUser` and send an HTTP *POST* request to the url 'http://localhost:8080/jboss-as-tasks-angluarjs/tasks/task1'. + +To issue the *POST* command using cURL, type the following command: + + curl -i -u 'quickstartUser:quickstartPwd1!' -H "Content-Length: 0" -X POST http://localhost:8080/jboss-as-tasks-angluarjs/tasks/task1 + +You will see the following response: + + HTTP/1.1 201 Created + Server: Apache-Coyote/1.1 + Location: http://localhost:8080/jboss-as-tasks-angluarjs/tasks/1 + Content-Length: 0 + Date: Sun, 15 Apr 2012 22:46:26 GMT + +This is what happens when the command is issued: + +* The `-i` flag tells cURL to print the returned headers. Notice that the `Location` header contains the URI of the resource corresponding to the new task you have just created. +* The `-u` flag provides the authentication information for the request. +* The `-H` flag adds a header to the outgoing request. +* The `-X` flag tells cURL which HTTP method to use. The HTTP *POST* is used to create resources. +* The `Location` header of the response contains the URI of the resource representing the newly created task. + +The final argument to cURL determines the title of the task. Note that this approach is perhaps not very restful but it simplifies this quickstart. A better approach would be to *POST* to "http://localhost:8080/jboss-as-tasks-angluarjs/tasks" passing the task title in the body of the request. + + +### Display the XML Representation of a Task + +To display the XML representation of the newly created resource, issue a *GET* request on the task URI returned in the `Location` header during the create. + +1. To issue a *GET* using a browser, open a browser and access the URI. You will be challenged to enter valid authentication credentials. + + +2. To issue a *GET* using cURL, type the following command: + + curl -H "Accept: application/xml" -u 'quickstartUser:quickstartPwd1!' -X GET http://localhost:8080/jboss-as-tasks-angluarjs/tasks/1 + + The `-H flag tells the server that the client wishes to accept XML content. + +Using either of the above *GET* methods, you should see the following XML: + + + + task1 + + + +### Display the XML Representation of all Tasks for a User + +To obtain a list of all tasks for user `quickstartUser` in XML format, authenticate as user `quickstartUser` and send an HTTP `GET` request to the resource `tasks` URL. + +1. To issue a *GET* using a browser, open a browser and access the following URL. You will be challenged to enter valid authentication credentials. + + + +2. To list all tasks associated with the user `quickstartUser` using cURL, type: + + curl -H "Accept: application/xml" -u 'quickstartUser:quickstartPwd1!' -X GET http://localhost:8080/jboss-as-tasks-angluarjs/tasks + +Using either of the above *GET* methods, you should see the following XML: + + + + + task1 + + + +### Delete a Task + +To delete a task, again authenticate as principal `quickstartUser` and send an HTTP *DELETE* request to the URI that represents the task. + +To delete the task with id `1`: + + curl -i -u 'quickstartUser:quickstartPwd1!' -X DELETE http://localhost:8080/jboss-as-tasks-angluarjs/tasks/1 + +You will see this response: + + HTTP/1.1 204 No Content + Server: Apache-Coyote/1.1 + Pragma: No-cache + Cache-Control: no-cache + Expires: Thu, 01 Jan 1970 01:00:00 GMT + Date: Sun, 15 Apr 2012 22:51:56 GMT + +Now list all tasks associated with user `quickstartUser`: + + curl -u 'quickstartUser:quickstartPwd1!' -X GET http://localhost:8080/jboss-as-tasks-angluarjs/tasks + +You will see a response with an empty collection: + + + + + +Modify this Quickstart to Support JSON Representations of Tasks +----------------------------------------------------------------- + +JSON is not part of the JAX-RS standard but most JAX-RS implementations do support it. This quickstart can be modified to support JSON by uncommenting a few lines. Look for lines beginning with "// JSON:": + +1. Open the file src/org/jboss/as/quickstarts/tasksrs/model/Task.java and remove the comments from the following two lines. + + // import org.codehaus.jackson.annotate.JsonIgnore; + + // @JsonIgnore + +2. Open the file src/org/jboss/as/quickstarts/tasksrs/service/TaskResource.java and make sure the *GET* methods produce "application/json" as well as "application/xml". Again, look for lines beginning with "// JSON:". + * Remove comments from these lines: + + //@Produces({ "application/xml", "application/json" }) + * Add comments to these lines: + + @Produces({ "application/xml" }) +3. Open pom.xml and remove the comments from the dependency with artifactId `resteasy-jackson-provider` + + + +4. [Create a Task](#create-a-task) as you did in the for the XML version of this quickstart. +5. Rebuild and redeploy the quickstart. + + +Now you can view task resources in JSON media type by specifying the correct Accept header. For example, using the cURL tool, type the following command: + + curl -H "Accept: application/json" -u 'quickstartUser:quickstartPwd1!' -X GET http://localhost:8080/jboss-as-tasks-angluarjs/tasks/1 + +You will see the following response: + + {"id":1,"title":"task1","ownerName":"quickstartUser"} + + +Undeploy the Archive +-------------------- + +1. Make sure you have started the JBoss Server as described above. +2. Open a command line and navigate to the root directory of this quickstart. +3. When you are finished testing, type this command to undeploy the archive: + + mvn jboss-as:undeploy + + +Run the Quickstart in JBoss Developer Studio or Eclipse +------------------------------------- +You can also start the server and deploy the quickstarts from Eclipse using JBoss tools. For more information, see [Use JBoss Developer Studio or Eclipse to Run the Quickstarts](../README.md#use-jboss-developer-studio-or-eclipse-to-run-the-quickstarts) + + +Debug the Application +--------------------- + +If you want to debug the source code or look at the Javadocs of any library in the project, run either of the following commands to pull them into your local repository. The IDE should then detect them. + + mvn dependency:sources + mvn dependency:resolve -Dclassifier=javadoc diff --git a/tasks-angularjs/pom.xml b/tasks-angularjs/pom.xml new file mode 100644 index 00000000..9952a9f9 --- /dev/null +++ b/tasks-angularjs/pom.xml @@ -0,0 +1,259 @@ + + + + 4.0.0 + + org.jboss.as.quickstarts + jboss-as-tasks-angularjs + 7.1.2-SNAPSHOT + war + JBoss EAP Quickstart: tasks-rs + JBoss EAP Quickstart: Tasks JSF JAX-RS + + + + Apache License, Version 2.0 + repo + http://www.apache.org/licenses/LICENSE-2.0.html + + + + + + + UTF-8 + + + 7.3.Final + + + 1.0.7.CR8 + + + + + 2.3.1 + 2.10 + 2.1.1 + + + 1.6 + 1.6 + + + + + + + org.jboss.bom + jboss-javaee-6.0-with-tools + ${version.jboss.bom} + pom + import + + + + + + + + javax.enterprise + cdi-api + provided + + + + + org.hibernate.javax.persistence + hibernate-jpa-2.0-api + provided + + + + + org.jboss.spec.javax.ws.rs + jboss-jaxrs-api_1.1_spec + provided + + + + + + + org.jboss.spec.javax.ejb + jboss-ejb-api_3.1_spec + provided + + + + + junit + junit + test + + + + org.jboss.arquillian.junit + arquillian-junit-container + test + + + + org.jboss.arquillian.protocol + arquillian-protocol-servlet + test + + + + + + + + ${project.artifactId} + + + maven-war-plugin + ${version.war.plugin} + + + false + + + + + maven-compiler-plugin + ${version.compiler.plugin} + + ${maven.compiler.source} + ${maven.compiler.target} + + + + + maven-surefire-plugin + ${version.surefire.plugin} + + + + + org.jboss.as.plugins + jboss-as-maven-plugin + ${version.jboss.maven.plugin} + + + + + + + + + default + + true + + + + + maven-surefire-plugin + + true + + + + + + + + + + + arq-jbossas-managed + + + org.jboss.as + jboss-as-arquillian-container-managed + test + + + + + + + + arq-jbossas-remote + + + org.jboss.as + jboss-as-arquillian-container-remote + test + + + + + + + + + + openshift + + + + maven-war-plugin + ${version.war.plugin} + + deployments + ROOT + + + + + + + + + diff --git a/tasks-angularjs/src/main/java/org/jboss/as/quickstarts/tasksrs/model/Resources.java b/tasks-angularjs/src/main/java/org/jboss/as/quickstarts/tasksrs/model/Resources.java new file mode 100644 index 00000000..cbf3924e --- /dev/null +++ b/tasks-angularjs/src/main/java/org/jboss/as/quickstarts/tasksrs/model/Resources.java @@ -0,0 +1,48 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2013, Red Hat, Inc. and/or its affiliates, and individual + * contributors by the @authors tag. See the copyright.txt in the + * distribution for a full listing of individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jboss.as.quickstarts.tasksrs.model; + +import java.util.logging.Logger; + +import javax.enterprise.inject.Produces; +import javax.enterprise.inject.spi.InjectionPoint; +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; + +/** + * This class uses CDI to alias Java EE resources, such as the persistence context, to CDI beans. As it is a stateful bean, it + * can produce extended persistence contexts. + * + * Example injection on a managed bean field: + * + * @Inject private EntityManager em; + * + * @author Pete Muir + * @author Lukas Fryc + * + */ +public class Resources { + + @Produces @PersistenceContext + private EntityManager em; + + @Produces + public Logger getLogger(InjectionPoint ip) { + String category = ip.getMember().getDeclaringClass().getName(); + return Logger.getLogger(category); + } +} diff --git a/tasks-angularjs/src/main/java/org/jboss/as/quickstarts/tasksrs/model/Task.java b/tasks-angularjs/src/main/java/org/jboss/as/quickstarts/tasksrs/model/Task.java new file mode 100644 index 00000000..9642bbfc --- /dev/null +++ b/tasks-angularjs/src/main/java/org/jboss/as/quickstarts/tasksrs/model/Task.java @@ -0,0 +1,92 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2013, Red Hat, Inc. and/or its affiliates, and individual + * contributors by the @authors tag. See the copyright.txt in the + * distribution for a full listing of individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jboss.as.quickstarts.tasksrs.model; + +// JSON: uncomment to include json support (note json is not part of the JAX-RS standard) +//import org.codehaus.jackson.annotate.JsonIgnore; + +import static javax.persistence.GenerationType.IDENTITY; + +import java.io.Serializable; +import java.io.StringReader; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.xml.bind.JAXB; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlTransient; + +/** + * User's task entity which is marked up with JPA annotations and JAXB for serializing XML + * (and JSON if required) + * + * @author Oliver Kiss and others + */ +@SuppressWarnings("serial") +@Entity +@XmlRootElement(name = "task") +public class Task implements Serializable { + + @Id + @GeneratedValue(strategy = IDENTITY) + private Long id; + + //@ManyToOne + //@XmlTransient + //private User owner; + + private String title; + + private boolean complete; + + public Task() { + } + + public Task(String title) { + super(); + this.title = title; + } + + @XmlAttribute + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + @XmlElement + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public boolean isComplete() { + return complete; + } + + public void setComplete(boolean complete) { + this.complete = complete; + } +} diff --git a/tasks-angularjs/src/main/java/org/jboss/as/quickstarts/tasksrs/model/TaskDao.java b/tasks-angularjs/src/main/java/org/jboss/as/quickstarts/tasksrs/model/TaskDao.java new file mode 100644 index 00000000..5811c250 --- /dev/null +++ b/tasks-angularjs/src/main/java/org/jboss/as/quickstarts/tasksrs/model/TaskDao.java @@ -0,0 +1,75 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2013, Red Hat, Inc. and/or its affiliates, and individual + * contributors by the @authors tag. See the copyright.txt in the + * distribution for a full listing of individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jboss.as.quickstarts.tasksrs.model; + +import java.util.List; + +import javax.ejb.Stateful; +import javax.inject.Inject; +import javax.persistence.EntityManager; +import javax.persistence.TypedQuery; + +/** + * Provides functionality for manipulation with tasks using the persistence context from {@link Resources}. + * + * @author Lukas Fryc + * @author Oliver Kiss + * + */ +@Stateful +public class TaskDao { + + @Inject + private EntityManager em; + + public void createTask(User user, Task task) { + if (task.getId() != null) { + em.merge(task); + } else { + em.persist(task); + } + } + + public List getAll(User user) { + TypedQuery query = querySelectAllTasksFromUser(user); + return query.getResultList(); + } + + public List getRange(User user, int offset, int count) { + TypedQuery query = querySelectAllTasksFromUser(user); + query.setMaxResults(count); + query.setFirstResult(offset); + return query.getResultList(); + } + + public List getForTitle(User user, String title) { + String lowerCaseTitle = "%" + title.toLowerCase() + "%"; + return em.createQuery("SELECT t FROM Task t WHERE LOWER(t.title) LIKE ?", Task.class) + .setParameter(2, lowerCaseTitle).getResultList(); + } + + public void deleteTask(Task task) { + if (!em.contains(task)) { + task = em.merge(task); + } + em.remove(task); + } + + private TypedQuery querySelectAllTasksFromUser(User user) { + return em.createQuery("SELECT t FROM Task t", Task.class); + } +} \ No newline at end of file diff --git a/tasks-angularjs/src/main/java/org/jboss/as/quickstarts/tasksrs/model/User.java b/tasks-angularjs/src/main/java/org/jboss/as/quickstarts/tasksrs/model/User.java new file mode 100644 index 00000000..75421af0 --- /dev/null +++ b/tasks-angularjs/src/main/java/org/jboss/as/quickstarts/tasksrs/model/User.java @@ -0,0 +1,97 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2013, Red Hat, Inc. and/or its affiliates, and individual + * contributors by the @authors tag. See the copyright.txt in the + * distribution for a full listing of individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jboss.as.quickstarts.tasksrs.model; + +import static javax.persistence.CascadeType.ALL; +import static javax.persistence.GenerationType.IDENTITY; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.OneToMany; +import javax.xml.bind.annotation.XmlTransient; + +/** + * User entity + * + * @author Oliver Kiss + */ +@SuppressWarnings("serial") +@Entity +public class User implements Serializable { + + @Id + @GeneratedValue(strategy = IDENTITY) + private Long id; + + @Column(unique = true) + private String username; + + public User() { + } + + public User(String username) { + this.username = username; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((username == null) ? 0 : username.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + User other = (User) obj; + if (username == null) { + if (other.username != null) + return false; + } else if (!username.equals(other.username)) + return false; + return true; + } +} diff --git a/tasks-angularjs/src/main/java/org/jboss/as/quickstarts/tasksrs/model/UserDao.java b/tasks-angularjs/src/main/java/org/jboss/as/quickstarts/tasksrs/model/UserDao.java new file mode 100644 index 00000000..ff81be12 --- /dev/null +++ b/tasks-angularjs/src/main/java/org/jboss/as/quickstarts/tasksrs/model/UserDao.java @@ -0,0 +1,51 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2013, Red Hat, Inc. and/or its affiliates, and individual + * contributors by the @authors tag. See the copyright.txt in the + * distribution for a full listing of individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jboss.as.quickstarts.tasksrs.model; + +import java.util.List; + +import javax.ejb.Stateful; +import javax.inject.Inject; +import javax.persistence.EntityManager; + +/** + * Provides functionality for manipulation with users using persistence context from {@link Resources}. + * + * @author Lukas Fryc + * @author Oliver Kiss + * + */ +@Stateful +public class UserDao { + + @Inject + private EntityManager em; + + public User getForUsername(String username) { + List result = em.createQuery("select u from User u where u.username = ?", User.class).setParameter(1, username) + .getResultList(); + + if (result.isEmpty()) { + return null; + } + return result.get(0); + } + + public void createUser(User user) { + em.persist(user); + } +} \ No newline at end of file diff --git a/tasks-angularjs/src/main/java/org/jboss/as/quickstarts/tasksrs/service/JaxRsActivator.java b/tasks-angularjs/src/main/java/org/jboss/as/quickstarts/tasksrs/service/JaxRsActivator.java new file mode 100644 index 00000000..587f93a7 --- /dev/null +++ b/tasks-angularjs/src/main/java/org/jboss/as/quickstarts/tasksrs/service/JaxRsActivator.java @@ -0,0 +1,33 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2013, Red Hat, Inc. and/or its affiliates, and individual + * contributors by the @authors tag. See the copyright.txt in the + * distribution for a full listing of individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jboss.as.quickstarts.tasksrs.service; + +import javax.ws.rs.ApplicationPath; +import javax.ws.rs.core.Application; + +/** + * A class extending {@link Application} and annotated with @ApplicationPath is the Java EE 6 "no XML" approach to activating + * JAX-RS. + * + *

+ * Resources are served relative to the servlet path specified in the {@link ApplicationPath} annotation. + *

+ */ +@ApplicationPath("/rest") +public class JaxRsActivator extends Application { + /* class body intentionally left blank */ +} diff --git a/tasks-angularjs/src/main/java/org/jboss/as/quickstarts/tasksrs/service/TaskRESTService.java b/tasks-angularjs/src/main/java/org/jboss/as/quickstarts/tasksrs/service/TaskRESTService.java new file mode 100644 index 00000000..8681cc45 --- /dev/null +++ b/tasks-angularjs/src/main/java/org/jboss/as/quickstarts/tasksrs/service/TaskRESTService.java @@ -0,0 +1,150 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2013, Red Hat, Inc. and/or its affiliates, and individual + * contributors by the @authors tag. See the copyright.txt in the + * distribution for a full listing of individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jboss.as.quickstarts.tasksrs.service; + +import java.net.URI; +import java.security.Principal; +import java.util.List; + +import javax.inject.Inject; +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.SecurityContext; +import javax.ws.rs.core.UriBuilder; +import javax.ws.rs.core.UriInfo; + +import org.jboss.as.quickstarts.tasksrs.model.Task; +import org.jboss.as.quickstarts.tasksrs.model.TaskDao; +import org.jboss.as.quickstarts.tasksrs.model.User; +import org.jboss.as.quickstarts.tasksrs.model.UserDao; + +/** + * A JAX-RS resource for exposing REST endpoints for Task manipulation + */ +@Path("/task") +public class TaskRESTService { + + @Inject + private UserDao userDao; + + @Inject + private TaskDao taskDao; + + @POST + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Response createTask(Task task, @Context UriInfo info, @Context SecurityContext context) { + + User user = getUser(context); + + taskDao.createTask(user, task); + + // Construct the URI for the newly created resource and put in into the Location header of the response + // (assumes that there is only one occurrence of the task title in the request) + String rawPath = info.getAbsolutePath().getRawPath().replace(task.getTitle(), task.getId().toString()); + UriBuilder uriBuilder = info.getAbsolutePathBuilder().replacePath(rawPath); + URI uri = uriBuilder.build(); + + return Response.created(uri).build(); + } + + @DELETE + @Path("{id}") + public void deleteTaskById(@Context SecurityContext context, @PathParam("id") Long id) { + Task task = getTaskById(context, id); + + taskDao.deleteTask(task); + } + + @GET + @Path("{id}") + @Produces(MediaType.APPLICATION_JSON) + public Task getTaskById(@Context SecurityContext context, @PathParam("id") Long id) { + User user = getUser(context); + return getTask(user, id); + } + + @GET + @Path("{title}") + @Produces(MediaType.APPLICATION_JSON) + public List getTasksByTitle(@Context SecurityContext context, @PathParam("title") String title) { + return getTasks(getUser(context), title); + } + + @GET + @Produces(MediaType.APPLICATION_JSON) + public List getTasks(@Context SecurityContext context) { + return getTasks(getUser(context)); + } + + + // Utility Methods + + private List getTasks(User user, String title) { + return taskDao.getForTitle(user, title); + } + + private List getTasks(User user) { + return taskDao.getAll(user); + } + + private Task getTask(User user, Long id) { + for (Task task : taskDao.getAll(user)) + if (task.getId().equals(id)) + return task; + + throw new WebApplicationException(Response.Status.NOT_FOUND); + } + + private User getUser(SecurityContext context) { + Principal principal = null; + + if (context != null) + principal = context.getUserPrincipal(); + +// if (principal == null) +// throw new WebApplicationException(Response.Status.UNAUTHORIZED); + + return getUser("guest"); + } + + private User getUser(String username) { + + try { + User user = userDao.getForUsername(username); + + if (user == null) { + user = new User(username); + + userDao.createUser(user); + } + + return user; + } catch (Exception e) { + throw new WebApplicationException(e); + } + } +} diff --git a/tasks-angularjs/src/main/resources/META-INF/persistence.xml b/tasks-angularjs/src/main/resources/META-INF/persistence.xml new file mode 100644 index 00000000..c972b6aa --- /dev/null +++ b/tasks-angularjs/src/main/resources/META-INF/persistence.xml @@ -0,0 +1,31 @@ + + + + + java:jboss/datasources/TasksRsQuickstartDS + + + + + + + diff --git a/tasks-angularjs/src/main/webapp/WEB-INF/beans.xml b/tasks-angularjs/src/main/webapp/WEB-INF/beans.xml new file mode 100644 index 00000000..b62eb2cb --- /dev/null +++ b/tasks-angularjs/src/main/webapp/WEB-INF/beans.xml @@ -0,0 +1,17 @@ + + \ No newline at end of file diff --git a/tasks-angularjs/src/main/webapp/WEB-INF/tasks-rs-ds.xml b/tasks-angularjs/src/main/webapp/WEB-INF/tasks-rs-ds.xml new file mode 100644 index 00000000..2955518d --- /dev/null +++ b/tasks-angularjs/src/main/webapp/WEB-INF/tasks-rs-ds.xml @@ -0,0 +1,33 @@ + + + + + + jdbc:h2:mem:tasks-rs-xml-quickstart;DB_CLOSE_ON_EXIT=FALSE;DB_CLOSE_DELAY=-1 + h2 + + sa + sa + + + diff --git a/tasks-angularjs/src/main/webapp/css/todo.css b/tasks-angularjs/src/main/webapp/css/todo.css new file mode 100644 index 00000000..dabc65d7 --- /dev/null +++ b/tasks-angularjs/src/main/webapp/css/todo.css @@ -0,0 +1,167 @@ +body { + background: #2D3640; +} + +h1 { + color:#fff; +} + +#content { + max-width:800px; + margin:0 auto; +} + +.completed { + color: #33aa66; +} + +/* + Hide radio button (the round disc) + we will use just the label to create pushbutton effect +*/ +.display-controls input[type=radio] { + display:none; + margin:10px; +} + +.display-controls label{ + padding-left: 7px; + color:#232930; +} + .display-controls span.number-left { + background: #2D3640; + color:#fff; + padding: 3px 7px; + border-radius: 5px; + margin-right: 3px; + } + +/* + Change the font weight for the checked element +*/ + +.display-controls input[type=radio]:checked + label{ + font-weight: bold; +} + +.help { + font-size: x-small; + color: grey; + text-align:center; +} + +.notepad { + font-size: large;` + width:100%; + border: 20px solid #232930; + width: 100%; + float: left; + border-radius: 10px; + padding: 20px; + background: #f6f9fa; + border-radius: 10px; +} + +.notepad ul { + list-style:none; + margin: 0; +} + + +.notepad ul li { + background:#fff; + margin: 10px 0 0 0; + clear:both; + float:left; + width:100%; + min-height:20px; + border-radius:5px; + padding:10px; + box-shadow: 0 2px 1px rgba(204, 204, 204, 0.47); + border: 1px solid rgba(204, 204, 204, 0.31); +} + .notepad ul li.completed { + background: #F3F3F3; + opacity: 5.5; + box-shadow: none; + } + + .notepad ul li.completed span { + text-decoration: line-through; + } + +.notepad-margin { + width:5%; + float:left; +} + .notepad-margin i { + cursor:pointer; + } + +.notepad-main { + width:95%; + float:left; +} +.new-task form { + margin-bottom: 0px; + margin-top:10px; +} + +.edit-task form { + margin-bottom: 0px; + margin-top: 0px; +} + +.items-remaining, .items-filter { + padding:0; + font-size:12px; +} + +.notepad td { + padding-left: 10px; + background-position: left bottom; + nackground-repeat: no-repeat; + padding-bottom:8px; +} + +.notepad input { + min-width: 300px; + border: 0px; + box-shadow: 0px 0px 0px 0px; + outline: none; + vertical-align: bottom; + font-size: large; +} + +.new-task input { + font-size: x-large; + min-height: 30px; +} + +.show-task { + padding-top:1px; +} + +.edit-task input { + margin-bottom: 0px; + padding: 0px; +} + +input:focus:invalid:focus, input[type="text"]:focus { + border: 0px; + box-shadow: 0px 0px 0px 0px; + outline: 0px; +} + + +/* Media Queries for responsive version */ + +@media (max-width: 800px) { + body { + margin:0; + padding:0; + } + .row { + margin:0; + } +} diff --git a/tasks-angularjs/src/main/webapp/img/notepad-main.jpg b/tasks-angularjs/src/main/webapp/img/notepad-main.jpg new file mode 100644 index 0000000000000000000000000000000000000000..859888953297ba6942abde27f24abe17b2907b08 GIT binary patch literal 6014 zcmeHJeNa?Y6hH61-F^FounI^v!^Q$a(l{#gp*1`amjxYiR#S|zA+-eZFVI4om^WYu z;Y=G^mP`}4TR@sMBm`!)f)>~~LkJ=eGf09M*}yJeyUXr7-L=5jf3p7Vop;a7op;}T z_xC&Jch9}pgEt{yQ&LJ2P!t8pR^O5(y(^Wh~3eWHMH+Qm}HRTqaZaDU>ReTCHXk zevACni%3`H{fT!jb8oIxC6~!n|Jv{(Xyh!bD2=dMW>96wOGa z1QEeOK4=Ia@EL|CV5Jg5oGKvWAkjz{hpkSKEivw9bvc1+3d>K)!#C752W{;bkBHrq zTcl71FAaHUS>*Dl=toz?J^sX#Ppw^-xKW>ENKV;O5Z9wcKqGww<+=KXuNs@qf8BEF^7lWq zwq5!0T4&ew?i)S5eS^Q;8XCSma_84kn|)$(YI?@uba{DE!2C&To|z9X4dF$T97tF% zFN)41&S)gku+_4~2}X8z&Jx|4LV4hZ@>6xqityO2<3W3JJCwl@af6XIFSUEj9*kJg ze_}RI>^`qPP%{)s9-{#cJZ^JYG>9(7K-7S!0Z{{@21E^r8W1(`ztsS9(K=XU9j$+( z0HNgqLVX8yV2vgN-Joln5bWnA}%?E=pa z)e(G&Vp8W6FD6yosq=+I+^P2~zgT`N#PTbiseeE5#WVH6E=u1%eY3HJb8HI@Zn{P; zicvQHXne=P8yWj;p_b{{T6^ht=_w64A-zp2*PRQUH16v8Y~o>4&D}Fy-xTPq5pUnU ZP;9?i-PpaVK0kARM#UC>c^`+pe*i#SK$idj literal 0 HcmV?d00001 diff --git a/tasks-angularjs/src/main/webapp/img/notepad-margin.jpg b/tasks-angularjs/src/main/webapp/img/notepad-margin.jpg new file mode 100644 index 0000000000000000000000000000000000000000..4907e007e5eb254bd50f651d006f2461adfe7318 GIT binary patch literal 2180 zcmeH{dr(wW9LIlm@9y4xfUvAeIW;>xj7^*gUFf-S(*+U+WmZkpsXW>mKjIbN1 zp*uAUprwo>aLX(k*+?h}1z{<%tUH8?P(IdO;$^TrcG(AePiHOYAu~Px&EGxWxxe|I zd(QcN&bf2Y6?6jvlM)gWfFKB1h95v?cq)EJRwlsm<*)z%BtR5pfe>c|);uf#L8V~Y z(N&Vud5^CX{Qx=;5QMJ@aKk~0NMDGBLQ+JDDT)${#gs%Yr6e+mSS}5)tP0A^#SHfE0>w zMYs<9L0up&pCkpiSdkEe6FYG~2o<8BkVQ+xO8rJEbldF31tnFIu%$K4b5^$7!ZqpH zg;Lqv;Ct?!H~)bM^@9tdV;+9w(Z?Rw#lB-u<&ptm@|3!NelBSbKiz?du;H866w9J0_eiw~vbe@>i^BvcGUCFqZ(IfspcX z5rSMSQXv$DED{GT(Ni0@DMJ?*NMu0%jSkho9B=C&~B6cGqA${ zL^cifJ6AXOkpw79P7!(u}4_Up-Bjp_P?c8qV1KyWn9(`Zl|pPjs*W(_c7Ku8TQQ6ID>h2BkykH z|ND=$J>=YAbe~YE7+W=hpQ9O*h`F@Y=|Qk37eN+ln4m8o=6Hs&)*!H^lp@e)({2jE z`Ccq)GAh-(rntDtnaViIX>(!IKyCg`1T75+YTM&ggDbWmpqob5A{Y(fSt~OhfS`;+ zP#W+z%l>gyoj1M>-(4yM5fuo+Rkr3d`}){e1m@=ubiZKXx)3-r_-hCX%bgxm(aqpi zk0!l*AAhl~GyhDIWpke1dy8Lpwc)$of|C1~t5){3*0MK8W`C)A`-|V`V}{PXMu*vH z|5LQuwBcl5M^(nc`{TU*1NBwc(n=hvKQZDfma`wzAgH+RTFAJRqntfB3_&F`d4!oP HL0!K9hNcD- literal 0 HcmV?d00001 diff --git a/tasks-angularjs/src/main/webapp/index.html b/tasks-angularjs/src/main/webapp/index.html new file mode 100644 index 00000000..bb446237 --- /dev/null +++ b/tasks-angularjs/src/main/webapp/index.html @@ -0,0 +1,80 @@ + + + + + tasks + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tasks-angularjs/src/main/webapp/js/app.js b/tasks-angularjs/src/main/webapp/js/app.js new file mode 100644 index 00000000..1aeebfeb --- /dev/null +++ b/tasks-angularjs/src/main/webapp/js/app.js @@ -0,0 +1,31 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2013, Red Hat, Inc. and/or its affiliates, and individual + * contributors by the @authors tag. See the copyright.txt in the + * distribution for a full listing of individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// Define any routes for the app +// Note that this app is a single page app, and each partial is routed to using the URL fragment. For example, to select the 'home' route, the URL is http://localhost:8080/jboss-as-kitchensink-angularjs/#/home +angular.module('tasks', ['tasksService', 'ngRoute', 'ngTouch']).config( + [ '$routeProvider', function($routeProvider) { + $routeProvider. + // if URL fragment is /home, then load the home partial, with the + // MembersCtrl controller + when('/home', { + templateUrl : 'partials/home.html', + controller : TasksCtrl + // Add a default route + }).otherwise({ + redirectTo : '/home' + }); + } ]); \ No newline at end of file diff --git a/tasks-angularjs/src/main/webapp/js/controllers.js b/tasks-angularjs/src/main/webapp/js/controllers.js new file mode 100644 index 00000000..564f1a25 --- /dev/null +++ b/tasks-angularjs/src/main/webapp/js/controllers.js @@ -0,0 +1,138 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2013, Red Hat, Inc. and/or its affiliates, and individual + * contributors by the @authors tag. See the copyright.txt in the + * distribution for a full listing of individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +function TasksCtrl($scope, $http, Tasks) { + + $scope.countCompleted = function(tasks) { + $scope.completedTaskCount = 0; + for (var i=0; i< tasks.length; i++) { + if (tasks[i].complete == true) { + $scope.completedTaskCount++; + } + } + $scope.taskCount = tasks.length; + if (window.console) { + console.debug($scope.completedTaskCount + ' of ' + $scope.taskCount + ' tasks completed') + } + }; + + // Define a refresh function, that updates the data from the REST service + $scope.refresh = function() { + $scope.tasks = Tasks.query(function(data) { + $scope.countCompleted(data); + }); + }; + + // Define a redisplay function. + $scope.redisplay = function() { + }; + + // Define a reset function, that clears the prototype newMember object, and + // consequently, the form + $scope.reset = function() { + // clear input fields + $scope.newTask = {}; + }; + + // Define a submit function, which adds the task using the REST service, + // and displays any error messages + $scope.submit = function(task) { + $scope.errors = {}; + clearEditFlags(); + Tasks.save(task, function(data) { + + // log a success message to the console + if (window.console) console.info('Task Created: ' + task.title) + + // Update the list of tasks + $scope.refresh(); + + // Clear the form + $scope.reset(); + }, function(result) { + // log an error message to the console + if (window.console) console.error('Response code' + result.status + ': ' + result.data); + }); + + }; + + $scope.displayFilter = function(task) { + if ($scope.display == 'active') + return !task.complete; + else if ($scope.display == 'complete') + return task.complete; + else + return true; + }; + + $scope.markAllComplete = function(completed) { + if (window.console) { + if (completed) { + console.info('All tasks marked complete'); + } else { + console.info('All tasks marked incomplete'); + } + } + for (var i=0; i< $scope.tasks.length; i++) { + _markComplete($scope.tasks[i], completed); + } + $scope.countCompleted($scope.tasks); + }; + + $scope.markComplete = function(task, completed) { + _markComplete(task, completed); + $scope.countCompleted($scope.tasks); + }; + + function _markComplete(task, completed) { + task.complete = completed; + Tasks.save(task, function(data) { + // log a success message to the console + if (window.console) { + if (completed) { + console.info('Task marked complete on server: ' + task.title); + } else { + console.info('Task marked incomplete on server: ' + task.title); + } + } + + }, function(result) { + // log an error message to the console + if (window.console) console.error('Response code' + result.status + ': ' + result.data); + }); + }; + + function clearEditFlags() { + for (var i=0; i< $scope.tasks.length; i++) { + delete $scope.tasks[i]['editing']; + } + }; + + $scope.setEditFlag = function(task){ + clearEditFlags(); + task.editing=true; + }; + + $scope.display = 'all'; + + // Call the refresh() function, to populate the list of tasks + $scope.refresh(); + + // Initialize newTask here to prevent Angular from sending a request + // without a proper Content-Type. + $scope.reset(); + +} \ No newline at end of file diff --git a/tasks-angularjs/src/main/webapp/js/services.js b/tasks-angularjs/src/main/webapp/js/services.js new file mode 100644 index 00000000..39a0c54e --- /dev/null +++ b/tasks-angularjs/src/main/webapp/js/services.js @@ -0,0 +1,21 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2013, Red Hat, Inc. and/or its affiliates, and individual + * contributors by the @authors tag. See the copyright.txt in the + * distribution for a full listing of individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// Define the REST resource service, allowing us to interact with it as a high level service +angular.module('tasksService', ['ngResource']). + factory('Tasks', function($resource){ + return $resource('rest/task:taskId', {}); +}); \ No newline at end of file diff --git a/tasks-angularjs/src/main/webapp/partials/home.html b/tasks-angularjs/src/main/webapp/partials/home.html new file mode 100644 index 00000000..246f6c8f --- /dev/null +++ b/tasks-angularjs/src/main/webapp/partials/home.html @@ -0,0 +1,76 @@ + + + +

todos

+ +
+
+
+ {{taskCount - completedTaskCount}} + item + items + remaining +
+
+ + + +
+
+
    +
  • +
    + + +
    +
    + +
    + + + {{errors.title}} +
    +
    +
  • + +
  • +
    + + +
    +
    + {{task.title}} +
    +
    + +
    + + + {{errors.title}} +
    +
    +
  • +
+
+ +
+ Click to edit a todo +
+ + + \ No newline at end of file diff --git a/tasks-angularjs/src/test/java/org/jboss/as/quickstarts/tasksrs/DefaultDeployment.java b/tasks-angularjs/src/test/java/org/jboss/as/quickstarts/tasksrs/DefaultDeployment.java new file mode 100644 index 00000000..04d2a759 --- /dev/null +++ b/tasks-angularjs/src/test/java/org/jboss/as/quickstarts/tasksrs/DefaultDeployment.java @@ -0,0 +1,55 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2013, Red Hat, Inc. and/or its affiliates, and individual + * contributors by the @authors tag. See the copyright.txt in the + * distribution for a full listing of individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jboss.as.quickstarts.tasksrs; + +import java.io.File; + +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.spec.WebArchive; + +/** + * Enables prepare project-specific {@link WebArchive} for deployment. + * + * @author Lukas Fryc + * + */ +public class DefaultDeployment { + + private static final String WEBAPP_SRC = "src/main/webapp"; + + private WebArchive webArchive; + + public DefaultDeployment() { + webArchive = ShrinkWrap.create(WebArchive.class, "test.war").addAsWebInfResource( + new File(WEBAPP_SRC, "WEB-INF/beans.xml")); + } + + public DefaultDeployment withPersistence() { + webArchive = webArchive.addAsResource("META-INF/test-persistence.xml", "META-INF/persistence.xml").addAsWebInfResource( + "test-ds.xml", "test-ds.xml"); + return this; + } + + public DefaultDeployment withImportedData() { + webArchive = webArchive.addAsResource("import.sql"); + return this; + } + + public WebArchive getArchive() { + return webArchive; + } +} diff --git a/tasks-angularjs/src/test/java/org/jboss/as/quickstarts/tasksrs/TaskDaoTest.java b/tasks-angularjs/src/test/java/org/jboss/as/quickstarts/tasksrs/TaskDaoTest.java new file mode 100644 index 00000000..bbfa5455 --- /dev/null +++ b/tasks-angularjs/src/test/java/org/jboss/as/quickstarts/tasksrs/TaskDaoTest.java @@ -0,0 +1,128 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2013, Red Hat, Inc. and/or its affiliates, and individual + * contributors by the @authors tag. See the copyright.txt in the + * distribution for a full listing of individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jboss.as.quickstarts.tasksrs; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.io.FileNotFoundException; +import java.util.List; + +import javax.inject.Inject; +import javax.persistence.EntityManager; + +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.junit.Arquillian; +import org.jboss.as.quickstarts.tasksrs.model.*; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +/** + * @author Lukas Fryc + * @author Oliver Kiss + */ +@RunWith(Arquillian.class) +public class TaskDaoTest { + + @Deployment + public static WebArchive deployment() throws IllegalArgumentException, FileNotFoundException { + return new DefaultDeployment().withPersistence().withImportedData().getArchive() + .addClasses(Resources.class, User.class, UserDao.class, Task.class, TaskDao.class, TaskDao.class); + } + + @Inject + private EntityManager em; + + @Inject + private TaskDao taskDao; + + private User detachedUser; + + @Before + public void setUp() throws Exception { + detachedUser = new User("jdoe"); + detachedUser.setId(1L); + } + + @Test + public void user_should_be_created_with_one_task_attached() throws Exception { + // given + User user = new User("New user"); + Task task = new Task("New task"); + + // when + em.persist(user); + taskDao.createTask(user, task); + List userTasks = em.createQuery("SELECT t FROM Task t WHERE t.owner = :owner", Task.class) + .setParameter("owner", user).getResultList(); + + // then + assertEquals(1, userTasks.size()); + assertEquals(task, userTasks.get(0)); + } + + @Test + public void all_tasks_should_be_obtained_from_detachedUser() { + // when + List userTasks = taskDao.getAll(detachedUser); + + // then + assertEquals(2, userTasks.size()); + } + + @Test + public void range_of_tasks_should_be_provided_by_taskDao() { + // when + List headOfTasks = taskDao.getRange(detachedUser, 0, 1); + List tailOfTasks = taskDao.getRange(detachedUser, 1, 1); + + // then + assertEquals(1, headOfTasks.size()); + assertEquals(1, tailOfTasks.size()); + assertTrue(headOfTasks.get(0).getTitle().contains("first")); + assertTrue(tailOfTasks.get(0).getTitle().contains("second")); + } + + @Test + public void taskDao_should_provide_basic_case_insensitive_full_text_search() { + // given + String taskTitlePart = "FIRST"; + + // when + List titledTasks = taskDao.getForTitle(detachedUser, taskTitlePart); + + // then + assertEquals(1, titledTasks.size()); + assertTrue(titledTasks.get(0).getTitle().contains("first")); + } + + @Test + public void taskDao_should_remove_task_from_detachedUser() { + // given + Task task = new Task(); + task.setId(1L); + assertEquals(2, taskDao.getAll(detachedUser).size()); + + // when + taskDao.deleteTask(task); + + // then + assertEquals(1, taskDao.getAll(detachedUser).size()); + } +} diff --git a/tasks-angularjs/src/test/java/org/jboss/as/quickstarts/tasksrs/UserDaoTest.java b/tasks-angularjs/src/test/java/org/jboss/as/quickstarts/tasksrs/UserDaoTest.java new file mode 100644 index 00000000..cf43710e --- /dev/null +++ b/tasks-angularjs/src/test/java/org/jboss/as/quickstarts/tasksrs/UserDaoTest.java @@ -0,0 +1,92 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2013, Red Hat, Inc. and/or its affiliates, and individual + * contributors by the @authors tag. See the copyright.txt in the + * distribution for a full listing of individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jboss.as.quickstarts.tasksrs; + +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import java.io.FileNotFoundException; + +import javax.inject.Inject; +import javax.persistence.EntityManager; + +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.junit.Arquillian; +import org.jboss.as.quickstarts.tasksrs.model.*; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; + +/** + * @author Lukas Fryc + * @author Oliver Kiss + */ +@RunWith(Arquillian.class) +public class UserDaoTest { + + @Deployment + public static WebArchive deployment() throws IllegalArgumentException, FileNotFoundException { + return new DefaultDeployment().withPersistence().withImportedData().getArchive() + .addClasses(Resources.class, User.class, UserDao.class, Task.class, TaskDao.class, UserDao.class); + } + + @Inject + private UserDao userDao; + + @Inject + private EntityManager em; + + @Test + public void userDao_should_create_user_so_it_could_be_retrieved_from_userDao_by_username() { + // given + User created = new User("username1"); + + // when + userDao.createUser(created); + User retrieved = userDao.getForUsername("username1"); + + // then + assertTrue(em.contains(created)); + assertTrue(em.contains(retrieved)); + Assert.assertEquals(created, retrieved); + } + + @Test + public void user_should_be_retrievable_from_userDao_by_username() { + // given + String username = "jdoe"; + + // when + User retrieved = userDao.getForUsername(username); + + // then + Assert.assertEquals(username, retrieved.getUsername()); + } + + @Test + public void userDao_should_return_null_when_searching_for_non_existent_user() { + // given + String nonExistent = "nonExistent"; + + // when + User retrieved = userDao.getForUsername(nonExistent); + + // then + assertNull(retrieved); + } +} diff --git a/tasks-angularjs/src/test/resources/META-INF/test-persistence.xml b/tasks-angularjs/src/test/resources/META-INF/test-persistence.xml new file mode 100644 index 00000000..517d26d5 --- /dev/null +++ b/tasks-angularjs/src/test/resources/META-INF/test-persistence.xml @@ -0,0 +1,36 @@ + + + + + + + java:jboss/datasources/TasksRsQuickstartTestDS + + + + + + + diff --git a/tasks-angularjs/src/test/resources/arquillian.xml b/tasks-angularjs/src/test/resources/arquillian.xml new file mode 100644 index 00000000..92606f53 --- /dev/null +++ b/tasks-angularjs/src/test/resources/arquillian.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/tasks-angularjs/src/test/resources/import.sql b/tasks-angularjs/src/test/resources/import.sql new file mode 100644 index 00000000..d3d54243 --- /dev/null +++ b/tasks-angularjs/src/test/resources/import.sql @@ -0,0 +1,26 @@ +-- +-- JBoss, Home of Professional Open Source +-- Copyright 2013, Red Hat, Inc. and/or its affiliates, and individual +-- contributors by the @authors tag. See the copyright.txt in the +-- distribution for a full listing of individual contributors. +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- http://www.apache.org/licenses/LICENSE-2.0 +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- + +BEGIN +INSERT INTO User (ID, USERNAME) VALUES (1, 'jdoe'); +INSERT INTO User (ID, USERNAME) VALUES (2, 'emuster'); +COMMIT + +BEGIN +INSERT INTO Task (ID, OWNER_ID, TITLE) VALUES (1, 1, 'johns first task'); +INSERT INTO Task (ID, OWNER_ID, TITLE) VALUES (2, 1, 'johns second task'); +COMMIT \ No newline at end of file diff --git a/tasks-angularjs/src/test/resources/test-ds.xml b/tasks-angularjs/src/test/resources/test-ds.xml new file mode 100644 index 00000000..ed7f7cbb --- /dev/null +++ b/tasks-angularjs/src/test/resources/test-ds.xml @@ -0,0 +1,36 @@ + + + + + + + jdbc:h2:mem:tasks-rs-quickstart-test;DB_CLOSE_DELAY=-1 + h2 + + sa + sa + + +