2 * This document is a part of the source code and related artifacts
3 * for CollectionSpace, an open source collections management system
4 * for museums and related institutions:
6 * http://www.collectionspace.org
7 * http://wiki.collectionspace.org
9 * Copyright © 2009 Regents of the University of California
11 * Licensed under the Educational Community License (ECL), Version 2.0.
12 * You may not use this file except in compliance with this License.
14 * You may obtain a copy of the ECL 2.0 License at
15 * https://source.collectionspace.org/collection-space/LICENSE.txt
17 * Unless required by applicable law or agreed to in writing, software
18 * distributed under the License is distributed on an "AS IS" BASIS,
19 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 * See the License for the specific language governing permissions and
21 * limitations under the License.
24 package org.collectionspace.services.client.test;
26 import java.util.ArrayList;
27 import java.util.List;
28 import javax.ws.rs.core.MultivaluedMap;
29 import javax.ws.rs.core.Response;
30 import javax.xml.bind.JAXBContext;
31 import javax.xml.bind.Marshaller;
32 import org.jboss.resteasy.client.ClientResponse;
33 import org.testng.Assert;
34 import org.testng.annotations.Test;
36 import org.collectionspace.services.client.CollectionObjectClient;
37 import org.collectionspace.services.collectionobject.CollectionObject;
38 import org.collectionspace.services.collectionobject.CollectionObjectList;
40 import java.io.IOException;
41 import java.io.UnsupportedEncodingException;
42 import javax.ws.rs.core.MediaType;
43 import javax.ws.rs.core.Response.Status;
44 // import org.jboss.resteasy.client.ClientRequest;
45 import org.collectionspace.services.client.TestServiceClient;
46 import org.apache.commons.httpclient.Header;
47 import org.apache.commons.httpclient.HttpClient;
48 import org.apache.commons.httpclient.HttpException;
49 import org.apache.commons.httpclient.HttpMethod;
50 import org.apache.commons.httpclient.HttpStatus;
51 import org.apache.commons.httpclient.methods.EntityEnclosingMethod;
52 import org.apache.commons.httpclient.methods.GetMethod;
53 import org.apache.commons.httpclient.methods.PostMethod;
54 import org.apache.commons.httpclient.methods.PutMethod;
55 import org.apache.commons.httpclient.methods.RequestEntity;
56 import org.apache.commons.httpclient.methods.StringRequestEntity;
58 import org.slf4j.Logger;
59 import org.slf4j.LoggerFactory;
62 * CollectionObjectServiceTest, carries out tests against a
63 * deployed and running CollectionObject Service.
65 * $LastChangedRevision$
68 public class CollectionObjectServiceTest {
70 // Instance variables specific to this test.
71 final Logger logger = LoggerFactory.getLogger(CollectionObjectServiceTest.class);
72 private CollectionObjectClient client = new CollectionObjectClient();
74 // Instance variables common to all entity service test classes.
75 private String knownObjectId = null;
76 private final String NON_EXISTENT_ID = createNonExistentIdentifier();
77 private HttpClient httpClient = new HttpClient();
78 private TestServiceClient serviceClient = new TestServiceClient();
81 // ---------------------------------------------------------------
82 // Service Discovery tests
83 // ---------------------------------------------------------------
88 // ---------------------------------------------------------------
89 // CRUD tests : CREATE tests
90 // ---------------------------------------------------------------
96 * Tests creation of a new object of the specified type.
98 * The 'Location' header will contain the URL for the newly created object.
99 * This is required by the extractId() utility method, below.
101 * The newly-created object is also used by other test(s)
102 * (e.g. update, delete) which follow, below.
105 public void create() {
107 // Expected status code: 201 Created
108 final int EXPECTED_STATUS_CODE = Response.Status.CREATED.getStatusCode();
110 String identifier = this.createIdentifier();
112 CollectionObject collectionObject = createCollectionObject(identifier);
113 ClientResponse<Response> res = client.createCollectionObject(collectionObject);
114 verbose("create: status = " + res.getStatus());
115 Assert.assertEquals(res.getStatus(), EXPECTED_STATUS_CODE);
117 // Store the ID returned from this create operation for additional tests below.
118 knownObjectId = extractId(res);
122 * Creates two or more new objects of the specified type.
124 * Repeatedly calls the create test, above, and relies on its
127 * The newly-created objects are also used by other test(s)
128 * (e.g. read multiple/list) which follow, below.
130 @Test(dependsOnMethods = {"create"})
131 public void createMultiple() {
132 for(int i = 0; i < 3; i++){
141 * Tests creation of an object of the specified type by sending a null to the client proxy.
144 @Test(dependsOnMethods = {"create"}, expectedExceptions = IllegalArgumentException.class)
145 public void createNull() {
147 // Expected result: IllegalArgumentException
148 ClientResponse<Response> res = client.createCollectionObject(null);
152 * Tests the HttpClient-based code used to submit data, in various methods below.
154 @Test(dependsOnMethods = {"create", "read"})
155 public void testSubmitRequest() {
157 // Expected status code: 200 OK
158 final int EXPECTED_STATUS_CODE = Response.Status.OK.getStatusCode();
160 String url = getResourceURL(knownObjectId);
161 GetMethod method = new GetMethod(url);
163 int statusCode = submitRequest(method);
164 verbose("testSubmitRequest: url=" + url + " status=" + statusCode);
166 // Evaluate the status code in the response.
167 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE,
168 "expected " + EXPECTED_STATUS_CODE);
173 * Tests creation of an object of the specified type by sending malformed XML data
174 * in the entity body of the request.
177 @Test(dependsOnMethods = {"create", "testSubmitRequest"})
178 public void createWithMalformedXml() {
180 // Expected status code: 400 Bad Request
181 final int EXPECTED_STATUS_CODE = Response.Status.BAD_REQUEST.getStatusCode();
183 // @TODO This test is currently commented out, because it returns a
184 // 500 Internal Server Error status code, rather than the expected status code.
186 String url = getServiceRootURL();
187 PostMethod method = new PostMethod(url);
188 // Note missing final angle bracket in text below.
189 final String MALFORMED_XML_DATA = "<malformed_xml>wrong schema contents</malformed_xml";
191 // Prepare the entity body of the request.
192 StringRequestEntity entity = getXmlEntity(MALFORMED_XML_DATA);
194 // Submit the request.
195 int statusCode = submitRequest(method, entity);
196 verbose("createWithMalformedXml url=" + url + " status=" + statusCode);
198 // Evaluate the status code in the response.
199 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE,
200 "expected " + EXPECTED_STATUS_CODE);
205 * Tests creation of an object of the specified type by sending data
206 * in the wrong schema (e.g. in a format that doesn't match the object's schema)
207 * in the entity body of the request.
210 @Test(dependsOnMethods = {"create", "testSubmitRequest", "createWithMalformedXml"})
211 public void createWithWrongSchema() {
213 // Expected status code: 400 Bad Request
214 final int EXPECTED_STATUS_CODE = Response.Status.BAD_REQUEST.getStatusCode();
216 // @TODO This test is currently commented out, because it returns a
217 // 500 Internal Server Error status code, rather than the expected status code.
219 String url = getServiceRootURL();
220 PostMethod method = new PostMethod(url);
222 // Prepare the entity body of the request.
223 final String WRONG_SCHEMA_DATA = "<wrong_schema>wrong schema contents</wrong_schema>";
224 StringRequestEntity entity = getXmlEntity(WRONG_SCHEMA_DATA);
226 // Submit the request.
227 int statusCode = submitRequest(method, entity);
228 verbose("createWithWrongSchema url=" + url + " status=" + statusCode);
230 // Evaluate the status code in the response.
231 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE,
232 "expected " + EXPECTED_STATUS_CODE);
238 * Tests creation of an object of the specified type,
239 * by a user who is not authorized to perform this action.
242 @Test(dependsOnMethods = {"create"})
243 public void createWithoutAuthorization() {
245 // Expected status code: 403 Forbidden
246 final int EXPECTED_STATUS_CODE = Response.Status.FORBIDDEN.getStatusCode();
248 // @TODO Currently only a stub. This test can be implemented
249 // when the service is revised to require authorization.
254 * Tests creation of a duplicate object of the specified type,
255 * whose unique resource identifier duplicates that of an existing object.
258 @Test(dependsOnMethods = {"create"})
259 public void createDuplicate() {
261 // Expected status code: 409 Conflict
262 final int EXPECTED_STATUS_CODE = Response.Status.CONFLICT.getStatusCode();
264 // @TODO This test is currently commented out because our current
265 // services do not appear to permit creation of duplicate records.
266 // Please see below for more details.
268 // Note: there doesn't appear to be a way to create a duplicate
269 // resource (object) by POSTing:
271 // 1. We can't POST to a specific resource by ID; that returns a
272 // response with a 405 Method Not Allowed status code.
274 // 2. If we POST to the container in which new resources are created,
275 // it doesn't appear that we can specify the CSID that the newly-created
276 // resource (object) will receive.
278 // If the two points above are accurate, this test is thus unneeded, until
279 // and unless, in our service(s), we begin detecting duplicates via a
280 // technique that isn't dependent on CSIDs; for instance, by checking for
281 // duplicate data in other information units (fields) whose values must be unique.
283 // One possible example: checking for duplicate Accession numbers in
284 // the "Object entry" information unit.
288 // ---------------------------------------------------------------
289 // CRUD tests : READ tests
290 // ---------------------------------------------------------------
296 * Tests reading (i.e. retrieval) of an object of the specified type.
298 @Test(dependsOnMethods = {"create"})
301 // Expected status code: 200 OK
302 final int EXPECTED_STATUS_CODE = Response.Status.OK.getStatusCode();
304 ClientResponse<CollectionObject> res =
305 client.getCollectionObject(knownObjectId);
306 verbose("read: status = " + res.getStatus());
307 Assert.assertEquals(res.getStatus(), EXPECTED_STATUS_CODE);
314 * Tests reading (i.e. retrieval) of an object of the specified type by a user who
315 * is not authorized to perform this action.
318 @Test(dependsOnMethods = {"read"})
319 public void readWithoutAuthorization() {
321 // Expected status code: 403 Forbidden
322 final int EXPECTED_STATUS_CODE = Response.Status.FORBIDDEN.getStatusCode();
324 // @TODO Currently only a stub. This test can be implemented
325 // when the service is revised to require authorization.
330 * Tests reading (i.e. retrieval) of a non-existent object of the specified type,
331 * whose resource identifier does not exist at the specified URL.
333 @Test(dependsOnMethods = {"read"})
334 public void readNonExistent() {
336 // Expected status code: 404 Not Found
337 final int EXPECTED_STATUS_CODE = Response.Status.NOT_FOUND.getStatusCode();
339 ClientResponse<CollectionObject> res =
340 client.getCollectionObject(NON_EXISTENT_ID);
341 verbose("readNonExistent: status = " + res.getStatus());
342 Assert.assertEquals(res.getStatus(), EXPECTED_STATUS_CODE);
346 // ---------------------------------------------------------------
347 // CRUD tests : READ (list, or multiple) tests
348 // ---------------------------------------------------------------
354 * Tests reading (i.e. retrieval) of a list of multiple objects of the specified type.
356 * Also expected: The entity body in the response contains
357 * a representation of a list of objects of the specified type.
359 @Test(dependsOnMethods = {"createMultiple"})
360 public void readList() {
362 // Expected status code: 200 OK
363 final int EXPECTED_STATUS_CODE = Response.Status.OK.getStatusCode();
365 // The 'read' method is expected to return at least an empty list.
366 ClientResponse<CollectionObjectList> res = client.getCollectionObjectList();
367 CollectionObjectList coList = res.getEntity();
368 verbose("readList: status = " + res.getStatus());
369 Assert.assertEquals(res.getStatus(), EXPECTED_STATUS_CODE);
371 if (logger.isDebugEnabled()) {
372 List<CollectionObjectList.CollectionObjectListItem> coItemList =
373 coList.getCollectionObjectListItem();
375 for(CollectionObjectList.CollectionObjectListItem pli : coItemList){
376 verbose("readList: list-item[" + i + "] csid=" + pli.getCsid());
377 verbose("readList: list-item[" + i + "] objectNumber=" + pli.getObjectNumber());
378 verbose("readList: list-item[" + i + "] URI=" + pli.getUri());
386 * Tests reading (i.e. retrieval) of a list of multiple objects of the specified type
387 * when the contents of the list are expected to be empty.
389 * Also expected: The entity body in the response contains
390 * a representation of an empty list of objects of the specified type.
393 @Test(dependsOnMethods = {"readList"})
394 public void readEmptyList() {
396 // Expected status code: 200 OK
397 // (NOTE: *not* 204 No Content)
398 final int EXPECTED_STATUS_CODE = Response.Status.OK.getStatusCode();
400 // @TODO Currently only a stub.
408 * Tests reading (i.e. retrieval) of a list of objects of the specified type
409 * when sending unrecognized query parameters with the request.
412 @Test(dependsOnMethods = {"readList"})
413 public void readListWithBadParams() {
415 // Expected status code: 400 Bad Request
416 final int EXPECTED_STATUS_CODE = Response.Status.BAD_REQUEST.getStatusCode();
418 // @TODO This test is currently commented out, because it returns a
419 // 200 OK status code, rather than the expected status code.
421 // @TODO Another variant of this test should use a URL for the service
422 // root that ends in a trailing slash.
424 String url = getServiceRootURL() + "?param=nonexistent";
425 GetMethod method = new GetMethod(url);
427 // Submit the request.
428 int statusCode = submitRequest(method);
429 verbose("readListWithBadParams: url=" + url + " status=" + statusCode);
431 // Evaluate the status code in the response.
432 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE,
433 "expected " + EXPECTED_STATUS_CODE);
438 * Tests reading (i.e. retrieval) of a list of objects of the specified type by a user who
439 * is not authorized to perform this action.
443 @Test(dependsOnMethods = {"readList"})
444 public void readListWithoutAuthorization() {
446 // Expected status code: 403 Forbidden
447 final int EXPECTED_STATUS_CODE = Response.Status.FORBIDDEN.getStatusCode();
449 // @TODO Currently only a stub. This test can be implemented
450 // when the service is revised to require authorization.
455 // ---------------------------------------------------------------
456 // CRUD tests : UPDATE tests
457 // ---------------------------------------------------------------
463 * Tests updating the content of an object of the specified type.
465 * Also expected: The entity body in the response contains
466 * a representation of the updated object of the specified type.
468 @Test(dependsOnMethods = {"create"})
469 public void update() {
471 // Expected status code: 200 OK
472 final int EXPECTED_STATUS_CODE = Response.Status.OK.getStatusCode();
474 ClientResponse<CollectionObject> res =
475 client.getCollectionObject(knownObjectId);
476 verbose("read: status = " + res.getStatus());
477 Assert.assertEquals(res.getStatus(), EXPECTED_STATUS_CODE);
478 CollectionObject collectionObject = res.getEntity();
479 verbose("Got object to update with ID: " + knownObjectId,
480 collectionObject, CollectionObject.class);
482 //collectionObject.setCsid("updated-" + knownObjectId);
483 collectionObject.setObjectNumber("updated-" + collectionObject.getObjectNumber());
484 collectionObject.setObjectName("updated-" + collectionObject.getObjectName());
486 // make call to update service
488 client.updateCollectionObject(knownObjectId, collectionObject);
489 verbose("update: status = " + res.getStatus());
490 Assert.assertEquals(res.getStatus(), EXPECTED_STATUS_CODE);
492 // check the response
493 CollectionObject updatedCollectionObject = res.getEntity();
494 Assert.assertEquals(updatedCollectionObject.getObjectName(),
495 collectionObject.getObjectName());
496 verbose("update: ", updatedCollectionObject, CollectionObject.class);
500 * Tests updating the content of an object of the specified type
501 * by sending malformed XML data in the entity body of the request.
504 @Test(dependsOnMethods = {"create", "testSubmitRequest"})
505 public void updateWithMalformedXml() {
507 // Expected status code: 400 Bad Request
508 final int EXPECTED_STATUS_CODE = Response.Status.BAD_REQUEST.getStatusCode();
510 // @TODO This test is currently commented out, because it returns a
511 // 500 Internal Server Error status code, rather than the expected status code.
513 String url = getResourceURL(knownObjectId);
514 PutMethod method = new PutMethod(url);
516 // Prepare the entity body of the request.
518 // Note missing final angle bracket in text below.
519 final String MALFORMED_XML_DATA = "<malformed_xml>wrong schema contents</malformed_xml";
520 StringRequestEntity entity = getXmlEntity(MALFORMED_XML_DATA);
522 // Submit the request.
523 int statusCode = submitRequest(method, entity);
524 verbose("updateWithMalformedXml: url=" + url + " status=" + statusCode);
526 // Evaluate the status code in the response.
527 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE,
528 "expected " + EXPECTED_STATUS_CODE);
533 * Tests updating the content of an object of the specified type
534 * by sending data in the wrong schema (e.g. in a format that
535 * doesn't match the object's schema) in the entity body of the request.
538 @Test(dependsOnMethods = {"create", "testSubmitRequest", "createWithMalformedXml"})
539 public void updateWithWrongSchema() {
541 // Expected status code: 400 Bad Request
542 final int EXPECTED_STATUS_CODE = Response.Status.BAD_REQUEST.getStatusCode();
544 // @TODO This test is currently commented out, because it returns a
545 // 500 Internal Server Error status code, rather than the expected status code.
547 String url = getResourceURL(knownObjectId);
548 PutMethod method = new PutMethod(url);
550 // Prepare the entity body of the request.
551 final String WRONG_SCHEMA_DATA = "<wrong_schema>wrong schema contents</wrong_schema>";
552 StringRequestEntity entity = getXmlEntity(WRONG_SCHEMA_DATA);
554 // Submit the request.
555 int statusCode = submitRequest(method, entity);
556 verbose("updateWithWrongSchema: url=" + url + " status=" + statusCode);
558 // Evaluate the status code in the response.
559 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE,
560 "expected " + EXPECTED_STATUS_CODE);
565 * Tests updating the content of an object of the specified type,
566 * by a user who is not authorized to perform this action.
569 @Test(dependsOnMethods = {"update"})
570 public void updateWithoutAuthorization() {
572 // Expected status code: 403 Forbidden
573 final int EXPECTED_STATUS_CODE = Response.Status.FORBIDDEN.getStatusCode();
575 // @TODO Currently only a stub. This test can be implemented
576 // when the service is revised to require authorization.
581 * Tests updating the content of a non-existent object of the specified type,
582 * whose resource identifier does not exist.
584 @Test(dependsOnMethods = {"update"})
585 public void updateNonExistent() {
587 // Expected status code: 404 Not Found
588 final int EXPECTED_STATUS_CODE = Response.Status.NOT_FOUND.getStatusCode();
590 // Note: The ID used in this 'create' call may be arbitrary.
591 // The only relevant ID may be the one used in updateCollectionObject(), below.
592 CollectionObject collectionObject = createCollectionObject(NON_EXISTENT_ID);
593 // make call to update service
594 ClientResponse<CollectionObject> res =
595 client.updateCollectionObject(NON_EXISTENT_ID, collectionObject);
596 verbose("updateNonExistent: status = " + res.getStatus());
597 Assert.assertEquals(res.getStatus(), EXPECTED_STATUS_CODE);
601 // ---------------------------------------------------------------
602 // CRUD tests : DELETE tests
603 // ---------------------------------------------------------------
609 * Tests deleting an object of the specified type.
611 * Expected status code: 200 OK
613 @Test(dependsOnMethods =
614 {"create", "read", "testSubmitRequest", "update"})
615 public void delete() {
617 // Expected status code: 200 OK
618 final int EXPECTED_STATUS_CODE = Response.Status.OK.getStatusCode();
620 ClientResponse<Response> res = client.deleteCollectionObject(knownObjectId);
621 verbose("delete: status = " + res.getStatus());
622 Assert.assertEquals(res.getStatus(), EXPECTED_STATUS_CODE);
629 * Tests deleting an object of the specified type,
630 * by a user who is not authorized to perform this action.
633 @Test(dependsOnMethods = {"delete"})
634 public void deleteWithoutAuthorization() {
636 // Expected status code: 403 Forbidden
637 final int EXPECTED_STATUS_CODE = Response.Status.FORBIDDEN.getStatusCode();
639 // @TODO Currently only a stub. This test can be implemented
640 // when the service is revised to require authorization.
645 * Tests deleting a non-existent object of the specified type,
646 * whose resource identifier does not exist at the specified URL.
648 @Test(dependsOnMethods = {"delete"})
649 public void deleteNonExistent() {
651 // Expected status code: 404 Not Found
652 final int EXPECTED_STATUS_CODE = Response.Status.NOT_FOUND.getStatusCode();
654 ClientResponse<Response> res =
655 client.deleteCollectionObject(NON_EXISTENT_ID);
656 verbose("deleteNonExistent: status = " + res.getStatus());
657 Assert.assertEquals(res.getStatus(), EXPECTED_STATUS_CODE);
661 // ---------------------------------------------------------------
662 // Utility methods used by tests above
663 // ---------------------------------------------------------------
665 // Methods specific to this test
667 private CollectionObject createCollectionObject(String identifier) {
668 CollectionObject collectionObject = createCollectionObject("objectNumber-" + identifier,
669 "objectName-" + identifier);
670 return collectionObject;
673 private CollectionObject createCollectionObject(String objectNumber, String objectName) {
674 CollectionObject collectionObject = new CollectionObject();
675 collectionObject.setObjectNumber(objectNumber);
676 collectionObject.setObjectName(objectName);
677 return collectionObject;
680 private String getServicePathComponent() {
681 // @TODO Determine if it is possible to obtain this value programmatically.
682 // We set this in an annotation in the CollectionObjectProxy interface, for instance.
683 final String SERVICE_PATH_COMPONENT = "collectionobjects";
684 return SERVICE_PATH_COMPONENT;
687 // Methods common to all entity service test classes. These can be
688 // moved out of individual service test classes into a common class,
689 // perhaps at the top-level 'client' module.
693 Utility that asserts various HTTP status codes received for a given type of a request.
694 This should be used from any test we write for a service. For example, this utility
695 could take the following two params.
696 import javax.ws.rs.core.Response;
697 final static public boolean checkStatus(String method, Response.Status status);
698 Perhaps you could find about method used from org.jboss.resteasy.client.ClientResponse metadata.
701 private String getServiceRootURL() {
702 return serviceClient.getBaseURL() + getServicePathComponent();
705 private String getResourceURL(String id) {
706 return getServiceRootURL() + "/" + id;
709 private int submitRequest(HttpMethod method) {
712 statusCode = httpClient.executeMethod(method);
713 } catch(HttpException e) {
714 logger.error("Fatal protocol violation: ", e);
715 } catch(IOException e) {
716 logger.error("Fatal transport error: ", e);
717 } catch(Exception e) {
718 logger.error("Unknown exception: ", e);
720 // Release the connection.
721 method.releaseConnection();
726 private int submitRequest(EntityEnclosingMethod method, RequestEntity entity) {
729 method.setRequestEntity(entity);
730 statusCode = httpClient.executeMethod(method);
731 } catch(HttpException e) {
732 logger.error("Fatal protocol violation: ", e);
733 } catch(IOException e) {
734 logger.error("Fatal transport error: ", e);
735 } catch(Exception e) {
736 logger.error("Unknown exception: ", e);
738 // Release the connection.
739 method.releaseConnection();
744 private StringRequestEntity getXmlEntity(String contents) {
745 if (contents == null) {
748 StringRequestEntity entity = null;
749 final String XML_DECLARATION = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>";
750 final String XML_CONTENT_TYPE=MediaType.APPLICATION_XML;
751 final String UTF8_CHARSET_NAME = "UTF-8";
754 new StringRequestEntity(XML_DECLARATION + contents, XML_CONTENT_TYPE, UTF8_CHARSET_NAME);
755 } catch (UnsupportedEncodingException e) {
756 logger.error("Unsupported character encoding error: ", e);
761 private String extractId(ClientResponse<Response> res) {
762 MultivaluedMap mvm = res.getMetadata();
763 String uri = (String) ((ArrayList) mvm.get("Location")).get(0);
764 verbose("extractId:uri=" + uri);
765 String[] segments = uri.split("/");
766 String id = segments[segments.length - 1];
771 private void verbose(String msg) {
772 if (logger.isDebugEnabled()) {
777 private void verbose(String msg, Object o, Class clazz) {
780 JAXBContext jc = JAXBContext.newInstance(clazz);
781 Marshaller m = jc.createMarshaller();
782 m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,
784 m.marshal(o, System.out);
790 private void verboseMap(MultivaluedMap map) {
791 for(Object entry : map.entrySet()){
792 MultivaluedMap.Entry mentry = (MultivaluedMap.Entry) entry;
793 verbose(" name=" + mentry.getKey() + " value=" + mentry.getValue());
797 private String createIdentifier() {
798 long identifier = System.currentTimeMillis();
799 return Long.toString(identifier);
802 private String createNonExistentIdentifier() {
803 return Long.toString(Long.MAX_VALUE);