Permalink
Browse files

merged the changes from the working branch.

  • Loading branch information...
1 parent 008d507 commit 5670731395021cd955b870a19f2d118703e4d754 @joshlong committed Dec 16, 2012
Showing with 24,195 additions and 15,986 deletions.
  1. BIN assets/.DS_Store
  2. +999 −0 assets/dropzone.ai
  3. +22 −1 code/README
  4. +148 −0 code/backoffice/pom.xml
  5. +162 −0 ...ffice/src/main/java/org/springsource/examples/spring31/backoffice/PhotoTransformationService.java
  6. +21 −0 ...e/src/main/java/org/springsource/examples/spring31/backoffice/config/BackOfficeConfiguration.java
  7. +44 −0 ...backoffice/src/main/java/org/springsource/examples/spring31/backoffice/utils/ImageResizeUtil.java
  8. +113 −0 code/backoffice/src/main/java/org/springsource/examples/spring31/backoffice/utils/RatioUtil.java
  9. +46 −0 code/backoffice/src/main/resources/backoffice/process-profile-photos-service.xml
  10. +14 −0 code/backoffice/src/main/resources/config.properties
  11. +5 −0 code/backoffice/src/main/resources/log4j.properties
  12. 0 code/{ → backoffice}/src/main/resources/messages.properties
  13. BIN {tutorial → code/backoffice/src/test}/.DS_Store
  14. +189 −0 ...t/java/org/springsource/examples/spring31/backoffice/TestPhotoTransformationClientAndService.java
  15. BIN code/backoffice/src/test/resources/.DS_Store
  16. BIN code/backoffice/src/test/resources/ss.png
  17. +360 −122 code/pom.xml
  18. +143 −0 code/services/pom.xml
  19. +20 −16 code/{ → services}/src/main/java/org/springsource/examples/spring31/services/Customer.java
  20. +7 −4 code/{ → services}/src/main/java/org/springsource/examples/spring31/services/CustomerService.java
  21. +27 −0 ...services/src/main/java/org/springsource/examples/spring31/services/PhotoTransformationClient.java
  22. +27 −12 code/{ → services}/src/main/java/org/springsource/examples/spring31/services/User.java
  23. +357 −0 code/services/src/main/java/org/springsource/examples/spring31/services/UserService.java
  24. +69 −16 .../java/org/springsource/examples/spring31/services/config/CloudFoundryDataSourceConfiguration.java
  25. +10 −3 ...es}/src/main/java/org/springsource/examples/spring31/services/config/DataSourceConfiguration.java
  26. +133 −0 ...rc/main/java/org/springsource/examples/spring31/services/config/LocalDataSourceConfiguration.java
  27. +113 −0 ...vices/src/main/java/org/springsource/examples/spring31/services/config/ServicesConfiguration.java
  28. +82 −0 code/services/src/main/java/org/springsource/examples/spring31/services/util/SeedDataGenerator.java
  29. +14 −0 code/services/src/main/resources/config.properties
  30. 0 code/services/src/main/resources/import_h2.sql
  31. +16 −0 code/services/src/main/resources/import_psql.sql
  32. +5 −0 code/services/src/main/resources/log4j.properties
  33. 0 code/services/src/main/resources/messages.properties
  34. +28 −0 code/services/src/main/resources/services/process-profile-photo-client.xml
  35. BIN code/services/src/main/resources/testImage.png
  36. +0 −83 code/src/main/java/org/springsource/examples/spring31/services/UserService.java
  37. +0 −87 ...rc/main/java/org/springsource/examples/spring31/services/config/LocalDataSourceConfiguration.java
  38. +0 −47 code/src/main/java/org/springsource/examples/spring31/services/config/ServicesConfiguration.java
  39. +0 −38 code/src/main/java/org/springsource/examples/spring31/services/security/CrmClientDetails.java
  40. +0 −60 code/src/main/java/org/springsource/examples/spring31/services/security/CrmClientDetailsService.java
  41. +0 −87 code/src/main/java/org/springsource/examples/spring31/services/security/CrmUserDetails.java
  42. +0 −33 code/src/main/java/org/springsource/examples/spring31/services/security/CrmUserDetailsService.java
  43. +0 −50 code/src/main/java/org/springsource/examples/spring31/web/WebMvcConfiguration.java
  44. +0 −5 code/src/main/resources/config.properties
  45. +0 −16 code/src/main/resources/import_h2.sql
  46. +0 −16 code/src/main/resources/import_psql.sql
  47. +0 −9 code/src/main/resources/log4j.properties
  48. +0 −39 code/src/main/webapp/WEB-INF/web.xml
  49. +0 −13,556 code/src/main/webapp/web/assets/js/angular-1.0.0rc6.js
  50. +0 −4 code/src/main/webapp/web/assets/js/jquery-1.7.2.min.js
  51. +0 −10 code/src/main/webapp/web/views/customers.css
  52. +0 −154 code/src/main/webapp/web/views/customers.js
  53. +0 −97 code/src/test/java/org/springsource/examples/spring31/services/CustomerServiceTest.java
  54. +208 −0 code/web/pom.xml
  55. 0 code/{ → web}/src/main/java/org/springsource/examples/spring31/util/SeedDataGenerator.java
  56. +8 −8 code/{ → web}/src/main/java/org/springsource/examples/spring31/web/CustomerApiController.java
  57. +2 −3 ...troller.java → web/src/main/java/org/springsource/examples/spring31/web/StatusApiController.java}
  58. +73 −0 code/web/src/main/java/org/springsource/examples/spring31/web/UserApiController.java
  59. +23 −0 code/web/src/main/java/org/springsource/examples/spring31/web/ViewController.java
  60. +100 −0 code/web/src/main/java/org/springsource/examples/spring31/web/config/SecurityConfiguration.java
  61. +14 −27 ...main/java/org/springsource/examples/spring31/web/config}/SpringApplicationContextInitializer.java
  62. +155 −0 code/web/src/main/java/org/springsource/examples/spring31/web/config/WebMvcConfiguration.java
  63. +77 −0 ...rg/springsource/examples/spring31/web/interceptors/CrmHttpServletRequestEnrichingInterceptor.java
  64. +50 −0 .../web/src/main/java/org/springsource/examples/spring31/web/oauth/AccessConfirmationController.java
  65. +118 −0 code/web/src/main/java/org/springsource/examples/spring31/web/oauth/AdminController.java
  66. +58 −0 ...n/java/org/springsource/examples/spring31/web/security/RoleAwareAuthenticationSuccessHandler.java
  67. +66 −0 ...g/springsource/examples/spring31/web/security/RoleAwareOAuthTokenServicesUserApprovalHandler.java
  68. +22 −0 code/web/src/main/java/org/springsource/examples/spring31/web/util/HibernateAwareObjectMapper.java
  69. +14 −0 code/web/src/main/resources/config.properties
  70. 0 code/web/src/main/resources/import_h2.sql
  71. +16 −0 code/web/src/main/resources/import_psql.sql
  72. +5 −0 code/web/src/main/resources/log4j.properties
  73. 0 code/web/src/main/resources/messages.properties
  74. +99 −0 code/web/src/main/resources/security/security.xml
  75. BIN code/web/src/main/resources/testImage.png
  76. +3 −0 code/web/src/main/webapp/WEB-INF/layouts/components/box.jsp
  77. +91 −0 code/web/src/main/webapp/WEB-INF/layouts/template.jsp
  78. +9 −0 code/web/src/main/webapp/WEB-INF/layouts/tiles.xml
  79. +49 −0 code/web/src/main/webapp/WEB-INF/views/accessConfirmation/accessConfirmation.jsp
  80. +23 −0 code/web/src/main/webapp/WEB-INF/views/accessConfirmation/oauthError.jsp
  81. +12 −0 code/web/src/main/webapp/WEB-INF/views/accessConfirmation/tiles.xml
  82. +262 −0 code/web/src/main/webapp/WEB-INF/views/administration/administration.jsp
  83. +12 −0 code/web/src/main/webapp/WEB-INF/views/administration/tiles.xml
  84. +21 −38 code/{src/main/webapp/WEB-INF/views → web/src/main/webapp/WEB-INF/views/customers}/customers.jsp
  85. +12 −0 code/web/src/main/webapp/WEB-INF/views/customers/tiles.xml
  86. +14 −0 code/web/src/main/webapp/WEB-INF/views/home/home.jsp
  87. +10 −0 code/web/src/main/webapp/WEB-INF/views/home/tiles.xml
  88. +18 −0 code/web/src/main/webapp/WEB-INF/views/oops/oops.jsp
  89. +15 −0 code/web/src/main/webapp/WEB-INF/views/oops/tiles.xml
  90. +63 −0 code/web/src/main/webapp/WEB-INF/views/profile/profile.jsp
  91. +10 −0 code/web/src/main/webapp/WEB-INF/views/profile/tiles.xml
  92. +57 −0 code/web/src/main/webapp/WEB-INF/views/signin/signin.jsp
  93. +10 −0 code/web/src/main/webapp/WEB-INF/views/signin/tiles.xml
  94. +55 −0 code/web/src/main/webapp/WEB-INF/web.xml
  95. 0 code/{ → web}/src/main/webapp/web/assets/bootstrap/bootstrap.css
  96. BIN code/{ → web}/src/main/webapp/web/assets/img/glyphicons-halflings.png
  97. +166 −0 code/web/src/main/webapp/web/assets/js/angular-bootstrap.js
  98. +432 −0 code/web/src/main/webapp/web/assets/js/angular-resource.js
  99. +14,331 −0 code/web/src/main/webapp/web/assets/js/angular.js
  100. +327 −0 code/web/src/main/webapp/web/assets/js/jquery-filedrop.js
  101. +407 −0 code/web/src/main/webapp/web/assets/js/jquery-ui.js
  102. +2,579 −0 code/web/src/main/webapp/web/assets/js/jquery.js
  103. +611 −0 code/web/src/main/webapp/web/assets/js/jso.js
  104. +211 −0 code/web/src/main/webapp/web/views/controllers.css
  105. +103 −0 code/web/src/main/webapp/web/views/controllers.js
  106. BIN tutorial/tutorial.docx
  107. +0 −1,248 tutorial/tutorial.htm
  108. +0 −8 tutorial/tutorial_files/filelist.xml
  109. +0 −89 tutorial/tutorial_files/header.htm
  110. BIN tutorial/tutorial_files/image001.jpg
  111. BIN tutorial/tutorial_files/image002.png
  112. BIN tutorial/tutorial_files/themedata.xml
View
Binary file not shown.
View

Large diffs are not rendered by default.

Oops, something went wrong.
View
@@ -1,4 +1,25 @@
-This is a simple application that demonstrates how to use Spring 3.1 on Cloud Foundry.
+=======================================================================================================================
+TODO
+ - clean up the UI (maybe a watermark of the S2 logo in the background of the page that doesnt move even when you scroll?
+ - setup a Spring Integration flow that takes the uploaded image, resizes it, forwards the image to an http WS
+ that in turn emails the image as an attachment for someone to review in an email client and then type 'approve'
+ or 'disapprove' to make sure the images aren't lude. if they type 'approve' the image is 'enabled'
+
+ so there are two flows:
+ a) resize image and respond w/ resized image.
+ b) send image for moderation in a way that demonstrates hybrid cloud integration: CF propagates oauth creds
+ to a WS from the original AMQP context, and then uses that to securely send an email to the administrator asking
+ for approval. if the reply comes back 'yes' then the image is enabled. otherwise, a timeout happens and some sort
+ of escalation, maybe? iono. Either way, this would be a nice example of using Si to work with inbound
+ http (basic auth), amqp, smtp, spring security, etc.
+
+ - make it possible to signup/register with Spring Social
+ - use MongoDB and Redis somehow (gridfs, caching? what about gemfire?)
+
+=======================================================================================================================
+
+
+This is a simple application that demonstrates how to use Spring 3.1 on Cloud Foundry.
This application builds a transactional service that talks to an RDBMS and is fronted by
an Spring MVC controller which handles RESTful API calls.
View
@@ -0,0 +1,148 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.springsource.examples.crm</groupId>
+ <artifactId>core</artifactId>
+ <version>1.0.0</version>
+ </parent>
+ <artifactId>backoffice</artifactId>
+
+
+ <dependencies>
+ <dependency>
+ <groupId>org.springsource.examples.crm</groupId>
+ <artifactId>services</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-tx</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-context-support</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>jcl-over-slf4j</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-log4j12</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>postgresql</groupId>
+ <artifactId>postgresql</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>commons-dbcp</groupId>
+ <artifactId>commons-dbcp</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>javax.inject</groupId>
+ <artifactId>javax.inject</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.data</groupId>
+ <artifactId>spring-data-mongodb</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.data</groupId>
+ <artifactId>spring-data-redis</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.security.oauth</groupId>
+ <artifactId>spring-security-oauth2</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.integration</groupId>
+ <artifactId>spring-integration-amqp</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.integration</groupId>
+ <artifactId>spring-integration-jdbc</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.integration</groupId>
+ <artifactId>spring-integration-twitter</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.integration</groupId>
+ <artifactId>spring-integration-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>commons-lang</groupId>
+ <artifactId>commons-lang</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>commons-logging</groupId>
+ <artifactId>commons-logging</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.hibernate</groupId>
+ <artifactId>hibernate-entitymanager</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.h2database</groupId>
+ <artifactId>h2</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>jstl</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.codehaus.jackson</groupId>
+ <artifactId>jackson-mapper-asl</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.cloudfoundry</groupId>
+ <artifactId>cloudfoundry-runtime</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>javax.validation</groupId>
+ <artifactId>validation-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.hibernate</groupId>
+ <artifactId>hibernate-validator</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-test</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>commons-fileupload</groupId>
+ <artifactId>commons-fileupload</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-orm</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>cglib</groupId>
+ <artifactId>cglib</artifactId>
+ </dependency>
+ </dependencies>
+
+</project>
@@ -0,0 +1,162 @@
+package org.springsource.examples.spring31.backoffice;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.log4j.Logger;
+import org.springframework.integration.Message;
+import org.springframework.integration.annotation.Header;
+import org.springframework.integration.annotation.Payload;
+import org.springframework.integration.annotation.ServiceActivator;
+import org.springframework.stereotype.Component;
+import org.springframework.util.StringUtils;
+import org.springsource.examples.spring31.backoffice.utils.ImageResizeUtil;
+import org.springsource.examples.spring31.services.User;
+import org.springsource.examples.spring31.services.UserService;
+
+import javax.annotation.PostConstruct;
+import javax.inject.Inject;
+import java.io.*;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ *
+ * @author Josh Long
+ */
+@Component("photoConverter")
+public class PhotoTransformationService {
+
+ private Logger logger = Logger.getLogger(getClass());
+ private int defaultImageWidth = 300;
+ private UserService userService;
+
+ // this needs to be on the path
+ private String convertCommandLinePath = "convert";
+
+ private AtomicInteger atomicInteger = new AtomicInteger(0);
+
+ /**
+ * mainly for debugging purposes
+ */
+ public AtomicInteger getAtomicInteger() {
+ return this.atomicInteger;
+ }
+
+ @Inject
+ public void setUserService(UserService userService) {
+ this.userService = userService;
+ }
+
+ @PostConstruct
+ public void setup() {
+ assert this.defaultImageWidth > 0 : "the width must be a positive number. By default this value is initialized to '300'.";
+ assert StringUtils.hasText(this.convertCommandLinePath) : "You must provide a value for the 'convert' command's command line argument.";
+ }
+
+ /**
+ * place to set the path of the 'convert' ImageMagic tool. This is one place where the
+ * configuration of this class can benefit greatly from the use of Spring's profiles, allowing
+ * different environments to be deployed to with ease. The path for the convert library is different on Cloud Foundry,
+ * in our case, than it would be on any of our local development machines.
+ */
+ public void setConvertCommandLinePath(String x) {
+ this.convertCommandLinePath = x;
+ }
+
+ /**
+ * Tell the processor what width the images need to be. These are
+ * going to be profile photo images, so they need to be small.
+ * <p/>
+ * There's not going to be a large profile shot, and we don't
+ * want a large memory footprint serving up lots of images.
+ *
+ * @param dw desired width
+ */
+ public void setDefaultImageWidth(int dw) {
+ this.defaultImageWidth = dw;
+ }
+
+ /**
+ * This method handles all incoming Spring Integration messages and copies the profile photo bytes
+ * to a staging photo which can be then manipulate to perform the conversion and rotation.
+ * <p/>
+ * Finally, we'll connect the work back to the original gridFs file system entry.
+ *
+ * @throws Throwable
+ */
+ @ServiceActivator
+ public long convertAndResizeUserProfilePhoto(@Header("fileExtension") String fileExtension, @Payload Long userId) throws Throwable {
+ InputStream profilePhotoBytesFromGridFs = null, fileInputStream = null;
+ OutputStream outputStream = null;
+ File tmpStagingFile = null, convertedFile = null;
+
+ try {
+ User user = userService.getUserById(userId);
+ assert user != null : "the user reference should still be valid!";
+ tmpStagingFile = File.createTempFile("profilePhoto" + userId, "." + fileExtension);
+ convertedFile = File.createTempFile("profilePhotoConvertedAndResized" + userId, ".jpg");
+ profilePhotoBytesFromGridFs = userService.readUserProfilePhoto(userId);
+ outputStream = new FileOutputStream(tmpStagingFile);
+ copyStreamsAndClose(profilePhotoBytesFromGridFs, outputStream);
+ ImageResizeUtil.resizeToWidth(tmpStagingFile, convertedFile, this.defaultImageWidth, userId);
+ fileInputStream = new FileInputStream(convertedFile);
+ userService.writeUserProfilePhoto(userId, convertedFile.getName(), fileInputStream);
+ logger.debug("wrote converted image for " + userId + ". The temporary staging file is " + convertedFile.getAbsolutePath());
+ } finally {
+ IOUtils.closeQuietly(fileInputStream);
+ IOUtils.closeQuietly(profilePhotoBytesFromGridFs);
+ IOUtils.closeQuietly(outputStream);
+ assert ensureRemovalOfFile(convertedFile) : "the file " + pathForFile(convertedFile) + " must be either be deleted or not exist.";
+ assert ensureRemovalOfFile(tmpStagingFile) : "the file " + pathForFile(convertedFile) + " must be either deleted or not exist.";
+ }
+ atomicInteger.incrementAndGet();
+
+ return userId;
+ }
+
+ private String pathForFile(File fi) {
+ return fi == null ? "null" : fi.getAbsolutePath();
+ }
+
+ /**
+ * copy the streams, and make sure that the streams' descriptors are closed.
+ *
+ * @param inputStream the input stream
+ * @param outputStream the output stream
+ */
+ private void copyStreamsAndClose(InputStream inputStream, OutputStream outputStream) throws Exception {
+ assert null != inputStream : "the input stream can't be null";
+ assert null != outputStream : "the output stream can't be null";
+ try {
+ IOUtils.copy(inputStream, outputStream);
+ } finally {
+ IOUtils.closeQuietly(inputStream);
+ IOUtils.closeQuietly(outputStream);
+ }
+
+ }
+
+ /**
+ * Deletes the file if it exists
+ *
+ * @param file the {@link File file} object to remove
+ * @return whether or not
+ */
+ private boolean ensureRemovalOfFile(File file) {
+ return null != file && (!file.exists() || file.delete());
+ }
+
+ /**
+ * logs information about the incoming message requests.
+ *
+ * @param msg the incoming Spring Integration message.
+ * @throws Throwable
+ */
+ private void dumpInformationAboutTheIncomingMessage(Message<?> msg) throws Throwable {
+ if (null == msg || !logger.isDebugEnabled())
+ return;
+ logger.debug("Payload: " + msg.getPayload() + "");
+ for (String k : msg.getHeaders().keySet()) {
+ logger.debug(k + "=" + msg.getHeaders().get(k));
+ }
+ }
+
+}
@@ -0,0 +1,21 @@
+package org.springsource.examples.spring31.backoffice.config;
+
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Import;
+import org.springframework.context.annotation.ImportResource;
+import org.springsource.examples.spring31.backoffice.PhotoTransformationService;
+import org.springsource.examples.spring31.services.config.ServicesConfiguration;
+
+/**
+ * Handles processing of all incoming processing requests
+ *
+ * @author Josh Long
+ */
+@Configuration
+@Import(ServicesConfiguration.class)
+@ComponentScan(basePackageClasses = PhotoTransformationService.class)
+@ImportResource({"/backoffice/process-profile-photos-service.xml"})
+public class BackOfficeConfiguration {
+}
+
Oops, something went wrong.

0 comments on commit 5670731

Please sign in to comment.