Repository: cxf Updated Branches: refs/heads/master bf6da99ae -> 2156bf58d
CXF-5413: Support Java API for JSON Processing Project: http://git-wip-us.apache.org/repos/asf/cxf/repo Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/2156bf58 Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/2156bf58 Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/2156bf58 Branch: refs/heads/master Commit: 2156bf58d496383900cd964933f09379cf4f8b7a Parents: bf6da99 Author: reta <[email protected]> Authored: Wed Apr 30 12:51:01 2014 -0400 Committer: reta <[email protected]> Committed: Wed Apr 30 12:51:01 2014 -0400 ---------------------------------------------------------------------- parent/pom.xml | 14 ++ rt/rs/extensions/providers/pom.xml | 10 + .../provider/jsr353/JsonJsr353Provider.java | 111 +++++++++++ .../provider/jsr353/JsonJsr353ProviderTest.java | 189 ++++++++++++++++++ systests/jaxrs/pom.xml | 8 + .../apache/cxf/systest/jaxrs/provider/Book.java | 62 ++++++ .../cxf/systest/jaxrs/provider/BookChapter.java | 48 +++++ .../systest/jaxrs/provider/BookJsonStore.java | 127 ++++++++++++ .../jaxrs/provider/JsonJsr353ProviderTest.java | 192 +++++++++++++++++++ 9 files changed, 761 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cxf/blob/2156bf58/parent/pom.xml ---------------------------------------------------------------------- diff --git a/parent/pom.xml b/parent/pom.xml index f980366..e219105 100644 --- a/parent/pom.xml +++ b/parent/pom.xml @@ -160,9 +160,11 @@ <cxf.xpp3.bundle.version>1.1.4c_6</cxf.xpp3.bundle.version> <cxf.validation.api.version>1.1.0.Final</cxf.validation.api.version> <cxf.cdi.api.version>1.1</cxf.cdi.api.version> + <cxf.json.api.version>1.0</cxf.json.api.version> <cxf.jboss.weld.version>2.1.2.Final</cxf.jboss.weld.version> <cxf.osgi.validation.api.version>1.1.0</cxf.osgi.validation.api.version> <cxf.hibernate.validator.version>5.0.2.Final</cxf.hibernate.validator.version> + <cxf.glassfish.json.version>1.0.4</cxf.glassfish.json.version> <cxf.javax.el.version>3.0.0</cxf.javax.el.version> <cxf.hibernate-validator.bundle.version>5.0.2.Final_1</cxf.hibernate-validator.bundle.version> <!-- various OSGi related versions --> @@ -831,6 +833,18 @@ <artifactId>cdi-api</artifactId> <version>${cxf.cdi.api.version}</version> <optional>true</optional> + </dependency> + <dependency> + <groupId>javax.json</groupId> + <artifactId>javax.json-api</artifactId> + <version>${cxf.json.api.version}</version> + <optional>true</optional> + </dependency> + <dependency> + <groupId>org.glassfish</groupId> + <artifactId>javax.json</artifactId> + <version>${cxf.glassfish.json.version}</version> + <optional>true</optional> </dependency> <dependency> <groupId>org.slf4j</groupId> http://git-wip-us.apache.org/repos/asf/cxf/blob/2156bf58/rt/rs/extensions/providers/pom.xml ---------------------------------------------------------------------- diff --git a/rt/rs/extensions/providers/pom.xml b/rt/rs/extensions/providers/pom.xml index cfa5df7..c1feea8 100644 --- a/rt/rs/extensions/providers/pom.xml +++ b/rt/rs/extensions/providers/pom.xml @@ -103,6 +103,16 @@ <optional>true</optional> </dependency> <dependency> + <groupId>javax.json</groupId> + <artifactId>javax.json-api</artifactId> + <optional>true</optional> + </dependency> + <dependency> + <groupId>org.glassfish</groupId> + <artifactId>javax.json</artifactId> + <optional>true</optional> + </dependency> + <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-bindings-soap</artifactId> <version>${project.version}</version> http://git-wip-us.apache.org/repos/asf/cxf/blob/2156bf58/rt/rs/extensions/providers/src/main/java/org/apache/cxf/jaxrs/provider/jsr353/JsonJsr353Provider.java ---------------------------------------------------------------------- diff --git a/rt/rs/extensions/providers/src/main/java/org/apache/cxf/jaxrs/provider/jsr353/JsonJsr353Provider.java b/rt/rs/extensions/providers/src/main/java/org/apache/cxf/jaxrs/provider/jsr353/JsonJsr353Provider.java new file mode 100644 index 0000000..26ef3ed --- /dev/null +++ b/rt/rs/extensions/providers/src/main/java/org/apache/cxf/jaxrs/provider/jsr353/JsonJsr353Provider.java @@ -0,0 +1,111 @@ +/** + * 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.cxf.jaxrs.provider.jsr353; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; + +import javax.json.Json; +import javax.json.JsonArray; +import javax.json.JsonException; +import javax.json.JsonObject; +import javax.json.JsonReader; +import javax.json.JsonStructure; +import javax.json.JsonWriter; +import javax.ws.rs.Consumes; +import javax.ws.rs.Produces; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.ext.MessageBodyReader; +import javax.ws.rs.ext.MessageBodyWriter; +import javax.ws.rs.ext.Provider; + +import org.apache.cxf.jaxrs.utils.ExceptionUtils; + +@Produces({"application/json", "application/*+json" }) +@Consumes({"application/json", "application/*+json" }) +@Provider +public class JsonJsr353Provider implements MessageBodyReader<JsonStructure>, MessageBodyWriter<JsonStructure> { + @Override + public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) { + return JsonStructure.class.isAssignableFrom(type) + || JsonObject.class.isAssignableFrom(type) + || JsonArray.class.isAssignableFrom(type); + } + + @Override + public long getSize(JsonStructure t, Class<?> type, Type genericType, Annotation[] annotations, + MediaType mediaType) { + + return -1; + } + + @Override + public void writeTo(JsonStructure t, Class<?> type, Type genericType, Annotation[] annotations, + MediaType mediaType, MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream) + throws IOException, WebApplicationException { + + if (entityStream == null) { + throw new IOException("Initialized OutputStream should be provided"); + } + + JsonWriter writer = null; + try { + writer = Json.createWriter(entityStream); + writer.write(t); + } finally { + if (writer != null) { + writer.close(); + } + } + } + + @Override + public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) { + return JsonStructure.class.isAssignableFrom(type) + || JsonObject.class.isAssignableFrom(type) + || JsonArray.class.isAssignableFrom(type); + } + + @Override + public JsonStructure readFrom(Class<JsonStructure> type, Type genericType, Annotation[] annotations, + MediaType mediaType, MultivaluedMap<String, String> httpHeaders, InputStream entityStream) + throws IOException, WebApplicationException { + + if (entityStream == null) { + throw new IOException("Initialized InputStream should be provided"); + } + + JsonReader reader = null; + try { + reader = Json.createReader(entityStream); + return reader.read(); + } catch (JsonException ex) { + throw ExceptionUtils.toBadRequestException(ex, null); + } finally { + if (reader != null) { + reader.close(); + } + } + } +} http://git-wip-us.apache.org/repos/asf/cxf/blob/2156bf58/rt/rs/extensions/providers/src/test/java/org/apache/cxf/jaxrs/provider/jsr353/JsonJsr353ProviderTest.java ---------------------------------------------------------------------- diff --git a/rt/rs/extensions/providers/src/test/java/org/apache/cxf/jaxrs/provider/jsr353/JsonJsr353ProviderTest.java b/rt/rs/extensions/providers/src/test/java/org/apache/cxf/jaxrs/provider/jsr353/JsonJsr353ProviderTest.java new file mode 100644 index 0000000..355e33b --- /dev/null +++ b/rt/rs/extensions/providers/src/test/java/org/apache/cxf/jaxrs/provider/jsr353/JsonJsr353ProviderTest.java @@ -0,0 +1,189 @@ +/** + * 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.cxf.jaxrs.provider.jsr353; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.StringWriter; + +import javax.json.Json; +import javax.json.JsonArray; +import javax.json.JsonObject; +import javax.json.JsonStructure; +import javax.json.JsonValue; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.Response; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.instanceOf; + +public class JsonJsr353ProviderTest extends Assert { + private JsonJsr353Provider provider; + + @Before + public void setUp() { + provider = new JsonJsr353Provider(); + } + + @Test(expected = IOException.class) + public void testReadWithNullStream() throws Exception { + provider.readFrom(JsonStructure.class, null, null, null, null, null); + } + + @Test + public void testGetSizeReturnsMinusOne() throws Exception { + assertThat(provider.getSize(null, JsonStructure.class, null, null, null), + equalTo(-1L)); + } + + @Test + public void testReadableTypes() throws Exception { + assertThat(provider.isReadable(JsonArray.class, null, null, null), + equalTo(true)); + assertThat(provider.isReadable(JsonStructure.class, null, null, null), + equalTo(true)); + assertThat(provider.isReadable(JsonObject.class, null, null, null), + equalTo(true)); + assertThat(provider.isReadable(JsonValue.class, null, null, null), + equalTo(false)); + } + + @Test + public void testWritableTypes() throws Exception { + assertThat(provider.isWriteable(JsonArray.class, null, null, null), + equalTo(true)); + assertThat(provider.isWriteable(JsonStructure.class, null, null, null), + equalTo(true)); + assertThat(provider.isWriteable(JsonObject.class, null, null, null), + equalTo(true)); + assertThat(provider.isWriteable(JsonValue.class, null, null, null), + equalTo(false)); + } + + @Test(expected = IOException.class) + public void testWriteWithNullStream() throws Exception { + final JsonObject obj = Json.createObjectBuilder() + .add("firstName", "Tom") + .add("lastName", "Tommyknocker") + .build(); + + provider.writeTo(obj, JsonObject.class, null, null, null, null, null); + } + + @Test + public void testReadMalformedJson() throws Exception { + byte[] bytes = "junk".getBytes(); + + try { + provider.readFrom(JsonStructure.class, null, null, null, null, + new ByteArrayInputStream(bytes)); + fail("400 BAD REQUEST is expected"); + } catch (WebApplicationException ex) { + assertThat(ex.getResponse().getStatus(), + equalTo(Response.Status.BAD_REQUEST.getStatusCode())); + } + } + + @Test + public void testReadJsonObject() throws Exception { + final StringWriter writer = new StringWriter(); + + Json.createGenerator(writer) + .writeStartObject() + .write("firstName", "Tom") + .write("lastName", "Tommyknocker") + .writeEnd() + .close(); + + final String str = writer.toString(); + writer.close(); + + final JsonStructure obj = provider.readFrom(JsonStructure.class, null, null, null, null, + new ByteArrayInputStream(str.getBytes())); + + assertThat(obj, instanceOf(JsonObject.class)); + assertThat(((JsonObject)obj).getString("firstName"), equalTo("Tom")); + assertThat(((JsonObject)obj).getString("lastName"), equalTo("Tommyknocker")); + } + + @Test + public void testReadJsonArray() throws Exception { + final StringWriter writer = new StringWriter(); + + Json.createGenerator(writer) + .writeStartArray() + .write("Tom") + .write("Tommyknocker") + .writeEnd() + .close(); + + final JsonStructure obj = provider.readFrom(JsonStructure.class, null, null, null, null, + new ByteArrayInputStream(writer.toString().getBytes())); + + assertThat(obj, instanceOf(JsonArray.class)); + assertThat(((JsonArray)obj).getString(0), equalTo("Tom")); + assertThat(((JsonArray)obj).getString(1), equalTo("Tommyknocker")); + assertThat(((JsonArray)obj).size(), equalTo(2)); + } + + @Test + public void testWriteJsonObject() throws Exception { + final JsonObject obj = Json.createObjectBuilder() + .add("firstName", "Tom") + .add("lastName", "Tommyknocker") + .build(); + + final ByteArrayOutputStream out = new ByteArrayOutputStream(); + provider.writeTo(obj, JsonStructure.class, null, null, null, null, out); + out.close(); + + assertThat(new String(out.toByteArray()), + equalTo("{\"firstName\":\"Tom\",\"lastName\":\"Tommyknocker\"}")); + } + + @Test + public void testWriteJsonArray() throws Exception { + final JsonArray obj = Json.createArrayBuilder() + .add( + Json.createObjectBuilder() + .add("firstName", "Tom") + .add("lastName", "Tommyknocker") + ) + .add( + Json.createObjectBuilder() + .add("firstName", "Bob") + .add("lastName", "Bobbyknocker") + ) + .build(); + + final ByteArrayOutputStream out = new ByteArrayOutputStream(); + provider.writeTo(obj, JsonStructure.class, null, null, null, null, out); + out.close(); + + assertThat(new String(out.toByteArray()), + equalTo("[{\"firstName\":\"Tom\",\"lastName\":\"Tommyknocker\"}," + + "{\"firstName\":\"Bob\",\"lastName\":\"Bobbyknocker\"}]")); + } + +} http://git-wip-us.apache.org/repos/asf/cxf/blob/2156bf58/systests/jaxrs/pom.xml ---------------------------------------------------------------------- diff --git a/systests/jaxrs/pom.xml b/systests/jaxrs/pom.xml index e453479..7e951ec 100644 --- a/systests/jaxrs/pom.xml +++ b/systests/jaxrs/pom.xml @@ -47,6 +47,14 @@ <artifactId>hibernate-validator</artifactId> <version>${cxf.hibernate.validator.version}</version> </dependency> + <dependency> + <groupId>javax.json</groupId> + <artifactId>javax.json-api</artifactId> + </dependency> + <dependency> + <groupId>org.glassfish</groupId> + <artifactId>javax.json</artifactId> + </dependency> <!-- <dependency> <groupId>org.apache.bval</groupId> http://git-wip-us.apache.org/repos/asf/cxf/blob/2156bf58/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/provider/Book.java ---------------------------------------------------------------------- diff --git a/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/provider/Book.java b/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/provider/Book.java new file mode 100644 index 0000000..5c2bfcc --- /dev/null +++ b/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/provider/Book.java @@ -0,0 +1,62 @@ +/** + * 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.cxf.systest.jaxrs.provider; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +public class Book { + private String name; + private long id; + private Map<Long, BookChapter> chapters = new HashMap<Long, BookChapter>(); + + public Book() { + } + + public Book(String name, long id) { + this.setName(name); + this.setId(id); + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public void addChapter(long chapterId, String title) { + chapters.put(chapterId, new BookChapter(chapterId, title)); + } + + public Collection<BookChapter> getChapters() { + return chapters.values(); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/cxf/blob/2156bf58/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/provider/BookChapter.java ---------------------------------------------------------------------- diff --git a/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/provider/BookChapter.java b/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/provider/BookChapter.java new file mode 100644 index 0000000..0d8e72f --- /dev/null +++ b/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/provider/BookChapter.java @@ -0,0 +1,48 @@ +/** + * 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.cxf.systest.jaxrs.provider; + +public class BookChapter { + private String title; + private long id; + + public BookChapter() { + } + + public BookChapter(long id, String title) { + this.id = id; + this.title = title; + } + + public void setTitle(String n) { + title = n; + } + + public String getTitle() { + return title; + } + + public void setId(long i) { + id = i; + } + public long getId() { + return id; + } +} http://git-wip-us.apache.org/repos/asf/cxf/blob/2156bf58/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/provider/BookJsonStore.java ---------------------------------------------------------------------- diff --git a/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/provider/BookJsonStore.java b/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/provider/BookJsonStore.java new file mode 100644 index 0000000..9d44cc6 --- /dev/null +++ b/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/provider/BookJsonStore.java @@ -0,0 +1,127 @@ +/** + * 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.cxf.systest.jaxrs.provider; + +import java.util.HashMap; +import java.util.Map; + +import javax.json.Json; +import javax.json.JsonArray; +import javax.json.JsonArrayBuilder; +import javax.json.JsonObject; +import javax.json.JsonObjectBuilder; +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; + +@Path("/bookstore/") +public class BookJsonStore { + private Map< Long, Book > books = new HashMap< Long, Book >(); + + @GET + @Path("/books/{bookId}") + @Produces(MediaType.APPLICATION_JSON) + public JsonObject getBook(@PathParam("bookId") Long id) { + final Book book = books.get(id); + + if (book == null) { + return null; + } + + return bookToJson(book); + } + + @GET + @Path("/books") + @Produces(MediaType.APPLICATION_JSON) + public JsonArray getBooks() { + final JsonArrayBuilder builder = Json.createArrayBuilder(); + + for (final Book book: books.values()) { + builder.add(bookToJson(book)); + } + + return builder.build(); + } + + @POST + @Path("/books") + @Consumes(MediaType.APPLICATION_JSON) + public Response addBook(@Context final UriInfo uriInfo, JsonObject obj) { + final Book book = bookFromJson(obj); + books.put(book.getId(), book); + + return Response.created( + uriInfo + .getRequestUriBuilder() + .path(Long.toString(book.getId())) + .build()).build(); + } + + @DELETE + @Path("/books") + public Response deleteAll() { + books.clear(); + return Response.ok().build(); + } + + private JsonObject bookToJson(final Book book) { + final JsonObjectBuilder builder = Json + .createObjectBuilder() + .add("id", book.getId()) + .add("name", book.getName()); + + if (!book.getChapters().isEmpty()) { + final JsonArrayBuilder chapters = Json.createArrayBuilder(); + + for (final BookChapter chapter: book.getChapters()) { + chapters.add(Json.createObjectBuilder() + .add("id", chapter.getId()) + .add("title", chapter.getTitle()) + ); + } + + builder.add("chapters", chapters); + } + + return builder.build(); + } + + private Book bookFromJson(JsonObject obj) { + final Book book = new Book(obj.getString("name"), obj.getInt("id")); + final JsonArray chapters = (JsonArray)obj.get("chapters"); + if (chapters != null && !chapters.isEmpty()) { + for (final JsonObject chapter: chapters.getValuesAs(JsonObject.class)) { + book.addChapter(chapter.getInt("id"), chapter.getString("title")); + } + } + + return book; + } + +} http://git-wip-us.apache.org/repos/asf/cxf/blob/2156bf58/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/provider/JsonJsr353ProviderTest.java ---------------------------------------------------------------------- diff --git a/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/provider/JsonJsr353ProviderTest.java b/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/provider/JsonJsr353ProviderTest.java new file mode 100644 index 0000000..d0e7d1a --- /dev/null +++ b/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/provider/JsonJsr353ProviderTest.java @@ -0,0 +1,192 @@ +/** + * 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.cxf.systest.jaxrs.provider; + +import java.util.Arrays; + +import javax.json.Json; +import javax.json.JsonArray; +import javax.json.JsonObject; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; + +import org.apache.cxf.jaxrs.JAXRSServerFactoryBean; +import org.apache.cxf.jaxrs.client.WebClient; +import org.apache.cxf.jaxrs.lifecycle.SingletonResourceProvider; +import org.apache.cxf.jaxrs.model.AbstractResourceInfo; +import org.apache.cxf.jaxrs.provider.jsr353.JsonJsr353Provider; +import org.apache.cxf.testutil.common.AbstractBusClientServerTestBase; +import org.apache.cxf.testutil.common.AbstractBusTestServerBase; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Ignore; +import org.junit.Test; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.instanceOf; +import static org.hamcrest.core.IsNull.nullValue; + + +public class JsonJsr353ProviderTest extends AbstractBusClientServerTestBase { + public static final String PORT = allocatePort(JsonJsr353ProviderTest.class); + + @Ignore + public static class Server extends AbstractBusTestServerBase { + protected void run() { + final JAXRSServerFactoryBean sf = new JAXRSServerFactoryBean(); + sf.setResourceClasses(BookJsonStore.class); + sf.setResourceProvider(BookJsonStore.class, + new SingletonResourceProvider(new BookJsonStore())); + sf.setProvider(new JsonJsr353Provider()); + sf.setAddress("http://localhost:" + PORT + "/"); + sf.create(); + } + + public static void main(String[] args) { + try { + Server s = new Server(); + s.start(); + } catch (Exception ex) { + ex.printStackTrace(); + System.exit(-1); + } finally { + System.out.println("done!"); + } + } + } + + @BeforeClass + public static void startServers() throws Exception { + AbstractResourceInfo.clearAllMaps(); + //keep out of process due to stack traces testing failures + assertTrue("server did not launch correctly", launchServer(Server.class, true)); + createStaticBus(); + } + + @Before + public void setUp() { + final Response r = createWebClient("/bookstore/books").delete(); + assertEquals(Status.OK.getStatusCode(), r.getStatus()); + } + + @Test + public void testNoResultsAreReturned() throws Exception { + final Response r = createWebClient("/bookstore/books/155").get(); + assertEquals(Status.NO_CONTENT.getStatusCode(), r.getStatus()); + } + + @Test + public void testPostSimpleJsonObject() { + final Response r = createWebClient("/bookstore/books") + .header("Content-Type", MediaType.APPLICATION_JSON) + .post( + Json + .createObjectBuilder() + .add("id", 1) + .add("name", "Book 1") + .build() + ); + assertEquals(Status.CREATED.getStatusCode(), r.getStatus()); + } + + @Test + public void testPostComplexJsonObject() { + final Response r = createWebClient("/bookstore/books") + .header("Content-Type", MediaType.APPLICATION_JSON) + .post( + Json + .createObjectBuilder() + .add("id", 1) + .add("name", "Book 1") + .add("chapters", + Json.createArrayBuilder() + .add( + Json.createObjectBuilder() + .add("id", 1) + .add("title", "Chapter 1") + ) + .add( + Json.createObjectBuilder() + .add("id", 2) + .add("title", "Chapter 2") + ) + ) + .build() + ); + assertEquals(Status.CREATED.getStatusCode(), r.getStatus()); + } + + @Test + public void testPostAndGetSimpleJsonObject() { + testPostSimpleJsonObject(); + + final Response r = createWebClient("/bookstore/books/1").get(); + assertEquals(Status.OK.getStatusCode(), r.getStatus()); + + JsonObject obj = r.readEntity(JsonObject.class); + assertThat(obj.getInt("id"), equalTo(1)); + assertThat(obj.getString("name"), equalTo("Book 1")); + assertThat(obj.get("chapters"), nullValue()); + } + + @Test + public void testPostAndGetComplexJsonObject() { + testPostComplexJsonObject(); + + final Response r = createWebClient("/bookstore/books/1").get(); + assertEquals(Status.OK.getStatusCode(), r.getStatus()); + + JsonObject obj = r.readEntity(JsonObject.class); + assertThat(obj.getInt("id"), equalTo(1)); + assertThat(obj.getString("name"), equalTo("Book 1")); + assertThat(obj.get("chapters"), instanceOf(JsonArray.class)); + + final JsonArray chapters = (JsonArray)obj.get("chapters"); + assertThat(chapters.size(), equalTo(2)); + assertThat(((JsonObject)chapters.get(0)).getInt("id"), equalTo(1)); + assertThat(((JsonObject)chapters.get(0)).getString("title"), equalTo("Chapter 1")); + assertThat(((JsonObject)chapters.get(1)).getInt("id"), equalTo(2)); + assertThat(((JsonObject)chapters.get(1)).getString("title"), equalTo("Chapter 2")); + } + + @Test + public void testPostAndGetBooks() { + testPostSimpleJsonObject(); + + final Response r = createWebClient("/bookstore/books").get(); + assertEquals(Status.OK.getStatusCode(), r.getStatus()); + + final JsonArray obj = r.readEntity(JsonArray.class); + assertThat(obj.size(), equalTo(1)); + assertThat(obj.get(0), instanceOf(JsonObject.class)); + + assertThat(((JsonObject)obj.get(0)).getInt("id"), equalTo(1)); + assertThat(((JsonObject)obj.get(0)).getString("name"), equalTo("Book 1")); + } + + private static WebClient createWebClient(final String url) { + return WebClient + .create("http://localhost:" + PORT + url, + Arrays.< Object >asList(new JsonJsr353Provider())) + .accept(MediaType.APPLICATION_JSON); + } + +}
