├── Dockerfile ├── javaee6angularjsmysql ├── README.md ├── pom.xml └── src │ ├── main │ ├── java │ │ └── org │ │ │ └── jboss │ │ │ └── as │ │ │ └── quickstarts │ │ │ └── kitchensink │ │ │ ├── data │ │ │ ├── MemberListProducer.java │ │ │ └── MemberRepository.java │ │ │ ├── model │ │ │ └── Member.java │ │ │ ├── rest │ │ │ ├── JaxRsActivator.java │ │ │ └── MemberResourceRESTService.java │ │ │ ├── service │ │ │ └── MemberRegistration.java │ │ │ └── util │ │ │ └── Resources.java │ ├── resources │ │ ├── META-INF │ │ │ ├── backup_persistence .xml │ │ │ └── persistence.xml │ │ └── import.sql │ └── webapp │ │ ├── WEB-INF │ │ └── beans.xml │ │ ├── css │ │ └── screen.css │ │ ├── gfx │ │ ├── asidebkg.png │ │ ├── bkg-blkheader.png │ │ ├── dualbrand_logo.png │ │ ├── headerbkg.png │ │ ├── wildfly-banner.png │ │ └── wildfly_400x130.jpg │ │ ├── index.html │ │ ├── js │ │ ├── app.js │ │ ├── controllers.js │ │ ├── libs │ │ │ ├── angular-resource.js │ │ │ └── angular.js │ │ └── services.js │ │ └── partials │ │ └── home.html │ └── test │ ├── java │ └── org │ │ └── jboss │ │ └── as │ │ └── quickstarts │ │ └── kitchensink │ │ └── test │ │ └── MemberRegistrationTest.java │ └── resources │ ├── META-INF │ └── test-persistence.xml │ ├── arquillian.xml │ └── test-ds.xml ├── mysql-connector-java-5.1.31-bin.jar ├── mysql-sample-ds.xml ├── readme.md ├── screenshots ├── after_docker_build.png ├── browser.png ├── build_success.png ├── connect_to_database.png ├── docker_network_create.png ├── docker_quickstart_terminal.png ├── docker_run_mysql.png ├── download_unzip.png ├── mark_paste.png ├── mysql_root_password.png ├── mysql_sample_ds_xml.png ├── mysql_sql_editor.png ├── mysql_workbench_new_connection.png ├── mysqlapp_with_Dockerfile.png ├── persistence_xml.png ├── sql_editor.png ├── start_sh_running.png ├── target_directory.png └── wildfly_admin_console.png └── standalone.xml /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM centos/wildfly 2 | 3 | COPY standalone.xml /opt/wildfly/standalone/configuration/ 4 | COPY mysql-connector-java-5.1.31-bin.jar /opt/wildfly/standalone/deployments/ 5 | COPY mysql-sample-ds.xml /opt/wildfly/standalone/deployments/ 6 | 7 | COPY javaee6angularjsmysql/target/javaee6angularjsmysql.war /opt/wildfly/standalone/deployments/ 8 | -------------------------------------------------------------------------------- /javaee6angularjsmysql/README.md: -------------------------------------------------------------------------------- 1 | See the parent directory's readme.md file 2 | -------------------------------------------------------------------------------- /javaee6angularjsmysql/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 18 | 20 | 4.0.0 21 | 22 | org.wildfly.quickstarts 23 | javaee6angularjsmysql 24 | 9.0.0-SNAPSHOT 25 | war 26 | WildFly Quickstarts: Kitchensink with AngularJS 27 | A starter Java EE 7 webapp project for use on JBoss WildFly / WildFly, generated from the jboss-javaee6-webapp archetype, using AngularJS for the view 28 | 29 | http://wildfly.org 30 | 31 | 32 | Apache License, Version 2.0 33 | repo 34 | http://www.apache.org/licenses/LICENSE-2.0.html 35 | 36 | 37 | 38 | 39 | 40 | 42 | UTF-8 43 | 44 | 45 | 1.0.2.Final 46 | 47 | 8.2.1.Final 48 | 49 | 50 | 3.1 51 | 2.16 52 | 2.5 53 | 54 | 55 | 1.7 56 | 1.7 57 | 58 | 59 | 60 | 61 | 62 | 70 | 71 | org.wildfly.bom 72 | jboss-javaee-7.0-with-tools 73 | ${version.jboss.bom} 74 | pom 75 | import 76 | 77 | 78 | org.wildfly.bom 79 | jboss-javaee-7.0-with-hibernate 80 | ${version.jboss.bom} 81 | pom 82 | import 83 | 84 | 85 | 86 | 87 | 88 | 89 | 91 | 92 | 93 | 94 | javax.enterprise 95 | cdi-api 96 | provided 97 | 98 | 99 | 101 | 102 | org.jboss.spec.javax.annotation 103 | jboss-annotations-api_1.2_spec 104 | provided 105 | 106 | 107 | 108 | 109 | org.jboss.resteasy 110 | jaxrs-api 111 | provided 112 | 113 | 114 | 115 | 116 | org.hibernate.javax.persistence 117 | hibernate-jpa-2.1-api 118 | provided 119 | 120 | 121 | 122 | 123 | org.jboss.spec.javax.ejb 124 | jboss-ejb-api_3.2_spec 125 | provided 126 | 127 | 128 | 129 | 130 | 131 | 132 | org.hibernate 133 | hibernate-validator 134 | provided 135 | 136 | 137 | org.slf4j 138 | slf4j-api 139 | 140 | 141 | 142 | 143 | 144 | 145 | 147 | 148 | org.hibernate 149 | hibernate-jpamodelgen 150 | provided 151 | 152 | 153 | 155 | 156 | org.hibernate 157 | hibernate-validator-annotation-processor 158 | provided 159 | 160 | 161 | 162 | 163 | junit 164 | junit 165 | test 166 | 167 | 168 | 169 | 171 | 172 | org.jboss.arquillian.junit 173 | arquillian-junit-container 174 | test 175 | 176 | 177 | 178 | org.jboss.arquillian.protocol 179 | arquillian-protocol-servlet 180 | test 181 | 182 | 183 | 184 | 185 | 186 | 188 | ${project.artifactId} 189 | 190 | 191 | maven-war-plugin 192 | ${version.war.plugin} 193 | 194 | 196 | false 197 | 198 | 199 | 201 | 202 | 203 | org.wildfly.plugins 204 | wildfly-maven-plugin 205 | ${version.wildfly.maven.plugin} 206 | 207 | 208 | 209 | 210 | 211 | 212 | 214 | 216 | default 217 | 218 | true 219 | 220 | 221 | 222 | 223 | maven-surefire-plugin 224 | ${version.surefire.plugin} 225 | 226 | true 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 237 | 239 | 240 | arq-wildfly-managed 241 | 242 | 243 | org.wildfly 244 | wildfly-arquillian-container-managed 245 | test 246 | 247 | 248 | 249 | 250 | 251 | 253 | 254 | arq-wildfly-remote 255 | 256 | 257 | org.wildfly 258 | wildfly-arquillian-container-remote 259 | test 260 | 261 | 262 | 263 | 264 | 265 | 267 | 269 | 271 | 272 | openshift 273 | 274 | 275 | 276 | maven-war-plugin 277 | ${version.war.plugin} 278 | 279 | deployments 280 | ROOT 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | -------------------------------------------------------------------------------- /javaee6angularjsmysql/src/main/java/org/jboss/as/quickstarts/kitchensink/data/MemberListProducer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * JBoss, Home of Professional Open Source 3 | * Copyright 2013, Red Hat, Inc. and/or its affiliates, and individual 4 | * contributors by the @authors tag. See the copyright.txt in the 5 | * distribution for a full listing of individual contributors. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.jboss.as.quickstarts.kitchensink.data; 18 | 19 | import javax.annotation.PostConstruct; 20 | import javax.enterprise.context.RequestScoped; 21 | import javax.enterprise.event.Observes; 22 | import javax.enterprise.event.Reception; 23 | import javax.enterprise.inject.Produces; 24 | import javax.inject.Inject; 25 | import javax.inject.Named; 26 | import java.util.List; 27 | 28 | import org.jboss.as.quickstarts.kitchensink.model.Member; 29 | 30 | @RequestScoped 31 | public class MemberListProducer { 32 | 33 | @Inject 34 | private MemberRepository memberRepository; 35 | 36 | private List members; 37 | 38 | // @Named provides access the return value via the EL variable name "members" in the UI (e.g. 39 | // Facelets or JSP view) 40 | @Produces 41 | @Named 42 | public List getMembers() { 43 | return members; 44 | } 45 | 46 | public void onMemberListChanged(@Observes(notifyObserver = Reception.IF_EXISTS) final Member member) { 47 | retrieveAllMembersOrderedByName(); 48 | } 49 | 50 | @PostConstruct 51 | public void retrieveAllMembersOrderedByName() { 52 | members = memberRepository.findAllOrderedByName(); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /javaee6angularjsmysql/src/main/java/org/jboss/as/quickstarts/kitchensink/data/MemberRepository.java: -------------------------------------------------------------------------------- 1 | /* 2 | * JBoss, Home of Professional Open Source 3 | * Copyright 2013, Red Hat, Inc. and/or its affiliates, and individual 4 | * contributors by the @authors tag. See the copyright.txt in the 5 | * distribution for a full listing of individual contributors. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.jboss.as.quickstarts.kitchensink.data; 18 | 19 | import javax.enterprise.context.ApplicationScoped; 20 | import javax.inject.Inject; 21 | import javax.persistence.EntityManager; 22 | import javax.persistence.criteria.CriteriaBuilder; 23 | import javax.persistence.criteria.CriteriaQuery; 24 | import javax.persistence.criteria.Root; 25 | import java.util.List; 26 | 27 | import org.jboss.as.quickstarts.kitchensink.model.Member; 28 | 29 | @ApplicationScoped 30 | public class MemberRepository { 31 | 32 | @Inject 33 | private EntityManager em; 34 | 35 | public Member findById(Long id) { 36 | return em.find(Member.class, id); 37 | } 38 | 39 | public Member findByEmail(String email) { 40 | CriteriaBuilder cb = em.getCriteriaBuilder(); 41 | CriteriaQuery criteria = cb.createQuery(Member.class); 42 | Root member = criteria.from(Member.class); 43 | // Swap criteria statements if you would like to try out type-safe criteria queries, a new 44 | // feature in JPA 2.0 45 | // criteria.select(member).where(cb.equal(member.get(Member_.name), email)); 46 | criteria.select(member).where(cb.equal(member.get("email"), email)); 47 | return em.createQuery(criteria).getSingleResult(); 48 | } 49 | 50 | public List findAllOrderedByName() { 51 | CriteriaBuilder cb = em.getCriteriaBuilder(); 52 | CriteriaQuery criteria = cb.createQuery(Member.class); 53 | Root member = criteria.from(Member.class); 54 | // Swap criteria statements if you would like to try out type-safe criteria queries, a new 55 | // feature in JPA 2.0 56 | // criteria.select(member).orderBy(cb.asc(member.get(Member_.name))); 57 | criteria.select(member).orderBy(cb.asc(member.get("name"))); 58 | return em.createQuery(criteria).getResultList(); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /javaee6angularjsmysql/src/main/java/org/jboss/as/quickstarts/kitchensink/model/Member.java: -------------------------------------------------------------------------------- 1 | /* 2 | * JBoss, Home of Professional Open Source 3 | * Copyright 2013, Red Hat, Inc. and/or its affiliates, and individual 4 | * contributors by the @authors tag. See the copyright.txt in the 5 | * distribution for a full listing of individual contributors. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.jboss.as.quickstarts.kitchensink.model; 18 | 19 | import java.io.Serializable; 20 | 21 | import javax.persistence.Column; 22 | import javax.persistence.Entity; 23 | import javax.persistence.GeneratedValue; 24 | import javax.persistence.Id; 25 | import javax.persistence.Table; 26 | import javax.persistence.UniqueConstraint; 27 | import javax.validation.constraints.Digits; 28 | import javax.validation.constraints.NotNull; 29 | import javax.validation.constraints.Pattern; 30 | import javax.validation.constraints.Size; 31 | import javax.xml.bind.annotation.XmlRootElement; 32 | 33 | import org.hibernate.validator.constraints.Email; 34 | import org.hibernate.validator.constraints.NotEmpty; 35 | 36 | @SuppressWarnings("serial") 37 | @Entity 38 | @XmlRootElement 39 | @Table(uniqueConstraints = @UniqueConstraint(columnNames = "email")) 40 | public class Member implements Serializable { 41 | 42 | @Id 43 | @GeneratedValue 44 | private Long id; 45 | 46 | @NotNull 47 | @Size(min = 1, max = 25) 48 | @Pattern(regexp = "[^0-9]*", message = "Must not contain numbers") 49 | private String name; 50 | 51 | @NotNull 52 | @NotEmpty 53 | @Email 54 | private String email; 55 | 56 | @NotNull 57 | @Size(min = 10, max = 12) 58 | @Digits(fraction = 0, integer = 12) 59 | @Column(name = "phone_number") 60 | private String phoneNumber; 61 | 62 | public Long getId() { 63 | return id; 64 | } 65 | 66 | public void setId(Long id) { 67 | this.id = id; 68 | } 69 | 70 | public String getName() { 71 | return name; 72 | } 73 | 74 | public void setName(String name) { 75 | this.name = name; 76 | } 77 | 78 | public String getEmail() { 79 | return email; 80 | } 81 | 82 | public void setEmail(String email) { 83 | this.email = email; 84 | } 85 | 86 | public String getPhoneNumber() { 87 | return phoneNumber; 88 | } 89 | 90 | public void setPhoneNumber(String phoneNumber) { 91 | this.phoneNumber = phoneNumber; 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /javaee6angularjsmysql/src/main/java/org/jboss/as/quickstarts/kitchensink/rest/JaxRsActivator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * JBoss, Home of Professional Open Source 3 | * Copyright 2013, Red Hat, Inc. and/or its affiliates, and individual 4 | * contributors by the @authors tag. See the copyright.txt in the 5 | * distribution for a full listing of individual contributors. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.jboss.as.quickstarts.kitchensink.rest; 18 | 19 | import javax.ws.rs.ApplicationPath; 20 | import javax.ws.rs.core.Application; 21 | 22 | /** 23 | * A class extending {@link Application} and annotated with @ApplicationPath is the Java EE 7 24 | * "no XML" approach to activating JAX-RS. 25 | * 26 | *

