Skip to content

Commit 9a5b374

Browse files
committed
initial commit Google App engine sample
1 parent 450dbed commit 9a5b374

32 files changed

+4514
-1
lines changed

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,6 @@ test-output/
1212
.classpath
1313
.project
1414

15-
*.iml
15+
*.iml
16+
17+
appengine-web.xml
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">
3+
4+
</persistence>

samples/photo_album_gae/README.md

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
Cloudinary Java/Spring MVC Sample Project on Google AppEngine
2+
=============================================================
3+
4+
A simple web application that allows you to uploads photos, maintain a database with references to them, list them with their metadata, and display them using various cloud-based transformations.
5+
6+
## Installation
7+
8+
Run the following commands from your shell.
9+
10+
Clone the Cloudinary Java project:
11+
12+
git clone git://github.com/cloudinary/cloudinary_java.git
13+
14+
This sample relies on a version of the Cloudinary client not yet published so we need to install it locally:
15+
16+
cd cloudinary_java
17+
mvn install
18+
19+
Go to the sample project folder:
20+
21+
cd samples/photo_album_gae
22+
23+
## Configuration
24+
25+
Next you need to pass your Cloudinary account's Cloud Name, API Key, and API Secret. This sample application assumes these values exists in the form
26+
of a `CLOUDINARY_URL`. The `CLOUDINARY_URL` value is available in the [dashboard of your Cloudinary account](https://cloudinary.com/console).
27+
If you don't have a Cloudinary account yet, [click here](https://cloudinary.com/users/register/free) to create one for free.
28+
29+
cp src/main/webapp/WEB-INF/appengine-web.xml.sample src/main/webapp/WEB-INF/appengine-web.xml
30+
31+
Edit the new `appengine-web.xml` file and set `CLOUDINARY_URL` to the value matching your account.
32+
*Note*: you can also change the application ID to match a remote project ID you might have started.
33+
34+
## Running
35+
36+
Running the application locally first clean and compile to make sure everything is working as it should:
37+
38+
mvn clean compile
39+
40+
Then start the application:
41+
42+
mvn appengine:devserver_start
43+
44+
and point your browser to [http://localhost:8080/](http://localhost:8080/).
45+
46+
This sample configures the Cloudinary client with `GAEConnectionManager` from [here](http://esxx.blogspot.co.il/2009/06/using-apaches-httpclient-on-google-app.html).
47+
You can use any other connection manager or leave the default if you have the sockets enabled for your application. In the development environment it should work with either.
48+
Also, the way the `GAEConnectionManager` is instantiated and managed in this sample is not pretty. You should change it when building a real application.

samples/photo_album_gae/nbactions.xml

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<actions>
3+
<action>
4+
<actionName>CUSTOM-appengine:devserver</actionName>
5+
<displayName>appengine:devserver</displayName>
6+
<goals>
7+
<goal>appengine:devserver</goal>
8+
</goals>
9+
</action>
10+
<action>
11+
<actionName>CUSTOM-appengine:update</actionName>
12+
<displayName>appengine:update</displayName>
13+
<goals>
14+
<goal>appengine:update</goal>
15+
</goals>
16+
</action>
17+
<action>
18+
<actionName>CUSTOM-appengine:rollback</actionName>
19+
<displayName>appengine:rollback</displayName>
20+
<goals>
21+
<goal>appengine:rollback</goal>
22+
</goals>
23+
</action>
24+
<action>
25+
<actionName>CUSTOM-appengine:update_cron</actionName>
26+
<displayName>appengine:update_cron</displayName>
27+
<goals>
28+
<goal>appengine:update_cron</goal>
29+
</goals>
30+
</action>
31+
<action>
32+
<actionName>CUSTOM-appengine:update_dos</actionName>
33+
<displayName>appengine:update_dos</displayName>
34+
<goals>
35+
<goal>appengine:update_dos</goal>
36+
</goals>
37+
</action>
38+
<action>
39+
<actionName>CUSTOM-appengine:update_indexes</actionName>
40+
<displayName>appengine:update_indexes</displayName>
41+
<goals>
42+
<goal>appengine:update_indexes</goal>
43+
</goals>
44+
</action>
45+
<action>
46+
<actionName>CUSTOM-appengine:update_queues</actionName>
47+
<displayName>appengine:update_queues</displayName>
48+
<goals>
49+
<goal>appengine:update_queues</goal>
50+
</goals>
51+
</action>
52+
</actions>

samples/photo_album_gae/pom.xml

Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
2+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
3+
<modelVersion>4.0.0</modelVersion>
4+
<groupId>com.cloudinary</groupId>
5+
<artifactId>photo_album_gae</artifactId>
6+
<packaging>war</packaging>
7+
<version>1.0-SNAPSHOT</version>
8+
<name>photo_album_gae</name>
9+
10+
<properties>
11+
<spring.version>3.2.0.RELEASE</spring.version>
12+
<appengine.app.version>1</appengine.app.version>
13+
<appengine.target.version>1.8.9</appengine.target.version>
14+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
15+
</properties>
16+
17+
<repositories>
18+
<repository>
19+
<id>JBoss Repository</id>
20+
<url>https://repository.jboss.org/nexus/content/repositories/releases</url>
21+
<name>JBoss Repository</name>
22+
</repository>
23+
<repository>
24+
<id>gmultipart</id>
25+
<url>http://gmultipart.googlecode.com/svn/repo/m2</url>
26+
</repository>
27+
</repositories>
28+
29+
<pluginRepositories>
30+
<pluginRepository>
31+
<id>google-staging</id>
32+
<name>Google Staging</name>
33+
<url>https://oss.sonatype.org/content/repositories/comgoogleappengine-1004/</url>
34+
</pluginRepository>
35+
</pluginRepositories>
36+
37+
<dependencies>
38+
<dependency>
39+
<groupId>com.cloudinary</groupId>
40+
<artifactId>cloudinary-taglib</artifactId>
41+
<version>1.0.13-SNAPSHOT</version>
42+
</dependency>
43+
<dependency>
44+
<groupId>org.springframework</groupId>
45+
<artifactId>spring-core</artifactId>
46+
<version>${spring.version}</version>
47+
</dependency>
48+
49+
<dependency>
50+
<groupId>org.springframework</groupId>
51+
<artifactId>spring-web</artifactId>
52+
<version>${spring.version}</version>
53+
</dependency>
54+
55+
<dependency>
56+
<groupId>javax.servlet</groupId>
57+
<artifactId>servlet-api</artifactId>
58+
<version>2.5</version>
59+
</dependency>
60+
61+
<dependency>
62+
<groupId>javax.servlet.jsp</groupId>
63+
<artifactId>jsp-api</artifactId>
64+
<version>2.1</version>
65+
<scope>provided</scope>
66+
</dependency>
67+
68+
<dependency>
69+
<groupId>org.springframework</groupId>
70+
<artifactId>spring-webmvc</artifactId>
71+
<version>${spring.version}</version>
72+
</dependency>
73+
74+
<dependency>
75+
<groupId>org.springframework</groupId>
76+
<artifactId>spring-test</artifactId>
77+
<version>${spring.version}</version>
78+
<scope>test</scope>
79+
</dependency>
80+
81+
<dependency>
82+
<groupId>junit</groupId>
83+
<artifactId>junit</artifactId>
84+
<version>4.10</version>
85+
<scope>test</scope>
86+
</dependency>
87+
88+
<dependency>
89+
<groupId>jstl</groupId>
90+
<artifactId>jstl</artifactId>
91+
<version>1.2</version>
92+
</dependency>
93+
94+
<dependency>
95+
<groupId>org.springframework.data</groupId>
96+
<artifactId>spring-data-jpa</artifactId>
97+
<version>1.2.0.RELEASE</version>
98+
</dependency>
99+
100+
<dependency>
101+
<groupId>com.google.appengine</groupId>
102+
<artifactId>appengine-api-1.0-sdk</artifactId>
103+
<version>${appengine.target.version}</version>
104+
</dependency>
105+
106+
<dependency>
107+
<groupId>commons-fileupload</groupId>
108+
<artifactId>commons-fileupload</artifactId>
109+
<version>1.3</version>
110+
</dependency>
111+
112+
<dependency>
113+
<groupId>javax.validation</groupId>
114+
<artifactId>validation-api</artifactId>
115+
<version>1.1.0.Final</version>
116+
</dependency>
117+
118+
<dependency>
119+
<groupId>org.mockito</groupId>
120+
<artifactId>mockito-all</artifactId>
121+
<version>1.9.0</version>
122+
<scope>test</scope>
123+
</dependency>
124+
125+
<dependency>
126+
<groupId>com.google.appengine</groupId>
127+
<artifactId>appengine-testing</artifactId>
128+
<version>${appengine.target.version}</version>
129+
<scope>test</scope>
130+
</dependency>
131+
<dependency>
132+
<groupId>com.google.appengine</groupId>
133+
<artifactId>appengine-api-stubs</artifactId>
134+
<version>${appengine.target.version}</version>
135+
<scope>test</scope>
136+
</dependency>
137+
138+
<dependency>
139+
<groupId>org.hibernate</groupId>
140+
<artifactId>hibernate-validator-annotation-processor</artifactId>
141+
<version>4.1.0.Final</version>
142+
</dependency>
143+
144+
<dependency>
145+
<groupId>gmultipart</groupId>
146+
<artifactId>gmultipart</artifactId>
147+
<version>0.4</version>
148+
</dependency>
149+
</dependencies>
150+
151+
<build>
152+
<finalName>photo_album</finalName>
153+
<plugins>
154+
<plugin>
155+
<groupId>org.apache.maven.plugins</groupId>
156+
<version>2.5.1</version>
157+
<artifactId>maven-compiler-plugin</artifactId>
158+
<configuration>
159+
<source>1.7</source>
160+
<target>1.7</target>
161+
</configuration>
162+
</plugin>
163+
164+
<plugin>
165+
<groupId>org.apache.maven.plugins</groupId>
166+
<artifactId>maven-war-plugin</artifactId>
167+
<version>2.3</version>
168+
<configuration>
169+
<archiveClasses>true</archiveClasses>
170+
<webResources>
171+
<!-- in order to interpolate version from pom into appengine-web.xml -->
172+
<resource>
173+
<directory>${basedir}/src/main/webapp/WEB-INF</directory>
174+
<filtering>true</filtering>
175+
<targetPath>WEB-INF</targetPath>
176+
</resource>
177+
</webResources>
178+
</configuration>
179+
</plugin>
180+
181+
<plugin>
182+
<groupId>com.google.appengine</groupId>
183+
<artifactId>appengine-maven-plugin</artifactId>
184+
<version>${appengine.target.version}</version>
185+
</plugin>
186+
</plugins>
187+
</build>
188+
</project>
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
package cloudinary.controllers;
2+
3+
import cloudinary.lib.PhotoUploadValidator;
4+
import cloudinary.models.PhotoUpload;
5+
import com.cloudinary.Cloudinary;
6+
import com.cloudinary.Singleton;
7+
import org.springframework.stereotype.Controller;
8+
import org.springframework.ui.ModelMap;
9+
import org.springframework.validation.BindingResult;
10+
import org.springframework.web.bind.annotation.*;
11+
12+
import com.google.appengine.api.datastore.DatastoreService;
13+
import com.google.appengine.api.datastore.DatastoreServiceFactory;
14+
import com.google.appengine.api.datastore.Entity;
15+
import com.google.appengine.api.datastore.Key;
16+
import com.google.appengine.api.datastore.KeyFactory;
17+
import com.google.appengine.api.datastore.Query;
18+
import com.google.appengine.api.datastore.FetchOptions;
19+
20+
21+
import java.io.IOException;
22+
import java.util.Map;
23+
import java.util.List;
24+
25+
import org.esxx.js.protocol.GAEConnectionManager;
26+
27+
@Controller
28+
@RequestMapping("/")
29+
public class PhotoController {
30+
private final static GAEConnectionManager connectoinManager = new GAEConnectionManager();
31+
@RequestMapping(value = "/", method = RequestMethod.GET)
32+
public String listPhotos(ModelMap model) {
33+
DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
34+
Key photoKey = KeyFactory.createKey("photos", "album");
35+
List<Entity> photoEntities = datastore.prepare(new Query("photo", photoKey)).asList(FetchOptions.Builder.withDefaults());
36+
List<PhotoUpload> photos = new java.util.ArrayList<PhotoUpload>();
37+
for(int i = 0, n = photoEntities.size(); i < n; i++) {
38+
photos.add(new PhotoUpload(photoEntities.get(i)));
39+
}
40+
model.addAttribute("photos", photos);
41+
return "photos";
42+
}
43+
44+
@RequestMapping(value = "/upload", method = RequestMethod.POST)
45+
public String uploadPhoto(@ModelAttribute PhotoUpload photoUpload, BindingResult result, ModelMap model) throws IOException {
46+
PhotoUploadValidator validator = new PhotoUploadValidator();
47+
validator.validate(photoUpload, result);
48+
49+
Map uploadResult = null;
50+
if (photoUpload.getFile() != null && !photoUpload.getFile().isEmpty()) {
51+
uploadResult = Singleton.getCloudinary().uploader().withConnectionManager(connectoinManager).upload(photoUpload.getFile().getBytes(),
52+
Cloudinary.asMap("resource_type", "auto"));
53+
54+
photoUpload.setPublicId((String) uploadResult.get("public_id"));
55+
photoUpload.setVersion((Long) uploadResult.get("version"));
56+
photoUpload.setSignature((String) uploadResult.get("signature"));
57+
photoUpload.setFormat((String) uploadResult.get("format"));
58+
photoUpload.setResourceType((String) uploadResult.get("resource_type"));
59+
}
60+
61+
if (result.hasErrors()){
62+
model.addAttribute("photoUpload", photoUpload);
63+
return "upload_form";
64+
} else {
65+
Key photoKey = KeyFactory.createKey("photos", "album");
66+
Entity photo = new Entity("photo", photoKey);
67+
photoUpload.toEntity(photo);
68+
model.addAttribute("upload", uploadResult);
69+
DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
70+
datastore.put(photo);
71+
model.addAttribute("photo", photoUpload);
72+
return "upload";
73+
}
74+
}
75+
76+
@RequestMapping(value = "/upload_form", method = RequestMethod.GET)
77+
public String uploadPhotoForm(ModelMap model) {
78+
model.addAttribute("photo", new PhotoUpload());
79+
return "upload_form";
80+
}
81+
82+
@RequestMapping(value = "/direct_upload_form", method = RequestMethod.GET)
83+
public String directUploadPhotoForm(ModelMap model) {
84+
model.addAttribute("photo", new PhotoUpload());
85+
return "direct_upload_form";
86+
}
87+
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy