http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/e3d95284/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/RequestEchoResource.java ---------------------------------------------------------------------- diff --git a/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/RequestEchoResource.java b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/RequestEchoResource.java new file mode 100644 index 0000000..354ed8d --- /dev/null +++ b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/RequestEchoResource.java @@ -0,0 +1,60 @@ +// *************************************************************************************************************************** +// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file * +// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file * +// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance * +// * with the License. You may obtain a copy of the License at * +// * * +// * http://www.apache.org/licenses/LICENSE-2.0 * +// * * +// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an * +// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * +// * specific language governing permissions and limitations under the License. * +// *************************************************************************************************************************** +package org.apache.juneau.examples.rest; + +import static org.apache.juneau.html.HtmlDocSerializerContext.*; + +import javax.servlet.*; +import javax.servlet.http.*; + +import org.apache.juneau.*; +import org.apache.juneau.microservice.*; +import org.apache.juneau.rest.*; +import org.apache.juneau.rest.annotation.*; +import org.apache.juneau.rest.converters.*; +import org.apache.juneau.transforms.*; + +/** + * Sample REST resource for echoing HttpServletRequests back to the browser. + */ +@RestResource( + path="/echo", + messages="nls/RequestEchoResource", + properties={ + @Property(name=SERIALIZER_maxDepth, value="5"), + @Property(name=SERIALIZER_detectRecursions, value="true"), + @Property(name=HTMLDOC_links, value="{up:'$R{requestParentURI}',options:'?method=OPTIONS',source:'$R{servletParentURI}/source?classes=(org.apache.juneau.examples.rest.RequestEchoResource)'}") + }, + beanFilters={ + // Interpret these as their parent classes, not subclasses + HttpServletRequest.class, HttpSession.class, ServletContext.class, + }, + pojoSwaps={ + // Add a special filter for Enumerations + EnumerationSwap.class + } +) +public class RequestEchoResource extends Resource { + private static final long serialVersionUID = 1L; + + /** GET request handler */ + @RestMethod(name="GET", path="/*", converters={Traversable.class,Queryable.class}) + public HttpServletRequest doGet(RestRequest req, @Properties ObjectMap properties) { + // Set the HtmlDocSerializer title programmatically. + // This sets the value for this request only. + properties.put(HTMLDOC_title, "Contents of HttpServletRequest object"); + + // Just echo the request back as the response. + return req; + } +}
http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/e3d95284/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/RootResources.java ---------------------------------------------------------------------- diff --git a/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/RootResources.java b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/RootResources.java new file mode 100644 index 0000000..b193217 --- /dev/null +++ b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/RootResources.java @@ -0,0 +1,55 @@ +// *************************************************************************************************************************** +// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file * +// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file * +// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance * +// * with the License. You may obtain a copy of the License at * +// * * +// * http://www.apache.org/licenses/LICENSE-2.0 * +// * * +// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an * +// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * +// * specific language governing permissions and limitations under the License. * +// *************************************************************************************************************************** +package org.apache.juneau.examples.rest; + +import static org.apache.juneau.html.HtmlDocSerializerContext.*; + +import org.apache.juneau.examples.rest.addressbook.*; +import org.apache.juneau.microservice.*; +import org.apache.juneau.microservice.resources.*; +import org.apache.juneau.rest.annotation.*; + +/** + * Sample REST resource showing how to implement a "router" resource page. + */ +@RestResource( + path="/", + messages="nls/RootResources", + properties={ + @Property(name=HTMLDOC_links, value="{options:'$R{servletURI}?method=OPTIONS',source:'$R{servletURI}/source?classes=(org.apache.juneau.examples.rest.RootResources)'}") + }, + children={ + HelloWorldResource.class, + SystemPropertiesResource.class, + MethodExampleResource.class, + RequestEchoResource.class, + TempDirResource.class, + AddressBookResource.class, + SampleRemoteableServlet.class, + PhotosResource.class, + AtomFeedResource.class, + JsonSchemaResource.class, + SqlQueryResource.class, + TumblrParserResource.class, + CodeFormatterResource.class, + UrlEncodedFormResource.class, + SourceResource.class, + ConfigResource.class, + LogsResource.class, + DockerRegistryResource.class, + ShutdownResource.class + } +) +public class RootResources extends ResourceGroup { + private static final long serialVersionUID = 1L; +} http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/e3d95284/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/SampleRemoteableServlet.java ---------------------------------------------------------------------- diff --git a/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/SampleRemoteableServlet.java b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/SampleRemoteableServlet.java new file mode 100644 index 0000000..4eb38dd --- /dev/null +++ b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/SampleRemoteableServlet.java @@ -0,0 +1,55 @@ +// *************************************************************************************************************************** +// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file * +// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file * +// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance * +// * with the License. You may obtain a copy of the License at * +// * * +// * http://www.apache.org/licenses/LICENSE-2.0 * +// * * +// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an * +// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * +// * specific language governing permissions and limitations under the License. * +// *************************************************************************************************************************** +package org.apache.juneau.examples.rest; + +import static org.apache.juneau.html.HtmlDocSerializerContext.*; +import static org.apache.juneau.rest.RestServletContext.*; + +import java.util.*; + +import org.apache.juneau.examples.addressbook.*; +import org.apache.juneau.rest.annotation.*; +import org.apache.juneau.rest.remoteable.*; + +/** + * Class showing the functionality of the RemoteableServlet class. + */ +@SuppressWarnings("serial") +@RestResource( + path="/remoteable", + messages="nls/SampleRemoteableServlet", + properties={ + @Property(name=HTMLDOC_title, value="Remoteable Service Proxy API"), + @Property(name=HTMLDOC_description, value="Sample class showing how to use remoteable proxies. The list below are exposed services that can be retrieved using RestClient.getProxyInterface(Class)."), + @Property(name=HTMLDOC_links, value="{up:'$R{requestParentURI}',options:'$R{servletURI}?method=OPTIONS',source:'$R{servletParentURI}/source?classes=(org.apache.juneau.examples.rest.SampleRemoteableServlet)'}"), + // Allow us to use method=POST from a browser. + @Property(name=REST_allowMethodParam, value="*") + }, + stylesheet="styles/devops.css" +) +public class SampleRemoteableServlet extends RemoteableServlet { + + AddressBook addressBook = new AddressBook(); + + @Override /* RemoteableServlet */ + protected Map<Class<?>,Object> getServiceMap() throws Exception { + Map<Class<?>,Object> m = new LinkedHashMap<Class<?>,Object>(); + + // In this simplified example, we expose the same POJO service under two different interfaces. + // One is IAddressBook which only exposes methods defined on that interface, and + // the other is AddressBook itself which exposes all methods defined on the class itself. + m.put(IAddressBook.class, addressBook); + m.put(AddressBook.class, addressBook); + return m; + } +} http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/e3d95284/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/SourceResource.java ---------------------------------------------------------------------- diff --git a/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/SourceResource.java b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/SourceResource.java new file mode 100644 index 0000000..ba4550e --- /dev/null +++ b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/SourceResource.java @@ -0,0 +1,112 @@ +// *************************************************************************************************************************** +// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file * +// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file * +// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance * +// * with the License. You may obtain a copy of the License at * +// * * +// * http://www.apache.org/licenses/LICENSE-2.0 * +// * * +// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an * +// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * +// * specific language governing permissions and limitations under the License. * +// *************************************************************************************************************************** +package org.apache.juneau.examples.rest; + +import static org.apache.juneau.html.HtmlDocSerializerContext.*; + +import java.io.*; +import java.util.*; + +import org.apache.juneau.html.annotation.*; +import org.apache.juneau.internal.*; +import org.apache.juneau.microservice.*; +import org.apache.juneau.rest.annotation.*; + +/** + * Servlet for viewing source code on classes whose Java files are present on the classpath. + * <p> + * This class is by no means perfect but is pretty much the best you can get using only regular expression matching. + */ +@SuppressWarnings("serial") +@RestResource( + path="/source", + messages="nls/SourceResource", + properties={ + @Property(name=HTMLDOC_title, value="Source code viewer"), + @Property(name=HTMLDOC_cssImports, value="$R{servletURI}/htdocs/code-highlighting.css"), + @Property(name=HTMLDOC_links, value="{up:'$R{requestParentURI}',options:'$R{servletURI}?method=OPTIONS',source:'$R{servletParentURI}/source?classes=(org.apache.juneau.examples.rest.SourceResource)'}"), + } +) +public class SourceResource extends Resource { + + /** View source on the specified classes. */ + @RestMethod(name="GET", path="/") + public Object getSource(@Query("classes") String[] classes) throws Exception { + if (classes == null) + return "Specify classes using ?classes=(class1,class2,....) attribute"; + List<Object> l = new LinkedList<Object>(); + for (String c : classes) { + try { + l.add(new Source(Class.forName(c))); + } catch (ClassNotFoundException e) { + l.add("Class " + c + " not found"); + } catch (Exception e) { + l.add(e.getLocalizedMessage()); + } + } + return l; + } + + /** + * POJO that allows us to serialize HTML directly to the output. + */ + @Html(asPlainText=true) + public static class Source { + private Class<?> c; + private Source(Class<?> c) { + this.c = c; + } + @Override /* Object */ + public String toString() { + String filename = c.getSimpleName() + ".java"; + InputStream is = c.getResourceAsStream('/' + c.getPackage().getName().replace('.','/') + '/' + filename); + if (is == null) + return "Source for class " + c.getName() + " not found"; + StringBuilder sb = new StringBuilder(); + try { + sb.append("<h3>").append(c.getSimpleName()).append(".java").append("</h3>"); + sb.append("<p class='bcode'>"); + sb.append(highlight(IOUtils.read(is), "java")); + sb.append("</p>"); + } catch (Exception e) { + return e.getLocalizedMessage(); + } + return sb.toString(); + } + } + + public static String highlight(String code, String lang) throws Exception { + if (lang.equalsIgnoreCase("xml")) { + code = code.replaceAll("&", "&"); + code = code.replaceAll("<", "<"); + code = code.replaceAll(">", ">"); + code = code.replaceAll("(<[^\\s&]+>)", "<xt>$1</xt>"); + code = code.replaceAll("(<[^\\s&]+)(\\s)", "<xt>$1</xt>$2"); + code = code.replaceAll("(['\"])(/?>)", "$1<xt>$2</xt>"); + code = code.replaceAll("([\\S]+)=", "<xa>$1</xa>="); + code = code.replaceAll("=(['\"][^'\"]+['\"])", "=<xs>$1</xs>"); + } else if (lang.equalsIgnoreCase("java")) { + code = code.replaceAll("&", "&"); + code = code.replaceAll("<", "<"); + code = code.replaceAll(">", ">"); + code = code.replaceAll("(?s)(\\/\\*\\*.*?\\*\\/)", "<jd>$1</jd>"); // javadoc comments + code = code.replaceAll("(@\\w+)", "<ja>$1</ja>"); // annotations + code = code.replaceAll("(?s)(?!\\/)(\\/\\*.*?\\*\\/)", "<jc>$1</jc>"); // C style comments + code = code.replaceAll("(?m)(\\/\\/.*)", "<jc>$1</jc>"); // C++ style comments + code = code.replaceAll("(?m)('[^'\n]*'|\"[^\"\n]*\")", "<js>$1</js>"); // quotes + code = code.replaceAll("(?<!@)(import|package|boolean|byte|char|double|float|final|static|transient|synchronized|private|protected|public|int|long|short|abstract|class|interface|extends|implements|null|true|false|void|break|case|catch|continue|default|do|else|finally|for|goto|if|instanceof|native|new|return|super|switch|this|threadsafe|throws|throw|try|while)(?=\\W)", "<jk>$1</jk>"); // quotes + code = code.replaceAll("<\\/jk>(\\s+)<jk>", "$1"); // quotes + } + return code; + } +} http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/e3d95284/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/SqlQueryResource.java ---------------------------------------------------------------------- diff --git a/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/SqlQueryResource.java b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/SqlQueryResource.java new file mode 100644 index 0000000..3c42557 --- /dev/null +++ b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/SqlQueryResource.java @@ -0,0 +1,128 @@ +// *************************************************************************************************************************** +// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file * +// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file * +// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance * +// * with the License. You may obtain a copy of the License at * +// * * +// * http://www.apache.org/licenses/LICENSE-2.0 * +// * * +// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an * +// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * +// * specific language governing permissions and limitations under the License. * +// *************************************************************************************************************************** +package org.apache.juneau.examples.rest; + +import static javax.servlet.http.HttpServletResponse.*; +import static org.apache.juneau.html.HtmlDocSerializerContext.*; + +import java.io.*; +import java.sql.*; +import java.util.*; + +import org.apache.juneau.dto.*; +import org.apache.juneau.ini.*; +import org.apache.juneau.internal.*; +import org.apache.juneau.microservice.*; +import org.apache.juneau.rest.*; +import org.apache.juneau.rest.annotation.*; + +/** + * Sample resource that shows how Juneau can serialize ResultSets. + */ +@RestResource( + path="/sqlQuery", + messages="nls/SqlQueryResource", + properties={ + @Property(name=HTMLDOC_title, value="SQL query service"), + @Property(name=HTMLDOC_description, value="Executes queries against the local derby '$C{SqlQueryResource/connectionUrl}' database"), + @Property(name=HTMLDOC_links, value="{up:'$R{requestParentURI}',options:'$R{servletURI}?method=OPTIONS',source:'$R{servletParentURI}/source?classes=(org.apache.juneau.examples.rest.SqlQueryResource)'}"), + } +) +public class SqlQueryResource extends Resource { + private static final long serialVersionUID = 1L; + + private ConfigFile cf = getConfig(); + + private String driver = cf.getString("SqlQueryResource/driver"); + private String connectionUrl = cf.getString("SqlQueryResource/connectionUrl"); + private boolean + allowUpdates = cf.getBoolean("SqlQueryResource/allowUpdates", false), + allowTempUpdates = cf.getBoolean("SqlQueryResource/allowTempUpdates", false), + includeRowNums = cf.getBoolean("SqlQueryResource/includeRowNums", false); + + @Override /* Servlet */ + public void init() { + try { + Class.forName(driver).newInstance(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /** GET request handler - Display the query entry page. */ + @RestMethod(name="GET", path="/") + public ReaderResource doGet(RestRequest req) throws IOException { + return req.getReaderResource("SqlQueryResource.html", true); + } + + /** POST request handler - Execute the query. */ + @RestMethod(name="POST", path="/") + public List<Object> doPost(@Body PostInput in) throws Exception { + + List<Object> results = new LinkedList<Object>(); + + // Don't try to submit empty input. + if (StringUtils.isEmpty(in.sql)) + return results; + + if (in.pos < 1 || in.pos > 10000) + throw new RestException(SC_BAD_REQUEST, "Invalid value for position. Must be between 1-10000"); + if (in.limit < 1 || in.limit > 10000) + throw new RestException(SC_BAD_REQUEST, "Invalid value for limit. Must be between 1-10000"); + + // Create a connection and statement. + // If these fais, let the exception filter up as a 500 error. + Connection c = DriverManager.getConnection(connectionUrl); + c.setAutoCommit(false); + Statement st = c.createStatement(); + String sql = null; + + try { + for (String s : in.sql.split(";")) { + sql = s.trim(); + if (! sql.isEmpty()) { + Object o = null; + if (allowUpdates || (allowTempUpdates && ! sql.matches("(?:i)commit.*"))) { + if (st.execute(sql)) { + ResultSet rs = st.getResultSet(); + o = new ResultSetList(rs, in.pos, in.limit, includeRowNums); + } else { + o = st.getUpdateCount(); + } + } else { + ResultSet rs = st.executeQuery(sql); + o = new ResultSetList(rs, in.pos, in.limit, includeRowNums); + } + results.add(o); + } + } + if (allowUpdates) + c.commit(); + else if (allowTempUpdates) + c.rollback(); + } catch (SQLException e) { + c.rollback(); + throw new RestException(SC_BAD_REQUEST, "Invalid query: {0}", sql).initCause(e); + } finally { + c.close(); + } + + return results; + } + + /** The parsed form post */ + public static class PostInput { + public String sql; + public int pos = 1, limit = 100; + } +} http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/e3d95284/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/SystemPropertiesResource.java ---------------------------------------------------------------------- diff --git a/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/SystemPropertiesResource.java b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/SystemPropertiesResource.java new file mode 100644 index 0000000..8e4dd0b --- /dev/null +++ b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/SystemPropertiesResource.java @@ -0,0 +1,153 @@ +// *************************************************************************************************************************** +// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file * +// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file * +// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance * +// * with the License. You may obtain a copy of the License at * +// * * +// * http://www.apache.org/licenses/LICENSE-2.0 * +// * * +// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an * +// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * +// * specific language governing permissions and limitations under the License. * +// *************************************************************************************************************************** +package org.apache.juneau.examples.rest; + +import static org.apache.juneau.html.HtmlDocSerializerContext.*; + +import java.util.*; + +import org.apache.juneau.dto.swagger.*; +import org.apache.juneau.encoders.*; +import org.apache.juneau.rest.*; +import org.apache.juneau.rest.annotation.*; + +@RestResource( + path="/systemProperties", + title="System properties resource", + description="REST interface for performing CRUD operations on system properties.", + properties={ + @Property(name=SERIALIZER_quoteChar, value="'"), + @Property(name=HTMLDOC_links, value="{up:'$R{requestParentURI}',options:'$R{servletURI}?method=OPTIONS'}"), + }, + stylesheet="styles/devops.css", + encoders=GzipEncoder.class, + contact="{name:'John Smith',email:'[email protected]'}", + license="{name:'Apache 2.0',url:'http://www.apache.org/licenses/LICENSE-2.0.html'}", + version="2.0", + termsOfService="You're on your own.", + tags="[{name:'Java',description:'Java utility',externalDocs:{description:'Home page',url:'http://juneau.apache.org'}}]", + externalDocs="{description:'Home page',url:'http://juneau.apache.org'}" +) +public class SystemPropertiesResource extends RestServletDefault { + private static final long serialVersionUID = 1L; + + @RestMethod( + name="GET", path="/", + summary="Show all system properties", + description="Returns all system properties defined in the JVM.", + parameters={ + @Parameter(in="query", name="sort", description="Sort results alphabetically.", _default="false") + }, + responses={ + @Response(value=200, description="Returns a map of key/value pairs.") + } + ) + @SuppressWarnings({"rawtypes", "unchecked"}) + public Map getSystemProperties(@Query("sort") boolean sort) throws Throwable { + if (sort) + return new TreeMap(System.getProperties()); + return System.getProperties(); + } + + @RestMethod( + name="GET", path="/{propertyName}", + summary="Get system property", + description="Returns the value of the specified system property.", + parameters={ + @Parameter(in="path", name="propertyName", description="The system property name.") + }, + responses={ + @Response(value=200, description="The system property value, or null if not found.") + } + ) + public String getSystemProperty(@Path String propertyName) throws Throwable { + return System.getProperty(propertyName); + } + + @RestMethod( + name="PUT", path="/{propertyName}", + summary="Replace system property", + description="Sets a new value for the specified system property.", + guards=AdminGuard.class, + parameters={ + @Parameter(in="path", name="propertyName", description="The system property name."), + @Parameter(in="body", description="The new system property value."), + }, + responses={ + @Response(value=302, + headers={ + @Parameter(name="Location", description="The root URL of this resource.") + } + ), + @Response(value=403, description="User is not an admin.") + } + ) + public Redirect setSystemProperty(@Path String propertyName, @Body String value) { + System.setProperty(propertyName, value); + return new Redirect(); + } + + @RestMethod( + name="POST", path="/", + summary="Add an entire set of system properties", + description="Takes in a map of key/value pairs and creates a set of new system properties.", + guards=AdminGuard.class, + parameters={ + @Parameter(in="path", name="propertyName", description="The system property key."), + @Parameter(in="body", description="The new system property values.", schema="{example:{key1:'val1',key2:123}}"), + }, + responses={ + @Response(value=302, + headers={ + @Parameter(name="Location", description="The root URL of this resource.") + } + ), + @Response(value=403, description="Unauthorized: User is not an admin.") + } + ) + public Redirect setSystemProperties(@Body java.util.Properties newProperties) { + System.setProperties(newProperties); + return new Redirect(); + } + + @RestMethod( + name="DELETE", path="/{propertyName}", + summary="Delete system property", + description="Deletes the specified system property.", + guards=AdminGuard.class, + parameters={ + @Parameter(in="path", name="propertyName", description="The system property name."), + }, + responses={ + @Response(value=302, + headers={ + @Parameter(name="Location", description="The root URL of this resource.") + } + ), + @Response(value=403, description="Unauthorized: User is not an admin") + } + ) + public Redirect deleteSystemProperty(@Path String propertyName) { + System.clearProperty(propertyName); + return new Redirect(); + } + + @RestMethod( + name="OPTIONS", path="/*", + summary="Show resource options", + description="Show resource options as a Swagger doc" + ) + public Swagger getOptions(RestRequest req) { + return req.getSwagger(); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/e3d95284/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/TempDirResource.java ---------------------------------------------------------------------- diff --git a/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/TempDirResource.java b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/TempDirResource.java new file mode 100644 index 0000000..3753c17 --- /dev/null +++ b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/TempDirResource.java @@ -0,0 +1,77 @@ +// *************************************************************************************************************************** +// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file * +// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file * +// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance * +// * with the License. You may obtain a copy of the License at * +// * * +// * http://www.apache.org/licenses/LICENSE-2.0 * +// * * +// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an * +// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * +// * specific language governing permissions and limitations under the License. * +// *************************************************************************************************************************** +package org.apache.juneau.examples.rest; + +import static org.apache.juneau.html.HtmlDocSerializerContext.*; + +import java.io.*; + +import org.apache.commons.fileupload.*; +import org.apache.commons.fileupload.servlet.*; +import org.apache.juneau.rest.*; +import org.apache.juneau.rest.annotation.*; +import org.apache.juneau.utils.*; + +/** + * Sample resource that extends {@link DirectoryResource} to open up the temp directory as a REST resource. + */ +@RestResource( + path="/tempDir", + messages="nls/TempDirResource", + properties={ + @Property(name="rootDir", value="$S{java.io.tmpdir}"), + @Property(name="allowViews", value="true"), + @Property(name="allowDeletes", value="true"), + @Property(name="allowPuts", value="false"), + @Property(name=HTMLDOC_links, value="{up:'$R{requestParentURI}',options:'$R{servletURI}?method=OPTIONS',upload:'upload',source:'$R{servletParentURI}/source?classes=(org.apache.juneau.examples.rest.TempDirResource,org.apache.juneau.examples.rest.DirectoryResource)'}"), + }, + stylesheet="styles/devops.css" +) +public class TempDirResource extends DirectoryResource { + private static final long serialVersionUID = 1L; + + /** + * [GET /upload] - Display the form entry page for uploading a file to the temp directory. + */ + @RestMethod(name="GET", path="/upload") + public ReaderResource getUploadPage(RestRequest req) throws IOException { + return req.getReaderResource("TempDirUploadPage.html", true); + } + + /** + * [POST /upload] - Upload a file as a multipart form post. + * Shows how to use the Apache Commons ServletFileUpload class for handling multi-part form posts. + */ + @RestMethod(name="POST", path="/upload", matchers=TempDirResource.MultipartFormDataMatcher.class) + public Redirect uploadFile(RestRequest req) throws Exception { + ServletFileUpload upload = new ServletFileUpload(); + FileItemIterator iter = upload.getItemIterator(req); + while (iter.hasNext()) { + FileItemStream item = iter.next(); + if (item.getFieldName().equals("contents")) { //$NON-NLS-1$ + File f = new File(getRootDir(), item.getName()); + IOPipe.create(item.openStream(), new FileOutputStream(f)).closeOut().run(); + } + } + return new Redirect(); // Redirect to the servlet root. + } + + /** Causes a 404 if POST isn't multipart/form-data */ + public static class MultipartFormDataMatcher extends RestMatcher { + @Override /* RestMatcher */ + public boolean matches(RestRequest req) { + String contentType = req.getContentType(); + return contentType != null && contentType.startsWith("multipart/form-data"); //$NON-NLS-1$ + } + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/e3d95284/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/TumblrParserResource.java ---------------------------------------------------------------------- diff --git a/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/TumblrParserResource.java b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/TumblrParserResource.java new file mode 100644 index 0000000..d6f43e4 --- /dev/null +++ b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/TumblrParserResource.java @@ -0,0 +1,87 @@ +// *************************************************************************************************************************** +// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file * +// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file * +// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance * +// * with the License. You may obtain a copy of the License at * +// * * +// * http://www.apache.org/licenses/LICENSE-2.0 * +// * * +// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an * +// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * +// * specific language governing permissions and limitations under the License. * +// *************************************************************************************************************************** +package org.apache.juneau.examples.rest; + +import static org.apache.juneau.html.HtmlDocSerializerContext.*; + +import java.lang.Object; + +import org.apache.juneau.*; +import org.apache.juneau.dto.Link; +import org.apache.juneau.dto.html5.*; +import org.apache.juneau.json.*; +import org.apache.juneau.microservice.*; +import org.apache.juneau.rest.annotation.*; +import org.apache.juneau.rest.client.*; + +@RestResource( + path="/tumblrParser", + messages="nls/TumblrParserResource", + properties={ + @Property(name=HTMLDOC_links, value="{up:'$R{requestParentURI}',options:'?method=OPTIONS',source:'$R{servletParentURI}/source?classes=(org.apache.juneau.examples.rest.TumblrParserResource)'}"), + @Property(name=HTMLDOC_title, value="Tumblr parser service"), + @Property(name=HTMLDOC_description, value="Specify a URL to a Tumblr blog and parse the results.") + } +) +public class TumblrParserResource extends Resource { + private static final long serialVersionUID = 1L; + + @RestMethod(name="GET", path="/") + public String getInstructions() throws Exception { + return "Append the Tumblr blog name to the URL above (e.g. /juneau/sample/tumblrParser/mytumblrblog)"; + } + + @RestMethod(name="GET", path="/{blogName}") + public ObjectList parseBlog(@Path String blogName) throws Exception { + ObjectList l = new ObjectList(); + RestClient rc = new RestClient(JsonSerializer.class, JsonParser.class); + try { + String site = "http://" + blogName + ".tumblr.com/api/read/json"; + ObjectMap m = rc.doGet(site).getResponse(ObjectMap.class); + int postsTotal = m.getInt("posts-total"); + for (int i = 0; i < postsTotal; i += 20) { + m = rc.doGet(site + "?start=" + i + "&num=20&filter=text").getResponse(ObjectMap.class); + ObjectList ol = m.getObjectList("posts"); + for (int j = 0; j < ol.size(); j++) { + ObjectMap om = ol.getObjectMap(j); + String type = om.getString("type"); + Entry e = new Entry(); + e.date = om.getString("date"); + if (type.equals("link")) + e.entry = new Link(om.getString("link-text"), om.getString("link-url")); + else if (type.equals("audio")) + e.entry = new ObjectMap().append("type","audio").append("audio-caption", om.getString("audio-caption")); + else if (type.equals("video")) + e.entry = new ObjectMap().append("type","video").append("video-caption", om.getString("video-caption")); + else if (type.equals("quote")) + e.entry = new ObjectMap().append("type","quote").append("quote-source", om.getString("quote-source")).append("quote-text", om.getString("quote-text")); + else if (type.equals("regular")) + e.entry = om.getString("regular-body"); + else if (type.equals("photo")) + e.entry = new Img().src(om.getString("photo-url-250")); + else + e.entry = new ObjectMap().append("type", type); + l.add(e); + } + } + } finally { + rc.closeQuietly(); + } + return l; + } + + public static class Entry { + public String date; + public Object entry; + } +} http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/e3d95284/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/UrlEncodedFormResource.java ---------------------------------------------------------------------- diff --git a/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/UrlEncodedFormResource.java b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/UrlEncodedFormResource.java new file mode 100644 index 0000000..e3da795 --- /dev/null +++ b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/UrlEncodedFormResource.java @@ -0,0 +1,53 @@ +// *************************************************************************************************************************** +// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file * +// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file * +// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance * +// * with the License. You may obtain a copy of the License at * +// * * +// * http://www.apache.org/licenses/LICENSE-2.0 * +// * * +// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an * +// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * +// * specific language governing permissions and limitations under the License. * +// *************************************************************************************************************************** +package org.apache.juneau.examples.rest; + +import java.io.*; +import java.util.*; + +import org.apache.juneau.annotation.*; +import org.apache.juneau.microservice.*; +import org.apache.juneau.rest.*; +import org.apache.juneau.rest.annotation.*; +import org.apache.juneau.transforms.*; + +/** + * Sample REST resource for loading URL-Encoded form posts into POJOs. + */ +@RestResource( + path="/urlEncodedForm", + messages="nls/UrlEncodedFormResource" +) +public class UrlEncodedFormResource extends Resource { + private static final long serialVersionUID = 1L; + + /** GET request handler */ + @RestMethod(name="GET", path="/") + public ReaderResource doGet(RestRequest req) throws IOException { + return req.getReaderResource("UrlEncodedForm.html", true); + } + + /** POST request handler */ + @RestMethod(name="POST", path="/") + public Object doPost(@Body FormInputBean input) throws Exception { + // Just mirror back the request + return input; + } + + public static class FormInputBean { + public String aString; + public int aNumber; + @BeanProperty(swap=CalendarSwap.ISO8601DT.class) + public Calendar aDate; + } +} http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/e3d95284/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/addressbook/AddressBookResource.java ---------------------------------------------------------------------- diff --git a/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/addressbook/AddressBookResource.java b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/addressbook/AddressBookResource.java new file mode 100644 index 0000000..f66a5bc --- /dev/null +++ b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/addressbook/AddressBookResource.java @@ -0,0 +1,320 @@ +// *************************************************************************************************************************** +// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file * +// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file * +// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance * +// * with the License. You may obtain a copy of the License at * +// * * +// * http://www.apache.org/licenses/LICENSE-2.0 * +// * * +// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an * +// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * +// * specific language governing permissions and limitations under the License. * +// *************************************************************************************************************************** +package org.apache.juneau.examples.rest.addressbook; + +import static javax.servlet.http.HttpServletResponse.*; +import static org.apache.juneau.examples.addressbook.AddressBook.*; +import static org.apache.juneau.html.HtmlDocSerializerContext.*; +import static org.apache.juneau.jena.RdfCommonContext.*; +import static org.apache.juneau.jena.RdfSerializerContext.*; +import static org.apache.juneau.rest.RestServletContext.*; + +import java.util.*; + +import org.apache.juneau.*; +import org.apache.juneau.dto.*; +import org.apache.juneau.dto.cognos.*; +import org.apache.juneau.dto.swagger.*; +import org.apache.juneau.encoders.*; +import org.apache.juneau.examples.addressbook.*; +import org.apache.juneau.examples.rest.*; +import org.apache.juneau.microservice.*; +import org.apache.juneau.rest.*; +import org.apache.juneau.rest.annotation.*; +import org.apache.juneau.rest.converters.*; +import org.apache.juneau.transform.*; +import org.apache.juneau.utils.*; + +/** + * Proof-of-concept resource that shows off the capabilities of working with POJO resources. + * Consists of an in-memory address book repository. + */ +@RestResource( + path="/addressBook", + messages="nls/AddressBookResource", + properties={ + @Property(name=REST_allowMethodParam, value="*"), + @Property(name=HTML_uriAnchorText, value=TO_STRING), + @Property(name=SERIALIZER_quoteChar, value="'"), + @Property(name=RDF_rdfxml_tab, value="5"), + @Property(name=RDF_addRootProperty, value="true"), + @Property(name=HTMLDOC_links, value="{up:'$R{requestParentURI}',options:'$R{servletURI}?method=OPTIONS',source:'$R{servletParentURI}/source?classes=(org.apache.juneau.examples.rest.addressbook.AddressBookResource,org.apache.juneau.examples.addressbook.Address,org.apache.juneau.examples.addressbook.AddressBook,org.apache.juneau.examples.addressbook.CreateAddress,org.apache.juneau.examples.addressbook.CreatePerson,org.apache.juneau.examples.addressbook.IAddressBook,org.apache.juneau.examples.addressbook.Person)'}"), + // Resolve all relative URIs so that they're relative to this servlet! + @Property(name=SERIALIZER_relativeUriBase, value="$R{servletURI}"), + }, + stylesheet="styles/devops.css", + encoders=GzipEncoder.class, + contact="{name:'John Smith',email:'[email protected]'}", + license="{name:'Apache 2.0',url:'http://www.apache.org/licenses/LICENSE-2.0.html'}", + version="2.0", + termsOfService="You're on your own.", + tags="[{name:'Java',description:'Java utility',externalDocs:{description:'Home page',url:'http://juneau.apache.org'}}]", + externalDocs="{description:'Home page',url:'http://juneau.apache.org'}" +) +public class AddressBookResource extends ResourceJena { + private static final long serialVersionUID = 1L; + + // The in-memory address book + private AddressBook addressBook; + + @Override /* Servlet */ + public void init() { + + try { + // Create the address book + addressBook = new AddressBook(java.net.URI.create("")); + + // Add some people to our address book by default + addressBook.createPerson( + new CreatePerson( + "Barack Obama", + toCalendar("Aug 4, 1961"), + new CreateAddress("1600 Pennsylvania Ave", "Washington", "DC", 20500, true), + new CreateAddress("5046 S Greenwood Ave", "Chicago", "IL", 60615, false) + ) + ); + addressBook.createPerson( + new CreatePerson( + "George Walker Bush", + toCalendar("Jul 6, 1946"), + new CreateAddress("43 Prairie Chapel Rd", "Crawford", "TX", 76638, true), + new CreateAddress("1600 Pennsylvania Ave", "Washington", "DC", 20500, false) + ) + ); + + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /** + * [GET /] + * Get root page. + */ + @RestMethod(name="GET", path="/", + converters=Queryable.class + ) + public Link[] getRoot() throws Exception { + return new Link[] { + new Link("people", "people"), + new Link("addresses", "addresses") + }; + } + + /** + * [GET /people/*] + * Get all people in the address book. + * Traversable filtering enabled to allow nodes in returned POJO tree to be addressed. + * Introspectable filtering enabled to allow public methods on the returned object to be invoked. + */ + @RestMethod(name="GET", path="/people/*", + converters={Traversable.class,Queryable.class,Introspectable.class} + ) + public AddressBook getAllPeople() throws Exception { + return addressBook; + } + + /** + * [GET /people/{id}/*] + * Get a single person by ID. + * Traversable filtering enabled to allow nodes in returned POJO tree to be addressed. + * Introspectable filtering enabled to allow public methods on the returned object to be invoked. + */ + @RestMethod(name="GET", path="/people/{id}/*", + converters={Traversable.class,Queryable.class,Introspectable.class} + ) + public Person getPerson(@Path int id) throws Exception { + return findPerson(id); + } + + /** + * [GET /addresses/*] + * Get all addresses in the address book. + */ + @RestMethod(name="GET", path="/addresses/*", + converters={Traversable.class,Queryable.class} + ) + public List<Address> getAllAddresses() throws Exception { + return addressBook.getAddresses(); + } + + /** + * [GET /addresses/{id}/*] + * Get a single address by ID. + */ + @RestMethod(name="GET", path="/addresses/{id}/*", + converters={Traversable.class,Queryable.class} + ) + public Address getAddress(@Path int id) throws Exception { + return findAddress(id); + } + + /** + * [POST /people] + * Create a new Person bean. + */ + @RestMethod(name="POST", path="/people", + guards=AdminGuard.class + ) + public Redirect createPerson(@Body CreatePerson cp) throws Exception { + Person p = addressBook.createPerson(cp); + return new Redirect("people/{0}", p.id); + } + + /** + * [POST /people/{id}/addresses] + * Create a new Address bean. + */ + @RestMethod(name="POST", path="/people/{id}/addresses", + guards=AdminGuard.class + ) + public Redirect createAddress(@Path int id, @Body CreateAddress ca) throws Exception { + Person p = findPerson(id); + Address a = p.createAddress(ca); + return new Redirect("addresses/{0}", a.id); + } + + /** + * [DELETE /people/{id}] + * Delete a Person bean. + */ + @RestMethod(name="DELETE", path="/people/{id}", + guards=AdminGuard.class + ) + public String deletePerson(@Path int id) throws Exception { + addressBook.removePerson(id); + return "DELETE successful"; + } + + /** + * [DELETE /addresses/{id}] + * Delete an Address bean. + */ + @RestMethod(name="DELETE", path="/addresses/{id}", + guards=AdminGuard.class + ) + public String deleteAddress(@Path int addressId) throws Exception { + Person p = addressBook.findPersonWithAddress(addressId); + if (p == null) + throw new RestException(SC_NOT_FOUND, "Person not found"); + Address a = findAddress(addressId); + p.addresses.remove(a); + return "DELETE successful"; + } + + /** + * [PUT /people/{id}/*] + * Change property on Person bean. + */ + @RestMethod(name="PUT", path="/people/{id}/*", + guards=AdminGuard.class + ) + public String updatePerson(RestRequest req, @Path int id) throws Exception { + try { + Person p = findPerson(id); + String pathRemainder = req.getPathRemainder(); + PojoRest r = new PojoRest(p); + ClassMeta<?> cm = r.getClassMeta(pathRemainder); + Object in = req.getBody(cm); + r.put(pathRemainder, in); + return "PUT successful"; + } catch (Exception e) { + throw new RestException(SC_BAD_REQUEST, "PUT unsuccessful").initCause(e); + } + } + + /** + * [PUT /addresses/{id}/*] + * Change property on Address bean. + */ + @RestMethod(name="PUT", path="/addresses/{id}/*", + guards=AdminGuard.class + ) + public String updateAddress(RestRequest req, @Path int id) throws Exception { + try { + Address a = findAddress(id); + String pathInfo = req.getPathInfo(); + PojoRest r = new PojoRest(a); + ClassMeta<?> cm = r.getClassMeta(pathInfo); + Object in = req.getBody(cm); + r.put(pathInfo, in); + return "PUT successful"; + } catch (Exception e) { + throw new RestException(SC_BAD_REQUEST, "PUT unsuccessful").initCause(e); + } + } + + /** + * [INIT /] + * Reinitialize this resource. + */ + @RestMethod(name="INIT", path="/", + guards=AdminGuard.class + ) + public String doInit() throws Exception { + init(); + return "OK"; + } + + /** + * [GET /cognos] + * Get data in Cognos/XML format + */ + @RestMethod(name="GET", path="/cognos") + public DataSet getCognosData() throws Exception { + + // The Cognos metadata + Column[] items = { + new Column("name", "xs:String", 255), + new Column("age", "xs:int"), + new Column("numAddresses", "xs:int") + .addPojoSwap( + new PojoSwap<Person,Integer>() { + @Override /* PojoSwap */ + public Integer swap(BeanSession session, Person p) { + return p.addresses.size(); + } + } + ) + }; + + return new DataSet(items, addressBook, this.getBeanContext().createSession()); + } + + /** + * [OPTIONS /*] + * View resource options + */ + @Override /* RestServletJenaDefault */ + @RestMethod(name="OPTIONS", path="/*") + public Swagger getOptions(RestRequest req) { + return req.getSwagger(); + } + + /** Convenience method - Find a person by ID */ + private Person findPerson(int id) throws RestException { + Person p = addressBook.findPerson(id); + if (p == null) + throw new RestException(SC_NOT_FOUND, "Person not found"); + return p; + } + + /** Convenience method - Find an address by ID */ + private Address findAddress(int id) throws RestException { + Address a = addressBook.findAddress(id); + if (a == null) + throw new RestException(SC_NOT_FOUND, "Address not found"); + return a; + } +} + http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/e3d95284/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/addressbook/ClientTest.java ---------------------------------------------------------------------- diff --git a/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/addressbook/ClientTest.java b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/addressbook/ClientTest.java new file mode 100644 index 0000000..ebf86e9 --- /dev/null +++ b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/addressbook/ClientTest.java @@ -0,0 +1,107 @@ +// *************************************************************************************************************************** +// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file * +// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file * +// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance * +// * with the License. You may obtain a copy of the License at * +// * * +// * http://www.apache.org/licenses/LICENSE-2.0 * +// * * +// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an * +// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * +// * specific language governing permissions and limitations under the License. * +// *************************************************************************************************************************** +package org.apache.juneau.examples.rest.addressbook; + +import java.text.*; +import java.util.*; + +import org.apache.juneau.examples.addressbook.*; +import org.apache.juneau.json.*; +import org.apache.juneau.rest.client.*; +import org.apache.juneau.xml.*; + +/** + * Sample client code for interacting with AddressBookResource + */ +public class ClientTest { + + public static void main(String[] args) { + + try { + System.out.println("Running client test..."); + + // Create a client to handle XML requests and responses. + RestClient client = new RestClient(JsonSerializer.DEFAULT, JsonParser.DEFAULT); + RestClient xmlClient = new RestClient(XmlSerializer.DEFAULT_NS, XmlParser.DEFAULT); + try { + String root = "http://localhost:10000/addressBook"; + + // Get the current contents of the address book + AddressBook ab = client.doGet(root + "/people").getResponse(AddressBook.class); + System.out.println("Number of entries = " + ab.getPeople().size()); + + // Same, but use XML as the protocol both ways + ab = xmlClient.doGet(root + "/people").getResponse(AddressBook.class); + System.out.println("Number of entries = " + ab.getPeople().size()); + + + // Delete the existing entries + for (Person p : ab.getPeople()) { + String r = client.doDelete(p.uri).getResponse(String.class); + System.out.println("Deleted person " + p.name + ", response = " + r); + } + + // Make sure they're gone + ab = client.doGet(root + "/people").getResponse(AddressBook.class); + System.out.println("Number of entries = " + ab.getPeople().size()); + + // Add 1st person again + CreatePerson cp = new CreatePerson( + "Barack Obama", + toCalendar("Aug 4, 1961"), + new CreateAddress("1600 Pennsylvania Ave", "Washington", "DC", 20500, true), + new CreateAddress("5046 S Greenwood Ave", "Chicago", "IL", 60615, false) + ); + Person p = client.doPost(root + "/people", cp).getResponse(Person.class); + System.out.println("Created person " + p.name + ", uri = " + p.uri); + + // Add 2nd person again, but add addresses separately + cp = new CreatePerson( + "George Walker Bush", + toCalendar("Jul 6, 1946") + ); + p = client.doPost(root + "/people", cp).getResponse(Person.class); + System.out.println("Created person " + p.name + ", uri = " + p.uri); + + // Add addresses to 2nd person + CreateAddress ca = new CreateAddress("43 Prairie Chapel Rd", "Crawford", "TX", 76638, true); + Address a = client.doPost(p.uri + "/addresses", ca).getResponse(Address.class); + System.out.println("Created address " + a.uri); + + ca = new CreateAddress("1600 Pennsylvania Ave", "Washington", "DC", 20500, false); + a = client.doPost(p.uri + "/addresses", ca).getResponse(Address.class); + System.out.println("Created address " + a.uri); + + // Find 1st person, and change name + Person[] pp = client.doGet(root + "/people?q=(name='Barack+Obama')").getResponse(Person[].class); + String r = client.doPut(pp[0].uri + "/name", "Barack Hussein Obama").getResponse(String.class); + System.out.println("Changed name, response = " + r); + p = client.doGet(pp[0].uri).getResponse(Person.class); + System.out.println("New name = " + p.name); + } finally { + client.closeQuietly(); + xmlClient.closeQuietly(); + } + + } catch (Exception e) { + e.printStackTrace(); + } + } + + // Utility method + public static Calendar toCalendar(String birthDate) throws Exception { + Calendar c = new GregorianCalendar(); + c.setTime(DateFormat.getDateInstance(DateFormat.MEDIUM).parse(birthDate)); + return c; + } +} http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/e3d95284/juneau-examples-rest/src/main/resources/examples.cfg ---------------------------------------------------------------------- diff --git a/juneau-examples-rest/src/main/resources/examples.cfg b/juneau-examples-rest/src/main/resources/examples.cfg new file mode 100755 index 0000000..758e6b8 --- /dev/null +++ b/juneau-examples-rest/src/main/resources/examples.cfg @@ -0,0 +1,143 @@ +# *************************************************************************************************************************** +# * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file * +# * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file * +# * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance * +# * with the License. You may obtain a copy of the License at * +# * * +# * http://www.apache.org/licenses/LICENSE-2.0 * +# * * +# * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an * +# * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * +# * specific language governing permissions and limitations under the License. * +# *************************************************************************************************************************** + +#================================================================================ +# Basic configuration file for SaaS microservices +# Subprojects can use this as a starting point. +#================================================================================ + +#================================================================================ +# REST settings +#================================================================================ +[REST] + +port = 10000 + +# Authentication: NONE, BASIC. +authType = NONE + +# The BASIC auth username, password, and realm +loginUser = +loginPassword = +authRealm = + +# Stylesheet to use for HTML views. +# The default options are: +# - styles/juneau.css +# - styles/devops.css +# Other stylesheets can be referenced relative to the servlet package or working +# directory. +stylesheet = styles/devops.css + +# What to do when the config file is saved. +# Possible values: +# NOTHING - Don't do anything. +# RESTART_SERVER - Restart the Jetty server. +# RESTART_SERVICE - Shutdown and exit with code '3'. +saveConfigAction = RESTART_SERVER + +# Enable SSL support. +useSsl = false + +#================================================================================ +# Bean properties on the org.eclipse.jetty.util.ssl.SslSocketFactory class +#-------------------------------------------------------------------------------- +# Ignored if REST/useSsl is false. +# Specify any of the following fields: +# allowRenegotiate (boolean) +# certAlias (String) +# crlPath (String) +# enableCRLDP (boolean) +# enableOCSP (boolean) +# excludeCipherSuites (String[]) +# excludeProtocols (String[]) +# includeCipherSuites (String[]) +# includeProtocols (String...) +# keyManagerPassword (String) +# keyStore (String) +# keyStorePassword (String) +# keyStorePath (String) +# keyStoreProvider (String) +# keyStoreType (String) +# maxCertPathLength (int) +# needClientAuth (boolean) +# ocspResponderURL (String) +# protocol (String) +# provider (String) +# secureRandomAlgorithm (String) +# sessionCachingEnabled (boolean) +# sslKeyManagerFactoryAlgorithm (String) +# sslSessionCacheSize (int) +# sslSessionTimeout (int) +# trustAll (boolean) +# trustManagerFactoryAlgorithm (String) +# trustStore (String) +# trustStorePassword (String) +# trustStoreProvider (String) +# trustStoreType (String) +# validateCerts (boolean) +# validatePeerCerts (boolean) +# wantClientAuth (boolean) +#================================================================================ +[REST-SslContextFactory] +keyStorePath = client_keystore.jks +keyStorePassword* = {HRAaRQoT} +excludeCipherSuites = TLS_DHE.*, TLS_EDH.* +excludeProtocols = SSLv3 +allowRenegotiate = false + +#================================================================================ +# Logger settings +# See FileHandler Java class for details. +#================================================================================ +[Logging] +logDir = logs +logFile = sample.%g.log +dateFormat = yyyy.MM.dd hh:mm:ss +format = [{date} {level}] {msg}%n +append = false +limit = 10M +count = 5 +levels = { org.apache.juneau:'INFO' } +useStackTraceHashes = true +consoleLevel = WARNING + +#================================================================================ +# System properties +#-------------------------------------------------------------------------------- +# These are arbitrary system properties that can be set during startup. +#================================================================================ +[SystemProperties] + +# Configure Jetty for StdErrLog Logging +org.eclipse.jetty.util.log.class = org.eclipse.jetty.util.log.StrErrLog + +# Jetty logging level +org.eclipse.jetty.LEVEL = WARN + +#================================================================================ +# DockerRegistryResource properties +#================================================================================ +[DockerRegistry] +url = http://docker.apache.org:5000/v1 + +#================================================================================ +# SqlQueryResource properties +#================================================================================ +[SqlQueryResource] +driver = org.apache.derby.jdbc.EmbeddedDriver +connectionUrl = jdbc:derby:C:/testDB;create=true +allowTempUpdates = true +includeRowNums = true + + http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/e3d95284/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/CodeFormatterResource.html ---------------------------------------------------------------------- diff --git a/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/CodeFormatterResource.html b/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/CodeFormatterResource.html new file mode 100644 index 0000000..90441cf --- /dev/null +++ b/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/CodeFormatterResource.html @@ -0,0 +1,68 @@ +<!DOCTYPE HTML> +<!-- +/*************************************************************************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + ***************************************************************************************************************************/ + --> +<html> +<head> + <style type='text/css'> + @import '$R{servletURI}/style.css'; + </style> + <script> + // Quick and dirty function to allow tabs in textarea. + function checkTab(e) { + if (e.keyCode == 9) { + var t = e.target; + var ss = t.selectionStart, se = t.selectionEnd; + t.value = t.value.slice(0,ss).concat('\t').concat(t.value.slice(ss,t.value.length)); + e.preventDefault(); + } + } + // Load results from IFrame into this document. + function loadResults(buff) { + var doc = buff.contentDocument || buff.contentWindow.document; + var buffBody = doc.getElementById('data'); + if (buffBody != null) { + document.getElementById('results').innerHTML = buffBody.innerHTML; + } + } + </script> +</head> +<body> + <h3 class='title'>Code Formatter</h3> + <div class='data'> + <form id='form' action='codeFormatter' method='POST' target='buff'> + <table> + <tr> + <th>Language: </th> + <td> + <select name='lang'> + <option value='java'>Java</option> + <option value='xml'>XML</option> + </select> + </td> + <td><button type='submit'>Submit</button><button type='reset'>Reset</button></td> + </tr> + <tr> + <td colspan='3'><textarea name='code' style='min-width:800px;min-height:400px;font-family:Courier;font-size:9pt;' onkeydown='checkTab(event)'></textarea></td> + </tr> + </table> + </form> + <div id='results' class='monospace'> + </div> + </div> + <iframe name='buff' style='display:none' onload="parent.loadResults(this)"></iframe> +</body> +</html> + http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/e3d95284/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/SqlQueryResource.html ---------------------------------------------------------------------- diff --git a/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/SqlQueryResource.html b/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/SqlQueryResource.html new file mode 100644 index 0000000..1119400 --- /dev/null +++ b/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/SqlQueryResource.html @@ -0,0 +1,66 @@ +<!DOCTYPE HTML> +<!-- +/*************************************************************************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + ***************************************************************************************************************************/ + --> +<html> +<head> + <style type='text/css'> + @import '$R{servletURI}/style.css'; + </style> + <script> + // Quick and dirty function to allow tabs in textarea. + function checkTab(e) { + if (e.keyCode == 9) { + var t = e.target; + var ss = t.selectionStart, se = t.selectionEnd; + t.value = t.value.slice(0,ss).concat('\t').concat(t.value.slice(ss,t.value.length)); + e.preventDefault(); + } + } + // Load results from IFrame into this document. + function loadResults(b) { + var doc = b.contentDocument || b.contentWindow.document; + var data = doc.getElementById('data') || doc.getElementsByTagName('body')[0]; + document.getElementById('results').innerHTML = data.innerHTML; + } + </script> +</head> +<body> + <h3 class='title'>SQL Query API</h3> + <div class='data'> + <form action='sqlQuery' method='POST' target='buf'> + <table> + <tr> + <th>Position (1-10000):</th> + <td><input name='pos' type='number' value='1'></td> + <th>Limit (1-10000):</th> + <td><input name='limit' type='number' value='100'></td> + <td><button type='submit'>Submit</button><button type='reset'>Reset</button></td> + </tr> + <tr> + <td colspan="5"> + <textarea name='sql' style='width:100%;height:200px;font-family:Courier;font-size:9pt;' onkeydown='checkTab(event)'></textarea> + </td> + </tr> + </table> + </form> + <br> + <div id='results'> + </div> + </div> + <iframe name='buf' style='display:none' onload="parent.loadResults(this)"></iframe> +</body> +</html> + http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/e3d95284/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/TempDirUploadPage.html ---------------------------------------------------------------------- diff --git a/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/TempDirUploadPage.html b/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/TempDirUploadPage.html new file mode 100644 index 0000000..947f8bf --- /dev/null +++ b/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/TempDirUploadPage.html @@ -0,0 +1,34 @@ +<!DOCTYPE HTML> +<!-- +/*************************************************************************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + ***************************************************************************************************************************/ + --> +<html> +<head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> + <style type='text/css'> + @import '$R{servletURI}/style.css'; + </style> +</head> +<body> + <h3 class='title'>$R{servletTitle}</h3> + <h5 class="description">$R{servletDescription}</h5> + <div class='data'> + <form id='form' action='$R{servletURI}/upload' method='POST' target='buff' enctype="multipart/form-data"> + <input name="contents" type="file"><button type="submit">Submit</button> + </form> + </div> +</body> +</html> + http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/e3d95284/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/UrlEncodedForm.html ---------------------------------------------------------------------- diff --git a/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/UrlEncodedForm.html b/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/UrlEncodedForm.html new file mode 100644 index 0000000..0c2d039 --- /dev/null +++ b/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/UrlEncodedForm.html @@ -0,0 +1,62 @@ +<!DOCTYPE HTML> +<!-- +/*************************************************************************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + ***************************************************************************************************************************/ + --> +<html> +<head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> + <style type='text/css'> + @import '$R{servletURI}/style.css'; + </style> + <script type="text/javascript"> + // Load results from IFrame into this document. + function loadResults(buff) { + var doc = buff.contentDocument || buff.contentWindow.document; + var buffBody = doc.getElementById('data'); + document.getElementById('results').innerHTML = buffBody.innerHTML; + } + </script> +</head> +<body> + <h3 class='title'>$R{servletTitle}</h3> + <h5 class="description">$R{servletDescription}</h5> + <div class='data'> + <form id='form' action='$R{servletURI}' method='POST' target='buff'> + <table> + <tr> + <th>$L{aString}</th> + <td><input name="aString" type="text"></td> + </tr> + <tr> + <th>$L{aNumber}</th> + <td><input name="aNumber" type="number"></td> + </tr> + <tr> + <th>$L{aDate}</th> + <td><input name="aDate" type="datetime"> (ISO8601, e.g. "<code>2001-07-04T15:30:45Z</code>")</td> + </tr> + <tr> + <td colspan='2' align='right'><button type="submit">$L{submit}</button></td> + </tr> + </table> + </form> + <br> + <div id='results'> + </div> + </div> + <iframe name='buff' style='display:none' onload="parent.loadResults(this)"></iframe> +</body> +</html> + http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/e3d95284/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/addressbook/nls/AddressBookResource.properties ---------------------------------------------------------------------- diff --git a/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/addressbook/nls/AddressBookResource.properties b/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/addressbook/nls/AddressBookResource.properties new file mode 100644 index 0000000..61aec3e --- /dev/null +++ b/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/addressbook/nls/AddressBookResource.properties @@ -0,0 +1,89 @@ +# *************************************************************************************************************************** +# * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file * +# * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file * +# * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance * +# * with the License. You may obtain a copy of the License at * +# * * +# * http://www.apache.org/licenses/LICENSE-2.0 * +# * * +# * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an * +# * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * +# * specific language governing permissions and limitations under the License. * +# *************************************************************************************************************************** + +title = AddressBook sample resource +description = Proof-of-concept resource that shows off the capabilities of working with POJO resources + +getRoot.summary = Get root page +getRoot.description = Jumping off page for top-level Person and Address beans. + +doInit.summary = Reinitialize this resource +doInit.description = Resets the address book to the original contents. +doInit.res.200.description = Returns the string "OK" + +getAllPeople.summary = Get all people in the address book +getAllPeople.res.200.description = Returns a serialized List<Person> +getAllPeople.res.200.examples = {'text/json':"[\n\t{\n\t\turi:'http://hostname/addressBook/person/1',\n\t\taddressBookUri:'http://localhost/addressBook',\n\t\tid:1,\n\t\tname:'John Smith',\n\t\tbirthDate:'Jan 1, 2000',\n\t\taddresses:[\n\t\t\t{\n\t\t\t\turi:'http://localhost/addressBook/addresses/1',\n\t\t\t\tpersonUri:'http://localhost/addressBook/people/1',\n\t\t\t\tid:1,\n\t\t\t\tstreet:'101 Main St',\n\t\t\t\tcity:'Anywhere',\n\t\t\t\tstate:'NY',\n\t\t\t\tzip:12345,\n\t\t\t\tisCurrent:true\n\t\t\t}\n\t\t]\n\t}\n]"} + +getPerson.summary = Get a single person by ID +getPerson.req.path.id.description = Person ID +getPerson.req.path.id.type = integer +getPerson.res.200.description = Returns a serialized Person bean +getPerson.res.200.examples = {'text/json':"{\n\turi:'http://hostname/addressBook/person/1',\n\taddressBookUri:'http://localhost/addressBook',\n\tid:1,\n\tname:'John Smith',\n\tbirthDate:'Jan 1, 2000',\n\taddresses:[\n\t\t{\n\t\t\turi:'http://localhost/addressBook/addresses/1',\n\t\t\tpersonUri:'http://localhost/addressBook/people/1',\n\t\t\tid:1,\n\t\t\tstreet:'101 Main St',\n\t\t\tcity:'Anywhere',\n\t\t\tstate:'NY',\n\t\t\tzip:12345,\n\t\t\tisCurrent:true\n\t\t}\n\t]\n\}"} +getPerson.res.404.description = Person ID not found + +getAllAddresses.summary = Get all addresses in the address book +getAllAddresses.res.200.description = Returns a serialized List<Address> +getAllAddresses.res.200.examples = {'text/json':"[\n\t{\n\t\turi:'http://localhost/addressBook/addresses/1',\n\t\tpersonUri:'http://localhost/addressBook/people/1',\n\t\tid:1,\n\t\tstreet:'101 Main St',\n\t\tcity:'Anywhere',\n\t\tstate:'NY',\n\t\tzip:12345,\n\t\tisCurrent:true\n\t}\n]"} + +getAddress.summary = Get a single address by ID +getAddress.req.path.id.description = Address ID +getAddress.req.path.id.type = integer +getAddress.res.200.description = Returns a serialized Address bean +getAddress.res.200.examples = {'text/json':"{\n\turi:'http://localhost/addressBook/addresses/1',\n\tpersonUri:'http://localhost/addressBook/people/1',\n\tid:1,\n\tstreet:'101 Main St',\n\tcity:'Anywhere',\n\tstate:'NY',\n\tzip:12345,\n\tisCurrent:true\n}"} +getAddress.res.404.description = Address ID not found + +createPerson.summary = Create a new Person bean +createPerson.req.body.description = Serialized CreatePerson bean +createPerson.req.body.schema = {example:"{\n\tname:'John Smith',\n\tbirthDate:'Jan 1, 2000',\n\taddresses:[\n\t\t{\n\t\t\tstreet:'101 Main St',\n\t\t\tcity:'Anywhere',\n\t\t\tstate:'NY',\n\t\t\tzip:12345,\n\t\t\tisCurrent:true\n\t\t}\n\t]\n\}"} +createPerson.res.307.header.Location.description = URL of new person + +createAddress.summary = Create a new Address bean +createAddress.req.path.id.description = Person ID +createAddress.req.path.id.type = integer +createAddress.req.body.schema = {example:"{\n\tstreet:'101 Main St',\n\tcity:'Anywhere',\n\tstate:'NY',\n\tzip:12345,\n\tisCurrent:true\n}"} +createAddress.res.307.header.Location.description = URL of new address + +deletePerson.summary = Delete a Person bean +deletePerson.req.path.id.description = Person ID +deletePerson.req.path.id.type = integer +deletePerson.res.200.description = Returns the string "DELETE successful" +deletePerson.res.404.description = Person ID not found + +deleteAddress.summary = Delete an Address bean +deleteAddress.req.path.id.description = Address ID +deleteAddress.res.200.description = Returns the string "DELETE successful" +deleteAddress.res.404.description = Address ID not found + +updatePerson.summary = Change property on Person bean +updatePerson.req.path.id.description = Person ID +updatePerson.req.path.id.type = integer +updatePerson.req.body.description = Any object matching the field +updatePerson.res.200.description = Returns the string "PUT successful" +updatePerson.res.400.description = Invalid object type used +updatePerson.res.404.description = Person ID not found + +updateAddress.summary = Change property on Address bean +updateAddress.req.path.id.description = Address ID +updateAddress.req.path.id.type = integer +updateAddress.req.body.description = Any object matching the field +updateAddress.res.200.description = Returns the string "PUT successful" +updateAddress.res.400.description = Invalid object type used +updateAddress.res.404.description = Address ID not found + +getOptions.summary = View resource options + +getCognosData.summary = Get data in Cognos/XML format +getCognosData.res.200.description = Returns a serialized DataSet + +otherNotes = GZip support enabled. Public methods can be invoked by using the &Method URL parameter. 'text/cognos+xml' support available under root resource only \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/e3d95284/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/averycutecat.jpg ---------------------------------------------------------------------- diff --git a/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/averycutecat.jpg b/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/averycutecat.jpg new file mode 100644 index 0000000..9760674 Binary files /dev/null and b/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/averycutecat.jpg differ