27 | * Resources are served relative to the servlet path specified in the {@link ApplicationPath} 28 | * annotation. 29 | *

30 | */ 31 | @ApplicationPath("/rest") 32 | public class JaxRsActivator extends Application { 33 | /* class body intentionally left blank */ 34 | } 35 | -------------------------------------------------------------------------------- /javaee6angularjsmysql/src/main/java/org/jboss/as/quickstarts/kitchensink/rest/MemberResourceRESTService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * JBoss, Home of Professional Open Source 3 | * Copyright 2013, Red Hat, Inc. and/or its affiliates, and individual 4 | * contributors by the @authors tag. See the copyright.txt in the 5 | * distribution for a full listing of individual contributors. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.jboss.as.quickstarts.kitchensink.rest; 18 | 19 | import java.util.HashMap; 20 | import java.util.HashSet; 21 | import java.util.List; 22 | import java.util.Map; 23 | import java.util.Set; 24 | import java.util.logging.Logger; 25 | 26 | import javax.enterprise.context.RequestScoped; 27 | import javax.inject.Inject; 28 | import javax.persistence.NoResultException; 29 | import javax.validation.ConstraintViolation; 30 | import javax.validation.ConstraintViolationException; 31 | import javax.validation.ValidationException; 32 | import javax.validation.Validator; 33 | import javax.ws.rs.Consumes; 34 | import javax.ws.rs.GET; 35 | import javax.ws.rs.POST; 36 | import javax.ws.rs.Path; 37 | import javax.ws.rs.PathParam; 38 | import javax.ws.rs.Produces; 39 | import javax.ws.rs.WebApplicationException; 40 | import javax.ws.rs.core.MediaType; 41 | import javax.ws.rs.core.Response; 42 | 43 | import org.jboss.as.quickstarts.kitchensink.data.MemberRepository; 44 | import org.jboss.as.quickstarts.kitchensink.model.Member; 45 | import org.jboss.as.quickstarts.kitchensink.service.MemberRegistration; 46 | 47 | /** 48 | * JAX-RS Example 49 | *

50 | * This class produces a RESTful service to read/write the contents of the members table. 51 | */ 52 | @Path("/members") 53 | @RequestScoped 54 | public class MemberResourceRESTService { 55 | 56 | @Inject 57 | private Logger log; 58 | 59 | @Inject 60 | private Validator validator; 61 | 62 | @Inject 63 | private MemberRepository repository; 64 | 65 | @Inject 66 | MemberRegistration registration; 67 | 68 | @GET 69 | @Produces(MediaType.APPLICATION_JSON) 70 | public List listAllMembers() { 71 | return repository.findAllOrderedByName(); 72 | } 73 | 74 | @GET 75 | @Path("/{id:[0-9][0-9]*}") 76 | @Produces(MediaType.APPLICATION_JSON) 77 | public Member lookupMemberById(@PathParam("id") long id) { 78 | Member member = repository.findById(id); 79 | if (member == null) { 80 | throw new WebApplicationException(Response.Status.NOT_FOUND); 81 | } 82 | return member; 83 | } 84 | 85 | /** 86 | * Creates a new member from the values provided. Performs validation, and will return a JAX-RS response with either 200 ok, 87 | * or with a map of fields, and related errors. 88 | */ 89 | @POST 90 | @Consumes(MediaType.APPLICATION_JSON) 91 | @Produces(MediaType.APPLICATION_JSON) 92 | public Response createMember(Member member) { 93 | 94 | Response.ResponseBuilder builder = null; 95 | 96 | try { 97 | // Validates member using bean validation 98 | validateMember(member); 99 | 100 | registration.register(member); 101 | 102 | // Create an "ok" response 103 | builder = Response.ok(); 104 | } catch (ConstraintViolationException ce) { 105 | // Handle bean validation issues 106 | builder = createViolationResponse(ce.getConstraintViolations()); 107 | } catch (ValidationException e) { 108 | // Handle the unique constrain violation 109 | Map responseObj = new HashMap<>(); 110 | responseObj.put("email", "Email taken"); 111 | builder = Response.status(Response.Status.CONFLICT).entity(responseObj); 112 | } catch (Exception e) { 113 | // Handle generic exceptions 114 | Map responseObj = new HashMap<>(); 115 | responseObj.put("error", e.getMessage()); 116 | builder = Response.status(Response.Status.BAD_REQUEST).entity(responseObj); 117 | } 118 | 119 | return builder.build(); 120 | } 121 | 122 | /** 123 | *

124 | * Validates the given Member variable and throws validation exceptions based on the type of error. If the error is standard 125 | * bean validation errors then it will throw a ConstraintValidationException with the set of the constraints violated. 126 | *

127 | *

128 | * If the error is caused because an existing member with the same email is registered it throws a regular validation 129 | * exception so that it can be interpreted separately. 130 | *

131 | * 132 | * @param member Member to be validated 133 | * @throws ConstraintViolationException If Bean Validation errors exist 134 | * @throws ValidationException If member with the same email already exists 135 | */ 136 | private void validateMember(Member member) throws ConstraintViolationException, ValidationException { 137 | // Create a bean validator and check for issues. 138 | Set> violations = validator.validate(member); 139 | 140 | if (!violations.isEmpty()) { 141 | throw new ConstraintViolationException(new HashSet>(violations)); 142 | } 143 | 144 | // Check the uniqueness of the email address 145 | if (emailAlreadyExists(member.getEmail())) { 146 | throw new ValidationException("Unique Email Violation"); 147 | } 148 | } 149 | 150 | /** 151 | * Creates a JAX-RS "Bad Request" response including a map of all violation fields, and their message. This can then be used 152 | * by clients to show violations. 153 | * 154 | * @param violations A set of violations that needs to be reported 155 | * @return JAX-RS response containing all violations 156 | */ 157 | private Response.ResponseBuilder createViolationResponse(Set> violations) { 158 | log.fine("Validation completed. violations found: " + violations.size()); 159 | 160 | Map responseObj = new HashMap<>(); 161 | 162 | for (ConstraintViolation violation : violations) { 163 | responseObj.put(violation.getPropertyPath().toString(), violation.getMessage()); 164 | } 165 | 166 | return Response.status(Response.Status.BAD_REQUEST).entity(responseObj); 167 | } 168 | 169 | /** 170 | * Checks if a member with the same email address is already registered. This is the only way to easily capture the 171 | * "@UniqueConstraint(columnNames = "email")" constraint from the Member class. 172 | * 173 | * @param email The email to check 174 | * @return True if the email already exists, and false otherwise 175 | */ 176 | public boolean emailAlreadyExists(String email) { 177 | Member member = null; 178 | try { 179 | member = repository.findByEmail(email); 180 | } catch (NoResultException e) { 181 | // ignore 182 | } 183 | return member != null; 184 | } 185 | } 186 | -------------------------------------------------------------------------------- /javaee6angularjsmysql/src/main/java/org/jboss/as/quickstarts/kitchensink/service/MemberRegistration.java: -------------------------------------------------------------------------------- 1 | /* 2 | * JBoss, Home of Professional Open Source 3 | * Copyright 2013, Red Hat, Inc. and/or its affiliates, and individual 4 | * contributors by the @authors tag. See the copyright.txt in the 5 | * distribution for a full listing of individual contributors. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.jboss.as.quickstarts.kitchensink.service; 18 | 19 | import org.jboss.as.quickstarts.kitchensink.model.Member; 20 | 21 | import javax.ejb.Stateless; 22 | import javax.enterprise.event.Event; 23 | import javax.inject.Inject; 24 | import javax.persistence.EntityManager; 25 | import java.util.logging.Logger; 26 | 27 | // The @Stateless annotation eliminates the need for manual transaction demarcation 28 | @Stateless 29 | public class MemberRegistration { 30 | 31 | @Inject 32 | private Logger log; 33 | 34 | @Inject 35 | private EntityManager em; 36 | 37 | @Inject 38 | private Event memberEventSrc; 39 | 40 | public void register(Member member) throws Exception { 41 | log.info("Registering " + member.getName()); 42 | em.persist(member); 43 | memberEventSrc.fire(member); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /javaee6angularjsmysql/src/main/java/org/jboss/as/quickstarts/kitchensink/util/Resources.java: -------------------------------------------------------------------------------- 1 | /* 2 | * JBoss, Home of Professional Open Source 3 | * Copyright 2013, Red Hat, Inc. and/or its affiliates, and individual 4 | * contributors by the @authors tag. See the copyright.txt in the 5 | * distribution for a full listing of individual contributors. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.jboss.as.quickstarts.kitchensink.util; 18 | 19 | import java.util.logging.Logger; 20 | 21 | import javax.enterprise.inject.Produces; 22 | import javax.enterprise.inject.spi.InjectionPoint; 23 | import javax.persistence.EntityManager; 24 | import javax.persistence.PersistenceContext; 25 | 26 | /** 27 | * This class uses CDI to alias Java EE resources, such as the persistence context, to CDI beans 28 | * 29 | *

30 | * Example injection on a managed bean field: 31 | *

32 | * 33 | *
34 |  * @Inject
35 |  * private EntityManager em;
36 |  * 
37 | */ 38 | public class Resources { 39 | 40 | @Produces 41 | @PersistenceContext 42 | private EntityManager em; 43 | 44 | @Produces 45 | public Logger produceLog(InjectionPoint injectionPoint) { 46 | return Logger.getLogger(injectionPoint.getMember().getDeclaringClass().getName()); 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /javaee6angularjsmysql/src/main/resources/META-INF/backup_persistence .xml: -------------------------------------------------------------------------------- 1 | 2 | 18 | 23 | 24 | 26 | 28 | java:jboss/datasources/ExampleMySQLDS 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /javaee6angularjsmysql/src/main/resources/META-INF/persistence.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | java:jboss/datasources/MySQLSampleDS 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /javaee6angularjsmysql/src/main/resources/import.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- JBoss, Home of Professional Open Source 3 | -- Copyright 2013, Red Hat, Inc. and/or its affiliates, and individual 4 | -- contributors by the @authors tag. See the copyright.txt in the 5 | -- distribution for a full listing of individual contributors. 6 | -- 7 | -- Licensed under the Apache License, Version 2.0 (the "License"); 8 | -- you may not use this file except in compliance with the License. 9 | -- You may obtain a copy of the License at 10 | -- http://www.apache.org/licenses/LICENSE-2.0 11 | -- Unless required by applicable law or agreed to in writing, software 12 | -- distributed under the License is distributed on an "AS IS" BASIS, 13 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | -- See the License for the specific language governing permissions and 15 | -- limitations under the License. 16 | -- 17 | 18 | -- You can use this file to load seed data into the database using SQL statements 19 | insert into Member (id, name, email, phone_number) values (0, 'John Smith', 'john.smith@mailinator.com', '2125551212') -------------------------------------------------------------------------------- /javaee6angularjsmysql/src/main/webapp/WEB-INF/beans.xml: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 23 | 24 | -------------------------------------------------------------------------------- /javaee6angularjsmysql/src/main/webapp/css/screen.css: -------------------------------------------------------------------------------- 1 | /* 2 | * JBoss, Home of Professional Open Source 3 | * Copyright 2013, Red Hat, Inc. and/or its affiliates, and individual 4 | * contributors by the @authors tag. See the copyright.txt in the 5 | * distribution for a full listing of individual contributors. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | /* Core styles for the page */ 18 | body { 19 | margin: 0; 20 | padding: 0; 21 | background-color: #F1F1F1; 22 | font-family: "Lucida Sans Unicode", "Lucida Grande", sans-serif; 23 | font-size: 0.8em; 24 | color:#363636; 25 | } 26 | 27 | #container { 28 | margin: 0 auto; 29 | padding: 0 20px 10px 20px; 30 | border-top: 5px solid #000000; 31 | border-left: 5px solid #8c8f91; 32 | border-right: 5px solid #8c8f91; 33 | border-bottom: 25px solid #8c8f91; 34 | width: 865px; /* subtract 40px from banner width for padding */ 35 | background: #FFFFFF; 36 | background-image: url(../gfx/headerbkg.png); 37 | background-repeat: repeat-x; 38 | padding-top: 30px; 39 | box-shadow: 3px 3px 15px #d5d5d5; 40 | } 41 | #content { 42 | float: left; 43 | width: 500px; 44 | margin: 20px; 45 | } 46 | #aside { 47 | font-size: 0.9em; 48 | width: 275px; 49 | float: left; 50 | margin: 20px 0px; 51 | border: 1px solid #D5D5D5; 52 | background: #F1F1F1; 53 | background-image: url(../gfx/asidebkg.png); 54 | background-repeat: repeat-x; 55 | padding: 20px; 56 | } 57 | 58 | #aside ul { 59 | padding-left: 30px; 60 | } 61 | .dualbrand { 62 | float: right; 63 | padding-right: 10px; 64 | } 65 | #footer { 66 | clear: both; 67 | text-align: center; 68 | color: #666666; 69 | font-size: 0.85em; 70 | } 71 | code { 72 | font-size: 1.1em; 73 | } 74 | a { 75 | color: #4a5d75; 76 | text-decoration: none; 77 | } 78 | a:hover { 79 | color: #369; 80 | text-decoration: underline; 81 | } 82 | h1 { 83 | color:#243446; 84 | font-size: 2.25em; 85 | } 86 | h2 { 87 | font-size: 1em; 88 | } 89 | h3 { 90 | color:#243446; 91 | } 92 | h4 { 93 | } 94 | h5 { 95 | } 96 | h6 { 97 | } 98 | /* Member registration styles */ 99 | span.invalid { 100 | padding-left: 3px; 101 | color: red; 102 | } 103 | form { 104 | padding: 1em; 105 | font: 80%/1 sans-serif; 106 | width: 375px; 107 | border: 1px solid #D5D5D5; 108 | } 109 | label { 110 | float: left; 111 | width: 15%; 112 | margin-left: 20px; 113 | margin-right: 0.5em; 114 | padding-top: 0.2em; 115 | text-align: right; 116 | font-weight: bold; 117 | color:#363636; 118 | } 119 | input { 120 | margin-bottom: 8px; 121 | } 122 | .register { 123 | float: left; 124 | margin-left: 85px; 125 | } 126 | 127 | /* ----- table style ------- */ 128 | 129 | 130 | /* = Simple Table style (black header, grey/white stripes */ 131 | 132 | .simpletablestyle { 133 | background-color:#E6E7E8; 134 | clear:both; 135 | width: 550px; 136 | } 137 | 138 | .simpletablestyle img { 139 | border:0px; 140 | } 141 | 142 | .simpletablestyle td { 143 | height:2em; 144 | padding-left: 6px; 145 | font-size:11px; 146 | padding:5px 5px; 147 | } 148 | 149 | .simpletablestyle th { 150 | background: url(../gfx/bkg-blkheader.png) black repeat-x top left; 151 | font-size:12px; 152 | font-weight:normal; 153 | padding:0 10px 0 5px; 154 | border-bottom:#999999 dotted 1px; 155 | } 156 | 157 | .simpletablestyle thead { 158 | background: url(../gfx/bkg-blkheader.png) black repeat-x top left; 159 | height:31px; 160 | font-size:10px; 161 | font-weight:bold; 162 | color:#FFFFFF; 163 | text-align:left; 164 | } 165 | 166 | .simpletablestyle .header a { 167 | color:#94aebd; 168 | } 169 | 170 | .simpletablestype tfoot { 171 | height: 20px; 172 | font-size: 10px; 173 | font-weight: bold; 174 | background-color: #EAECEE; 175 | text-align: center; 176 | } 177 | 178 | .simpletablestyle tr.header td { 179 | padding: 0px 10px 0px 5px; 180 | } 181 | 182 | 183 | .simpletablestyle .subheader { 184 | background-color: #e6e7e8; 185 | font-size:10px; 186 | font-weight:bold; 187 | color:#000000; 188 | text-align:left; 189 | } 190 | 191 | /* Using new CSS3 selectors for styling*/ 192 | .simpletablestyle tr:nth-child(odd) { 193 | background: #f4f3f3; 194 | } 195 | .simpletablestyle tr:nth-child(even) { 196 | background: #ffffff; 197 | } 198 | 199 | .simpletablestyle td a:hover { 200 | color:#3883ce; 201 | text-decoration:none; 202 | } 203 | -------------------------------------------------------------------------------- /javaee6angularjsmysql/src/main/webapp/gfx/asidebkg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/burrsutter/docker_mysql_tutorial/39fefcf7fd0ca8184a8c0aa5079850247a5b91d7/javaee6angularjsmysql/src/main/webapp/gfx/asidebkg.png -------------------------------------------------------------------------------- /javaee6angularjsmysql/src/main/webapp/gfx/bkg-blkheader.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/burrsutter/docker_mysql_tutorial/39fefcf7fd0ca8184a8c0aa5079850247a5b91d7/javaee6angularjsmysql/src/main/webapp/gfx/bkg-blkheader.png -------------------------------------------------------------------------------- /javaee6angularjsmysql/src/main/webapp/gfx/dualbrand_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/burrsutter/docker_mysql_tutorial/39fefcf7fd0ca8184a8c0aa5079850247a5b91d7/javaee6angularjsmysql/src/main/webapp/gfx/dualbrand_logo.png -------------------------------------------------------------------------------- /javaee6angularjsmysql/src/main/webapp/gfx/headerbkg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/burrsutter/docker_mysql_tutorial/39fefcf7fd0ca8184a8c0aa5079850247a5b91d7/javaee6angularjsmysql/src/main/webapp/gfx/headerbkg.png -------------------------------------------------------------------------------- /javaee6angularjsmysql/src/main/webapp/gfx/wildfly-banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/burrsutter/docker_mysql_tutorial/39fefcf7fd0ca8184a8c0aa5079850247a5b91d7/javaee6angularjsmysql/src/main/webapp/gfx/wildfly-banner.png -------------------------------------------------------------------------------- /javaee6angularjsmysql/src/main/webapp/gfx/wildfly_400x130.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/burrsutter/docker_mysql_tutorial/39fefcf7fd0ca8184a8c0aa5079850247a5b91d7/javaee6angularjsmysql/src/main/webapp/gfx/wildfly_400x130.jpg -------------------------------------------------------------------------------- /javaee6angularjsmysql/src/main/webapp/index.html: -------------------------------------------------------------------------------- 1 | 17 | 18 | 19 | 20 | kitchensink 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /javaee6angularjsmysql/src/main/webapp/js/app.js: -------------------------------------------------------------------------------- 1 | /* 2 | * JBoss, Home of Professional Open Source 3 | * Copyright 2013, Red Hat, Inc. and/or its affiliates, and individual 4 | * contributors by the @authors tag. See the copyright.txt in the 5 | * distribution for a full listing of individual contributors. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | // Define any routes for the app 18 | // 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/wildfly-kitchensink-angularjs/#/home 19 | angular.module('kitchensink', ['membersService']).config( 20 | [ '$routeProvider', function($routeProvider) { 21 | $routeProvider. 22 | // if URL fragment is /home, then load the home partial, with the 23 | // MembersCtrl controller 24 | when('/home', { 25 | templateUrl : 'partials/home.html', 26 | controller : MembersCtrl 27 | // Add a default route 28 | }).otherwise({ 29 | redirectTo : '/home' 30 | }); 31 | } ]); -------------------------------------------------------------------------------- /javaee6angularjsmysql/src/main/webapp/js/controllers.js: -------------------------------------------------------------------------------- 1 | /* 2 | * JBoss, Home of Professional Open Source 3 | * Copyright 2013, Red Hat, Inc. and/or its affiliates, and individual 4 | * contributors by the @authors tag. See the copyright.txt in the 5 | * distribution for a full listing of individual contributors. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | function MembersCtrl($scope, $http, Members) { 18 | 19 | // Define a refresh function, that updates the data from the REST service 20 | $scope.refresh = function() { 21 | $scope.members = Members.query(); 22 | }; 23 | 24 | // Define a reset function, that clears the prototype newMember object, and 25 | // consequently, the form 26 | $scope.reset = function() { 27 | // clear input fields 28 | $scope.newMember = {}; 29 | }; 30 | 31 | // Define a register function, which adds the member using the REST service, 32 | // and displays any error messages 33 | $scope.register = function() { 34 | $scope.successMessages = ''; 35 | $scope.errorMessages = ''; 36 | $scope.errors = {}; 37 | 38 | Members.save($scope.newMember, function(data) { 39 | 40 | // mark success on the registration form 41 | $scope.successMessages = [ 'Member Registered' ]; 42 | 43 | // Update the list of members 44 | $scope.refresh(); 45 | 46 | // Clear the form 47 | $scope.reset(); 48 | }, function(result) { 49 | if ((result.status == 409) || (result.status == 400)) { 50 | $scope.errors = result.data; 51 | } else { 52 | $scope.errorMessages = [ 'Unknown server error' ]; 53 | } 54 | $scope.$apply(); 55 | }); 56 | 57 | }; 58 | 59 | // Call the refresh() function, to populate the list of members 60 | $scope.refresh(); 61 | 62 | // Initialize newMember here to prevent Angular from sending a request 63 | // without a proper Content-Type. 64 | $scope.reset(); 65 | 66 | // Set the default orderBy to the name property 67 | $scope.orderBy = 'name'; 68 | } -------------------------------------------------------------------------------- /javaee6angularjsmysql/src/main/webapp/js/libs/angular-resource.js: -------------------------------------------------------------------------------- 1 | /* 2 | * JBoss, Home of Professional Open Source 3 | * Copyright 2013, Red Hat, Inc. and/or its affiliates, and individual 4 | * contributors by the @authors tag. See the copyright.txt in the 5 | * distribution for a full listing of individual contributors. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | /** 18 | * @license AngularJS v1.1.2 19 | * (c) 2010-2012 Google, Inc. http://angularjs.org 20 | * License: MIT 21 | */ 22 | (function(window, angular, undefined) { 23 | 'use strict'; 24 | 25 | /** 26 | * @ngdoc overview 27 | * @name ngResource 28 | * @description 29 | */ 30 | 31 | /** 32 | * @ngdoc object 33 | * @name ngResource.$resource 34 | * @requires $http 35 | * 36 | * @description 37 | * A factory which creates a resource object that lets you interact with 38 | * [RESTful](http://en.wikipedia.org/wiki/Representational_State_Transfer) server-side data sources. 39 | * 40 | * The returned resource object has action methods which provide high-level behaviors without 41 | * the need to interact with the low level {@link ng.$http $http} service. 42 | * 43 | * @param {string} url A parameterized URL template with parameters prefixed by `:` as in 44 | * `/user/:username`. If you are using a URL with a port number (e.g. 45 | * `http://example.com:8080/api`), you'll need to escape the colon character before the port 46 | * number, like this: `$resource('http://example.com\\:8080/api')`. 47 | * 48 | * @param {Object=} paramDefaults Default values for `url` parameters. These can be overridden in 49 | * `actions` methods. If any of the parameter value is a function, it will be executed every time 50 | * when a param value needs to be obtained for a request (unless the param was overriden). 51 | * 52 | * Each key value in the parameter object is first bound to url template if present and then any 53 | * excess keys are appended to the url search query after the `?`. 54 | * 55 | * Given a template `/path/:verb` and parameter `{verb:'greet', salutation:'Hello'}` results in 56 | * URL `/path/greet?salutation=Hello`. 57 | * 58 | * If the parameter value is prefixed with `@` then the value of that parameter is extracted from 59 | * the data object (useful for non-GET operations). 60 | * 61 | * @param {Object.=} actions Hash with declaration of custom action that should extend the 62 | * default set of resource actions. The declaration should be created in the format of {@link 63 | * ng.$http#Parameters $http.config}: 64 | * 65 | * {action1: {method:?, params:?, isArray:?, headers:?, ...}, 66 | * action2: {method:?, params:?, isArray:?, headers:?, ...}, 67 | * ...} 68 | * 69 | * Where: 70 | * 71 | * - **`action`** – {string} – The name of action. This name becomes the name of the method on your 72 | * resource object. 73 | * - **`method`** – {string} – HTTP request method. Valid methods are: `GET`, `POST`, `PUT`, `DELETE`, 74 | * and `JSONP`. 75 | * - **`params`** – {Object=} – Optional set of pre-bound parameters for this action. If any of the 76 | * parameter value is a function, it will be executed every time when a param value needs to be 77 | * obtained for a request (unless the param was overriden). 78 | * - **`isArray`** – {boolean=} – If true then the returned object for this action is an array, see 79 | * `returns` section. 80 | * - **`transformRequest`** – `{function(data, headersGetter)|Array.}` – 81 | * transform function or an array of such functions. The transform function takes the http 82 | * request body and headers and returns its transformed (typically serialized) version. 83 | * - **`transformResponse`** – `{function(data, headersGetter)|Array.}` – 84 | * transform function or an array of such functions. The transform function takes the http 85 | * response body and headers and returns its transformed (typically deserialized) version. 86 | * - **`cache`** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the 87 | * GET request, otherwise if a cache instance built with 88 | * {@link ng.$cacheFactory $cacheFactory}, this cache will be used for 89 | * caching. 90 | * - **`timeout`** – `{number}` – timeout in milliseconds. 91 | * - **`withCredentials`** - `{boolean}` - whether to to set the `withCredentials` flag on the 92 | * XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5 93 | * requests with credentials} for more information. 94 | * - **`responseType`** - `{string}` - see {@link 95 | * https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#responseType requestType}. 96 | * 97 | * @returns {Object} A resource "class" object with methods for the default set of resource actions 98 | * optionally extended with custom `actions`. The default set contains these actions: 99 | * 100 | * { 'get': {method:'GET'}, 101 | * 'save': {method:'POST'}, 102 | * 'query': {method:'GET', isArray:true}, 103 | * 'remove': {method:'DELETE'}, 104 | * 'delete': {method:'DELETE'} }; 105 | * 106 | * Calling these methods invoke an {@link ng.$http} with the specified http method, 107 | * destination and parameters. When the data is returned from the server then the object is an 108 | * instance of the resource class `save`, `remove` and `delete` actions are available on it as 109 | * methods with the `$` prefix. This allows you to easily perform CRUD operations (create, read, 110 | * update, delete) on server-side data like this: 111 | *
112 |         var User = $resource('/user/:userId', {userId:'@id'});
113 |         var user = User.get({userId:123}, function() {
114 |           user.abc = true;
115 |           user.$save();
116 |         });
117 |      
118 | * 119 | * It is important to realize that invoking a $resource object method immediately returns an 120 | * empty reference (object or array depending on `isArray`). Once the data is returned from the 121 | * server the existing reference is populated with the actual data. This is a useful trick since 122 | * usually the resource is assigned to a model which is then rendered by the view. Having an empty 123 | * object results in no rendering, once the data arrives from the server then the object is 124 | * populated with the data and the view automatically re-renders itself showing the new data. This 125 | * means that in most case one never has to write a callback function for the action methods. 126 | * 127 | * The action methods on the class object or instance object can be invoked with the following 128 | * parameters: 129 | * 130 | * - HTTP GET "class" actions: `Resource.action([parameters], [success], [error])` 131 | * - non-GET "class" actions: `Resource.action([parameters], postData, [success], [error])` 132 | * - non-GET instance actions: `instance.$action([parameters], [success], [error])` 133 | * 134 | * 135 | * @example 136 | * 137 | * # Credit card resource 138 | * 139 | *
140 |      // Define CreditCard class
141 |      var CreditCard = $resource('/user/:userId/card/:cardId',
142 |       {userId:123, cardId:'@id'}, {
143 |        charge: {method:'POST', params:{charge:true}}
144 |       });
145 | 
146 |      // We can retrieve a collection from the server
147 |      var cards = CreditCard.query(function() {
148 |        // GET: /user/123/card
149 |        // server returns: [ {id:456, number:'1234', name:'Smith'} ];
150 | 
151 |        var card = cards[0];
152 |        // each item is an instance of CreditCard
153 |        expect(card instanceof CreditCard).toEqual(true);
154 |        card.name = "J. Smith";
155 |        // non GET methods are mapped onto the instances
156 |        card.$save();
157 |        // POST: /user/123/card/456 {id:456, number:'1234', name:'J. Smith'}
158 |        // server returns: {id:456, number:'1234', name: 'J. Smith'};
159 | 
160 |        // our custom method is mapped as well.
161 |        card.$charge({amount:9.99});
162 |        // POST: /user/123/card/456?amount=9.99&charge=true {id:456, number:'1234', name:'J. Smith'}
163 |      });
164 | 
165 |      // we can create an instance as well
166 |      var newCard = new CreditCard({number:'0123'});
167 |      newCard.name = "Mike Smith";
168 |      newCard.$save();
169 |      // POST: /user/123/card {number:'0123', name:'Mike Smith'}
170 |      // server returns: {id:789, number:'01234', name: 'Mike Smith'};
171 |      expect(newCard.id).toEqual(789);
172 |  * 
173 | * 174 | * The object returned from this function execution is a resource "class" which has "static" method 175 | * for each action in the definition. 176 | * 177 | * Calling these methods invoke `$http` on the `url` template with the given `method`, `params` and `headers`. 178 | * When the data is returned from the server then the object is an instance of the resource type and 179 | * all of the non-GET methods are available with `$` prefix. This allows you to easily support CRUD 180 | * operations (create, read, update, delete) on server-side data. 181 | 182 |
183 |      var User = $resource('/user/:userId', {userId:'@id'});
184 |      var user = User.get({userId:123}, function() {
185 |        user.abc = true;
186 |        user.$save();
187 |      });
188 |    
189 | * 190 | * It's worth noting that the success callback for `get`, `query` and other method gets passed 191 | * in the response that came from the server as well as $http header getter function, so one 192 | * could rewrite the above example and get access to http headers as: 193 | * 194 |
195 |      var User = $resource('/user/:userId', {userId:'@id'});
196 |      User.get({userId:123}, function(u, getResponseHeaders){
197 |        u.abc = true;
198 |        u.$save(function(u, putResponseHeaders) {
199 |          //u => saved user object
200 |          //putResponseHeaders => $http header getter
201 |        });
202 |      });
203 |    
204 | 205 | * # Buzz client 206 | 207 | Let's look at what a buzz client created with the `$resource` service looks like: 208 | 209 | 210 | 230 | 231 |
232 | 233 | 234 |
235 |
236 |

237 | 238 | {{item.actor.name}} 239 | Expand replies: {{item.links.replies[0].count}} 240 |

241 | {{item.object.content | html}} 242 |
243 | 244 | {{reply.actor.name}}: {{reply.content | html}} 245 |
246 |
247 |
248 |
249 | 250 | 251 |
252 | */ 253 | angular.module('ngResource', ['ng']). 254 | factory('$resource', ['$http', '$parse', function($http, $parse) { 255 | var DEFAULT_ACTIONS = { 256 | 'get': {method:'GET'}, 257 | 'save': {method:'POST'}, 258 | 'query': {method:'GET', isArray:true}, 259 | 'remove': {method:'DELETE'}, 260 | 'delete': {method:'DELETE'} 261 | }; 262 | var noop = angular.noop, 263 | forEach = angular.forEach, 264 | extend = angular.extend, 265 | copy = angular.copy, 266 | isFunction = angular.isFunction, 267 | getter = function(obj, path) { 268 | return $parse(path)(obj); 269 | }; 270 | 271 | /** 272 | * We need our custom method because encodeURIComponent is too aggressive and doesn't follow 273 | * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path 274 | * segments: 275 | * segment = *pchar 276 | * pchar = unreserved / pct-encoded / sub-delims / ":" / "@" 277 | * pct-encoded = "%" HEXDIG HEXDIG 278 | * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" 279 | * sub-delims = "!" / "$" / "&" / "'" / "(" / ")" 280 | * / "*" / "+" / "," / ";" / "=" 281 | */ 282 | function encodeUriSegment(val) { 283 | return encodeUriQuery(val, true). 284 | replace(/%26/gi, '&'). 285 | replace(/%3D/gi, '='). 286 | replace(/%2B/gi, '+'); 287 | } 288 | 289 | 290 | /** 291 | * This method is intended for encoding *key* or *value* parts of query component. We need a custom 292 | * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be 293 | * encoded per http://tools.ietf.org/html/rfc3986: 294 | * query = *( pchar / "/" / "?" ) 295 | * pchar = unreserved / pct-encoded / sub-delims / ":" / "@" 296 | * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" 297 | * pct-encoded = "%" HEXDIG HEXDIG 298 | * sub-delims = "!" / "$" / "&" / "'" / "(" / ")" 299 | * / "*" / "+" / "," / ";" / "=" 300 | */ 301 | function encodeUriQuery(val, pctEncodeSpaces) { 302 | return encodeURIComponent(val). 303 | replace(/%40/gi, '@'). 304 | replace(/%3A/gi, ':'). 305 | replace(/%24/g, '$'). 306 | replace(/%2C/gi, ','). 307 | replace((pctEncodeSpaces ? null : /%20/g), '+'); 308 | } 309 | 310 | function Route(template, defaults) { 311 | this.template = template = template + '#'; 312 | this.defaults = defaults || {}; 313 | var urlParams = this.urlParams = {}; 314 | forEach(template.split(/\W/), function(param){ 315 | if (param && template.match(new RegExp("[^\\\\]:" + param + "\\W"))) { 316 | urlParams[param] = true; 317 | } 318 | }); 319 | this.template = template.replace(/\\:/g, ':'); 320 | } 321 | 322 | Route.prototype = { 323 | url: function(params) { 324 | var self = this, 325 | url = this.template, 326 | val, 327 | encodedVal; 328 | 329 | params = params || {}; 330 | forEach(this.urlParams, function(_, urlParam){ 331 | val = params.hasOwnProperty(urlParam) ? params[urlParam] : self.defaults[urlParam]; 332 | if (angular.isDefined(val) && val !== null) { 333 | encodedVal = encodeUriSegment(val); 334 | url = url.replace(new RegExp(":" + urlParam + "(\\W)", "g"), encodedVal + "$1"); 335 | } else { 336 | url = url.replace(new RegExp("(\/?):" + urlParam + "(\\W)", "g"), function(match, 337 | leadingSlashes, tail) { 338 | if (tail.charAt(0) == '/') { 339 | return tail; 340 | } else { 341 | return leadingSlashes + tail; 342 | } 343 | }); 344 | } 345 | }); 346 | url = url.replace(/\/?#$/, ''); 347 | var query = []; 348 | forEach(params, function(value, key){ 349 | if (!self.urlParams[key]) { 350 | query.push(encodeUriQuery(key) + '=' + encodeUriQuery(value)); 351 | } 352 | }); 353 | query.sort(); 354 | url = url.replace(/\/*$/, ''); 355 | return url + (query.length ? '?' + query.join('&') : ''); 356 | } 357 | }; 358 | 359 | 360 | function ResourceFactory(url, paramDefaults, actions) { 361 | var route = new Route(url); 362 | 363 | actions = extend({}, DEFAULT_ACTIONS, actions); 364 | 365 | function extractParams(data, actionParams){ 366 | var ids = {}; 367 | actionParams = extend({}, paramDefaults, actionParams); 368 | forEach(actionParams, function(value, key){ 369 | if (isFunction(value)) { value = value(); } 370 | ids[key] = value.charAt && value.charAt(0) == '@' ? getter(data, value.substr(1)) : value; 371 | }); 372 | return ids; 373 | } 374 | 375 | function Resource(value){ 376 | copy(value || {}, this); 377 | } 378 | 379 | forEach(actions, function(action, name) { 380 | action.method = angular.uppercase(action.method); 381 | var hasBody = action.method == 'POST' || action.method == 'PUT' || action.method == 'PATCH'; 382 | Resource[name] = function(a1, a2, a3, a4) { 383 | var params = {}; 384 | var data; 385 | var success = noop; 386 | var error = null; 387 | switch(arguments.length) { 388 | case 4: 389 | error = a4; 390 | success = a3; 391 | //fallthrough 392 | case 3: 393 | case 2: 394 | if (isFunction(a2)) { 395 | if (isFunction(a1)) { 396 | success = a1; 397 | error = a2; 398 | break; 399 | } 400 | 401 | success = a2; 402 | error = a3; 403 | //fallthrough 404 | } else { 405 | params = a1; 406 | data = a2; 407 | success = a3; 408 | break; 409 | } 410 | case 1: 411 | if (isFunction(a1)) success = a1; 412 | else if (hasBody) data = a1; 413 | else params = a1; 414 | break; 415 | case 0: break; 416 | default: 417 | throw "Expected between 0-4 arguments [params, data, success, error], got " + 418 | arguments.length + " arguments."; 419 | } 420 | 421 | var value = this instanceof Resource ? this : (action.isArray ? [] : new Resource(data)); 422 | var httpConfig = {}; 423 | 424 | forEach(action, function(value, key) { 425 | if (key != 'params' && key != 'isArray' ) { 426 | httpConfig[key] = copy(value); 427 | } 428 | }); 429 | httpConfig.data = data; 430 | httpConfig.url = route.url(extend({}, extractParams(data, action.params || {}), params)) 431 | 432 | $http(httpConfig).then(function(response) { 433 | var data = response.data; 434 | 435 | if (data) { 436 | if (action.isArray) { 437 | value.length = 0; 438 | forEach(data, function(item) { 439 | value.push(new Resource(item)); 440 | }); 441 | } else { 442 | copy(data, value); 443 | } 444 | } 445 | (success||noop)(value, response.headers); 446 | }, error); 447 | 448 | return value; 449 | }; 450 | 451 | 452 | Resource.prototype['$' + name] = function(a1, a2, a3) { 453 | var params = extractParams(this), 454 | success = noop, 455 | error; 456 | 457 | switch(arguments.length) { 458 | case 3: params = a1; success = a2; error = a3; break; 459 | case 2: 460 | case 1: 461 | if (isFunction(a1)) { 462 | success = a1; 463 | error = a2; 464 | } else { 465 | params = a1; 466 | success = a2 || noop; 467 | } 468 | case 0: break; 469 | default: 470 | throw "Expected between 1-3 arguments [params, success, error], got " + 471 | arguments.length + " arguments."; 472 | } 473 | var data = hasBody ? this : undefined; 474 | Resource[name].call(this, params, data, success, error); 475 | }; 476 | }); 477 | 478 | Resource.bind = function(additionalParamDefaults){ 479 | return ResourceFactory(url, extend({}, paramDefaults, additionalParamDefaults), actions); 480 | }; 481 | 482 | return Resource; 483 | } 484 | 485 | return ResourceFactory; 486 | }]); 487 | 488 | })(window, window.angular); 489 | -------------------------------------------------------------------------------- /javaee6angularjsmysql/src/main/webapp/js/services.js: -------------------------------------------------------------------------------- 1 | /* 2 | * JBoss, Home of Professional Open Source 3 | * Copyright 2013, Red Hat, Inc. and/or its affiliates, and individual 4 | * contributors by the @authors tag. See the copyright.txt in the 5 | * distribution for a full listing of individual contributors. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | // Define the REST resource service, allowing us to interact with it as a high level service 18 | angular.module('membersService', ['ngResource']). 19 | factory('Members', function($resource){ 20 | return $resource('rest/members:memberId', {}); 21 | }); -------------------------------------------------------------------------------- /javaee6angularjsmysql/src/main/webapp/partials/home.html: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 |
20 |

Welcome to WildFly!

21 | 22 |
23 |

You have successfully deployed a Java EE 7 Enterprise 24 | Application.

25 |

Your application can run on:

26 | 27 |
28 | 29 | 30 |
31 |

Member Registration

32 |
33 | Register a member: 34 | 35 |
36 | 37 | 38 | {{errors.name}} 39 |
40 |
41 | 42 | 43 | {{errors.email}} 44 |
45 |
46 | 47 | 48 | {{errors.phoneNumber}} 49 |
50 | 51 | 52 |
    53 |
  • {{message}}
  • 54 |
55 | 56 | 57 |
    58 |
  • {{message}}
  • 59 |
60 | 61 | 62 |
63 | 64 | 66 |
67 |
68 |
69 | 70 | 71 |

Members

72 | 73 | No registered members. 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 92 |
IdNameEmailPhone #REST URL
{{member.id}}{{member.name}}{{member.email}}{{member.phoneNumber}}/rest/members/{{member.id}} 91 |
93 |
94 | REST URL for all members: /rest/members 95 |
96 |
97 | 98 | 100 |
101 |
102 | -------------------------------------------------------------------------------- /javaee6angularjsmysql/src/test/java/org/jboss/as/quickstarts/kitchensink/test/MemberRegistrationTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * JBoss, Home of Professional Open Source 3 | * Copyright 2013, Red Hat, Inc. and/or its affiliates, and individual 4 | * contributors by the @authors tag. See the copyright.txt in the 5 | * distribution for a full listing of individual contributors. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.jboss.as.quickstarts.kitchensink.test; 18 | 19 | import static org.junit.Assert.assertNotNull; 20 | 21 | import java.util.logging.Logger; 22 | 23 | import javax.inject.Inject; 24 | 25 | import org.jboss.arquillian.container.test.api.Deployment; 26 | import org.jboss.arquillian.junit.Arquillian; 27 | import org.jboss.as.quickstarts.kitchensink.model.Member; 28 | import org.jboss.as.quickstarts.kitchensink.service.MemberRegistration; 29 | import org.jboss.as.quickstarts.kitchensink.util.Resources; 30 | import org.jboss.shrinkwrap.api.Archive; 31 | import org.jboss.shrinkwrap.api.ShrinkWrap; 32 | import org.jboss.shrinkwrap.api.asset.EmptyAsset; 33 | import org.jboss.shrinkwrap.api.spec.WebArchive; 34 | import org.junit.Test; 35 | import org.junit.runner.RunWith; 36 | 37 | @RunWith(Arquillian.class) 38 | public class MemberRegistrationTest { 39 | @Deployment 40 | public static Archive createTestArchive() { 41 | return ShrinkWrap.create(WebArchive.class, "test.war") 42 | .addClasses(Member.class, MemberRegistration.class, Resources.class) 43 | .addAsResource("META-INF/test-persistence.xml", "META-INF/persistence.xml") 44 | .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml") 45 | // Deploy our test datasource 46 | .addAsWebInfResource("test-ds.xml"); 47 | } 48 | 49 | @Inject 50 | MemberRegistration memberRegistration; 51 | 52 | @Inject 53 | Logger log; 54 | 55 | @Test 56 | public void testRegister() throws Exception { 57 | Member newMember = new Member(); 58 | newMember.setName("Jane Doe"); 59 | newMember.setEmail("jane@mailinator.com"); 60 | newMember.setPhoneNumber("2125551234"); 61 | memberRegistration.register(newMember); 62 | assertNotNull(newMember.getId()); 63 | log.info(newMember.getName() + " was persisted with id " + newMember.getId()); 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /javaee6angularjsmysql/src/test/resources/META-INF/test-persistence.xml: -------------------------------------------------------------------------------- 1 | 2 | 18 | 23 | 24 | 27 | 29 | java:jboss/datasources/KitchensinkQuickstartTestDS 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /javaee6angularjsmysql/src/test/resources/arquillian.xml: -------------------------------------------------------------------------------- 1 | 2 | 18 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /javaee6angularjsmysql/src/test/resources/test-ds.xml: -------------------------------------------------------------------------------- 1 | 2 | 18 | 21 | 24 | 26 | 29 | jdbc:h2:mem:kitchensink-quickstart-test;DB_CLOSE_DELAY=-1 30 | h2 31 | 32 | sa 33 | sa 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /mysql-connector-java-5.1.31-bin.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/burrsutter/docker_mysql_tutorial/39fefcf7fd0ca8184a8c0aa5079850247a5b91d7/mysql-connector-java-5.1.31-bin.jar -------------------------------------------------------------------------------- /mysql-sample-ds.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | jdbc:mysql://mysqldb:3306/sample 6 | mysql-connector-java-5.1.31-bin.jar_com.mysql.jdbc.Driver_5_1 7 | 8 | mysql 9 | mysql 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | Docker with Docker Toolbox for Windows Java EE + MySQL 2 | ======================================================= 3 | 4 | This tutorial walks you through using a Java EE application server and MySQL, both running in Docker Linux containers on a Windows host via Docker Toolbox. 5 | 6 | * * * 7 | ##### Prerequisites & Assumptions: 8 | * You completed the first [Docker Tutorial](https://github.com/burrsutter/docker_tutorial) that walks through the basics of standing up a Java EE application server in a Docker container 9 | * You have [MySQL Workbench](http://dev.mysql.com/downloads/workbench/) installed on your Windows host 10 | * You have [Maven](http://maven.apache.org/) and a [JDK](http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html) installed on your Windows host machine 11 | * Note: We give you an out if Java & Maven are not working well for you 12 | * * * 13 | 14 | 15 | 1. Docker Quickstart terminal 16 | 17 | ![Alt text](/screenshots/docker_quickstart_terminal.png?raw=true "Start Menu") 18 | 19 | ![Alt text](/screenshots/start_sh_running.png?raw=true "Boot2Docker Command Prompt") 20 | 21 | 2. `docker network create mysqlapp_net` 22 | 23 | > This command will create a network that will be used by mysql and wildfly containers 24 | 25 | ![Alt text](/screenshots/docker_network_create.png?raw=true "docker network create mysqlapp_net") 26 | 27 | 28 | 3. Now we run MySQL using the recently created network, inside of a Docker container 29 | 30 | ```` 31 | docker run --name mysqldb --net mysqlapp_net -p 3306:3306 -e MYSQL_USER=mysql -e MYSQL_PASSWORD=mysql -e MYSQL_DATABASE=sample -e MYSQL_ROOT_PASSWORD=supersecret -d mysql 32 | ```` 33 | 34 | This will take some time if this is the first run of the "mysql" image 35 | 36 | ![Alt text](/screenshots/docker_run_mysql.png?raw=true "docker run mysql") 37 | 38 | > Note: I am using -p 3306:3306 to connect from a Windows (host) MySQL Workbench and from a Windows/host based Wildfly instance. 3306 is the normal port for MySQL. You will see this port listed in the `docker ps` results as well. 39 | 40 | * * * 41 | ##### Tip: Copy & Paste in the default Windows Command Prompt is possible. 42 | Click on the top-left icon for the pull-down menu. Select Mark, highlight the text you wish to copy, then hit Enter. Then for Paste, simply use the menu option. 43 | ![Alt text](/screenshots/mark_paste.png?raw=true "DOS/Command Prompt Copy & Paste") 44 | 45 | * * * 46 | 47 | 4. Back in Windows run MySQL Workbench. You will need the IP address you saw when running `Docker Quickstart terminal` or `docker-machine ip default`. 48 | 49 | > Select New Connection 50 | 51 | ![Alt text](/screenshots/mysql_workbench_new_connection.png?raw=true "new connection") 52 | 53 | > Give the connection a name like "docker_mysql_104" as the IP address will change from time to time. Enter the correct IP address. You will notice that some of the screenshots use different IPs. 54 | 55 | ![Alt text](/screenshots/connect_to_database.png?raw=true "New Connection Dialog") 56 | 57 | > The root password was defined via the `docker run` command, look for MYSQL_ROOT_PASSWORD 58 | 59 | ![Alt text](/screenshots/mysql_root_password.png?raw=true "Root Password Prompt") 60 | 61 | > Double-click on the connection to open up the SQL Editor 62 | 63 | ![Alt text](/screenshots/mysql_sql_editor.png?raw=true "SQL Editor") 64 | 65 | 66 | > By default you get a "sample" database with no tables. A table will be created when we launch the Java EE application. 67 | 68 | > Now that your MySQL instance is running happily inside of a Docker container (inside the docker host called default) 69 | let's configure the Java EE app to use your MySQL 70 | 71 | 5. In the first tutorial, we gave you the .war pre-built, in this case, we want you to download the project sources to your local machine and perform you own Maven build to generate the .war. 72 | 73 | > Download and unzip 74 | 75 | ![Alt text](/screenshots/download_unzip.png?raw=true "Download and Unzip") 76 | 77 | 78 | 6. `mkdir /c/Users//docker_projects/mysqlapp` 79 | 80 | > Remember docker hosts have VirtualBox Guest Additions preconfigured to map the Linux `/c/Users/` to `c:\Users` 81 | > You can also just use the Windows Explorer to create this directory 82 | 83 | 7. Using File Explorer, copy the directory `javaee6angularjsmysql` to mysqlapp 84 | 85 | 8. From a Windows (DOS) Command Prompt, 86 | ```` 87 | cd \Users\\docker_projects\mysqlapp\javaee6angularjsmysql 88 | mvn clean compile package 89 | ```` 90 | 91 | 92 | > This does require that you have a JDK and Maven installed plus your PATH set properly. Setting up your PATH can be as simple as executing the following commands: 93 | 94 | ```` 95 | set JAVA_HOME=C:\tools\java\jdk1.7.0_04_32bit 96 | set M2_HOME=C:\tools\apache-maven-3.2.3 97 | set PATH=%JAVA_HOME%\bin;%M2_HOME%\bin;C:\tools;%PATH% 98 | ```` 99 | 100 | > Look for BUILD SUCCESS 101 | 102 | ![Alt text](/screenshots/build_success.png?raw=true "mvn clean compile package") 103 | 104 | > Do not have Maven nor the Java Development Kit running well on this workstation? No problem, just download the pre-built .war from 105 | 106 | 9. Open the javaee6angularjsmysql project in your favorite editor (I have been trying out Atom.io) and review the persistence.xml file (located in src/main/resources/META-INF folder). Take note of the following line: 107 | 108 | ```` 109 | java:jboss/datasources/MySQLSampleDS 110 | ```` 111 | 112 | ![Alt text](/screenshots/persistence_xml.png?raw=true "persistence.xml") 113 | 114 | > This Java EE6 application needs a datasource which must be configured inside of the application server. The datasource needs a JDBC Driver to have been pre-loaded as well. 115 | 116 | 10. Copy the file MySQL JBDC driver - mysql-connector-java-5.1.31-bin.jar - to your mysqlapp directory. When the docker image is created, this file will be dropped into Wildfly's standalone\deployments directory. Wildfly hot deploys JDBC drivers it finds in its deployments directory. 117 | 118 | 119 | 11. Copy the file mysql-sample-ds.xml to your mysqlapp directory and open it in your editor. 120 | 121 | ![Alt text](/screenshots/mysql_sample_ds_xml.png?raw=true "mysql-sample-ds.xml") 122 | 123 | > Now, this is where a lot of the magic happens. This file when found in Wildfly's standalone\deployments directory will configure a Datasource inside of Wildfly. You should notice that the JNDI name of "MySQLSampleDS" matches what you have in the persistence.xml. The hosname, user and password for MySQL were setup back with the `docker run` command in step 3. 124 | 125 | ```` 126 | jdbc:mysql://mysqldb:3306/sample 127 | mysql-connector-java-5.1.31-bin.jar_com.mysql.jdbc.Driver_5_1 128 | 129 | mysql 130 | mysql 131 | 132 | ```` 133 | 134 | 12. Copy the standalone.xml and Dockerfile to your mysqlapp directory and open it up in your editor. 135 | 136 | ```` 137 | FROM centos/wildfly 138 | 139 | COPY standalone.xml /opt/wildfly/standalone/configuration/ 140 | COPY mysql-connector-java-5.1.31-bin.jar /opt/wildfly/standalone/deployments/ 141 | COPY mysql-sample-ds.xml /opt/wildfly/standalone/deployments/ 142 | 143 | COPY javaee6angularjsmysql/target/javaee6angularjsmysql.war /opt/wildfly/standalone/deployments/ 144 | 145 | ```` 146 | ![Alt text](/screenshots/mysqlapp_with_Dockerfile.png?raw=true "mysqlapp directory with Dockerfile") 147 | 148 | > mysql-connector-java-5.1.31-bin.jar is in the same directory as the Dockerfile 149 | 150 | > mysql-sample-ds.xml and standalone.xml are also in the same directory 151 | 152 | > javaee6angularjsmysql.war was created via `mvn clean compile package` 153 | 154 | ![Alt text](/screenshots/target_directory.png?raw=true "target directory") 155 | 156 | 157 | > Note: This is NOT how you would normally configure a JDBC driver and Datasource for a production ready Docker image. You are likely separate these into three different layers/images - allowing you to update the JDBC driver in a single layer/location/image. 158 | 159 | 160 | 13. Build the new Docker image in the `Docker Quickstart terminal` 161 | 162 | ```` 163 | cd /c/Users//docker_projects/mysqlapp 164 | 165 | docker build --tag=mysqlapp . 166 | ```` 167 | 168 | ![Alt text](/screenshots/after_docker_build.png?raw=true "docker build results") 169 | 170 | 171 | 14. `docker run -it --net mysqlapp_net -p 8080:8080 mysqlapp` 172 | 173 | > The MySQL container was started with "--name mysqldb" back in Step 3 and the "mysqldb" is referenced in the -ds.xml as a hostname. You can verify the "mysqldb" name of the MySQL container via the `docker ps` command. 174 | > 175 | > You can find out more information about Docker networks in the official documentation at 176 | 177 | 178 | 179 | 180 | 15. Use your browser to interact with the application, register a new Member. You will need the IP address you saw when running `Docker Quickstart terminal` or `docker-machine ip default`. 181 | 182 | ![Alt text](/screenshots/browser.png?raw=true "Application in Browser") 183 | 184 | > Then check out your MySQL database in the SQL Editor. Note that the table name is case sensitve. 185 | 186 | ![Alt text](/screenshots/sql_editor.png?raw=true "SQL Editor") 187 | 188 | 189 | #### Extra Credit 190 | 191 | To enable the Wildfly Admin Console, add the following to your Dockerfile 192 | 193 | ```` 194 | RUN /opt/wildfly/bin/add-user.sh admin Admin!1234 --silent 195 | ```` 196 | 197 | and build the image again: 198 | 199 | ```` 200 | docker build --tag=mysqlapp . 201 | ```` 202 | 203 | This is an example where the Docker build will execute a screen to provide custom configuration of the resulting Docker image. In this specific case "admin" is the user id and "Admin!1234" is the password. 204 | You could have used this same technique to execute commands that would have configured the JDBC driver and Datasource inside of the container. We choose the -ds.xml and hot deployment of the JDBC driver .jar techniques above due to 'ease of learning'. 205 | 206 | The JBoss Wildfly Admin Console uses a different port, so also change your "docker run" statement as follows: 207 | 208 | ```` 209 | docker run -it -p 8080:8080 -p 9990:9990 --net mysqlapp_net mysqlapp 210 | ```` 211 | 212 | ![Alt text](/screenshots/wildfly_admin_console.png?raw=true "JBoss Wildfly Admin Console") 213 | 214 | The End 215 | -------------------------------------------------------------------------------- /screenshots/after_docker_build.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/burrsutter/docker_mysql_tutorial/39fefcf7fd0ca8184a8c0aa5079850247a5b91d7/screenshots/after_docker_build.png -------------------------------------------------------------------------------- /screenshots/browser.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/burrsutter/docker_mysql_tutorial/39fefcf7fd0ca8184a8c0aa5079850247a5b91d7/screenshots/browser.png -------------------------------------------------------------------------------- /screenshots/build_success.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/burrsutter/docker_mysql_tutorial/39fefcf7fd0ca8184a8c0aa5079850247a5b91d7/screenshots/build_success.png -------------------------------------------------------------------------------- /screenshots/connect_to_database.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/burrsutter/docker_mysql_tutorial/39fefcf7fd0ca8184a8c0aa5079850247a5b91d7/screenshots/connect_to_database.png -------------------------------------------------------------------------------- /screenshots/docker_network_create.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/burrsutter/docker_mysql_tutorial/39fefcf7fd0ca8184a8c0aa5079850247a5b91d7/screenshots/docker_network_create.png -------------------------------------------------------------------------------- /screenshots/docker_quickstart_terminal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/burrsutter/docker_mysql_tutorial/39fefcf7fd0ca8184a8c0aa5079850247a5b91d7/screenshots/docker_quickstart_terminal.png -------------------------------------------------------------------------------- /screenshots/docker_run_mysql.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/burrsutter/docker_mysql_tutorial/39fefcf7fd0ca8184a8c0aa5079850247a5b91d7/screenshots/docker_run_mysql.png -------------------------------------------------------------------------------- /screenshots/download_unzip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/burrsutter/docker_mysql_tutorial/39fefcf7fd0ca8184a8c0aa5079850247a5b91d7/screenshots/download_unzip.png -------------------------------------------------------------------------------- /screenshots/mark_paste.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/burrsutter/docker_mysql_tutorial/39fefcf7fd0ca8184a8c0aa5079850247a5b91d7/screenshots/mark_paste.png -------------------------------------------------------------------------------- /screenshots/mysql_root_password.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/burrsutter/docker_mysql_tutorial/39fefcf7fd0ca8184a8c0aa5079850247a5b91d7/screenshots/mysql_root_password.png -------------------------------------------------------------------------------- /screenshots/mysql_sample_ds_xml.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/burrsutter/docker_mysql_tutorial/39fefcf7fd0ca8184a8c0aa5079850247a5b91d7/screenshots/mysql_sample_ds_xml.png -------------------------------------------------------------------------------- /screenshots/mysql_sql_editor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/burrsutter/docker_mysql_tutorial/39fefcf7fd0ca8184a8c0aa5079850247a5b91d7/screenshots/mysql_sql_editor.png -------------------------------------------------------------------------------- /screenshots/mysql_workbench_new_connection.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/burrsutter/docker_mysql_tutorial/39fefcf7fd0ca8184a8c0aa5079850247a5b91d7/screenshots/mysql_workbench_new_connection.png -------------------------------------------------------------------------------- /screenshots/mysqlapp_with_Dockerfile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/burrsutter/docker_mysql_tutorial/39fefcf7fd0ca8184a8c0aa5079850247a5b91d7/screenshots/mysqlapp_with_Dockerfile.png -------------------------------------------------------------------------------- /screenshots/persistence_xml.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/burrsutter/docker_mysql_tutorial/39fefcf7fd0ca8184a8c0aa5079850247a5b91d7/screenshots/persistence_xml.png -------------------------------------------------------------------------------- /screenshots/sql_editor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/burrsutter/docker_mysql_tutorial/39fefcf7fd0ca8184a8c0aa5079850247a5b91d7/screenshots/sql_editor.png -------------------------------------------------------------------------------- /screenshots/start_sh_running.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/burrsutter/docker_mysql_tutorial/39fefcf7fd0ca8184a8c0aa5079850247a5b91d7/screenshots/start_sh_running.png -------------------------------------------------------------------------------- /screenshots/target_directory.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/burrsutter/docker_mysql_tutorial/39fefcf7fd0ca8184a8c0aa5079850247a5b91d7/screenshots/target_directory.png -------------------------------------------------------------------------------- /screenshots/wildfly_admin_console.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/burrsutter/docker_mysql_tutorial/39fefcf7fd0ca8184a8c0aa5079850247a5b91d7/screenshots/wildfly_admin_console.png -------------------------------------------------------------------------------- /standalone.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE 139 | h2 140 | 141 | sa 142 | sa 143 | 144 | 145 | 146 | 147 | org.h2.jdbcx.JdbcDataSource 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | true 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | ${jboss.bind.address:127.0.0.1} 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | --------------------------------------------------------------------------------