{"id":2469,"date":"2015-12-09T17:38:09","date_gmt":"2015-12-09T15:38:09","guid":{"rendered":"https:\/\/adrhc.go.ro\/wordpress\/?p=2469"},"modified":"2017-05-23T19:55:53","modified_gmt":"2017-05-23T17:55:53","slug":"jaxrs-jersey","status":"publish","type":"post","link":"https:\/\/adrhc.go.ro\/blog\/jaxrs-jersey\/","title":{"rendered":"JAX-RS with Jersey"},"content":{"rendered":"<pre>\r\n<strong>Terms<\/strong>\r\nresource method designator - annotation such as @GET, @PUT, @POST, @DELETE\r\nsub-resource methods - methods annotated with @Path and also with resource method designators such as @GET or @POST\r\nsub-resource locators - methods annotated with @Path but not with resource method designators such as @GET or @POST\r\n\r\n<strong>Tips & Tricks<\/strong>\r\nJersey gives you an option to register so called model processor providers (org.glassfish.jersey.server.model.ModelProcessor). These providers are able to modify or enhance the application resource model during application deployment.\r\n\r\nUse @InjectLink on an entity (returned by server) field in order to inject it with a link (intead of using a link header).\r\n\r\nDo not use ApacheConnectorProvider nor GrizzlyConnectorProvider neither JettyConnectorProvider connector implementations with Jersey Multipart features. See <a href=\"https:\/\/jersey.java.net\/documentation\/latest\/client.html#connectors.warning\" target=\"_blank\">Header modification issue<\/a> warning for more details.\r\n\r\njavax.activation.MimetypesFileTypeMap - utility for getting the MIME type of a file\r\n\r\n@Produces({\"application\/xml; qs=0.9\", \"application\/json\"})\r\nIf client accepts both \"application\/xml\" and \"application\/json\" (equally), then a server always sends \"application\/json\", since \"application\/xml\" has a lower quality factor.\r\n\r\nHttpHeaders, Request, UriInfo, SecurityContext can be injected into constructor or class fields of a singleton (using the @Context annotation).\r\nFor these objects the runtime will inject proxies which are able to simultaneously server more request.\r\n\r\nThe @FormParam annotation is special and may only be utilized on resource and sub-resource methods. This is because it extracts information from a request entity.\r\n\r\nBy default, <strong>the transport layer<\/strong> in Jersey is provided by HttpUrlConnection. This transport is implemented in Jersey via HttpUrlConnectorProvider that implements Jersey-specific Connector SPI. HttpUrlConnection by default restricts the use of some headers. In order to permit all headers to be sent the system property sun.net.http.allowRestrictedHeaders must be set to \"true\".\r\n\r\n<strong>Sub-resource locator return types<\/strong>\r\n@Path(\"\/\")\r\npublic ItemContentResource getItemContentResource() {\r\n\t\/\/ instance\r\n\treturn new ItemContentResource();\r\n}\r\n@Path(\"kid1\")\r\npublic Class<MySubResource1> getMySubResource1() {\r\n\t\/\/ Class<T>\r\n\treturn MySubResource1.class;\r\n}\r\n@Path(\"kid2\")\r\npublic Resource getMySubResource() {\r\n\t\/\/ Resource (programmatic resource model return type)\r\n\treturn Resource.from(MySubResource2.class);\r\n}\r\n@Path(\"kid5\")\r\npublic MySubResource5 getMySubResource(@QueryParam(\"impl\") String impl) {\r\n\t\/\/ Object (the way to support polymorphism)\r\n\t\/\/ @QueryParam(\"impl\") won't be available into sub-sesource\r\n\tif (impl.equals(\"a\")) {\r\n\t\treturn new MySubResource5a(impl);\r\n\t} else {\r\n\t\treturn new MySubResource5b(impl);\r\n\t}\r\n}\r\n\r\n<strong>Architecture (the usual usage)<\/strong>\r\n<em>invocating a jax-rs service<\/em>\r\nClientBuilder builds Client (dealing with registration of providers, features, filter and interceptors).\r\nClient builds WebTarget (dealing with the URI construction including query and matrix parameters, template values).\r\nWebTarget builds Invocation.Builder (dealing with any except URI construction; deals with headers and cookies, filter-accesible properties).\r\nInvocation.Builder builds Invocation\/AsyncInvoker (dealing with the \"actual call\" and getting the result).\r\nInvocation.Builder can behave also as SyncInvoker in order to do the \"actual call\".\r\n\r\n<em>javax.ws.rs.core.Response created by server<\/em>\r\nResponse creates a ResponseBuilder while also being able to set the http status.\r\nResponseBuilder sets headers (status, link, lastModified, entity tag, location, etc), cookies, entity (+annotations).\r\nResponseBuilder then builds the Response.\r\n\r\n<em>javax.ws.rs.core.Response used by client<\/em>\r\nResponse is obtained as a result of the \"actual call\" facilitated by Invocation.Builder.\r\nResponse provides headers, cookies and entity access (Response.readEntity(Class<T> entityType, Annotation[] annotations)).\r\nFor reading the entity a MessageBodyReader<T> in used based also on annotations provided to Response.readEntity().\r\n\r\n<em>Chunked Output<\/em>\r\nIn Jersey you can use ChunkedOutput to send response to a client in chunks. \r\nThis can be achived by returning ChunkedOutput<T> from a resource method - this makes the method automatically asynchronous.\r\nThen one writes T for the client using ChunkedOutput. After sending some T one should close the ChunkedOutput.\r\n\r\nClient side one uses Response.readEntity in order to get a ChunkedInput<T> from which reads T while not null.\r\n\r\n<em>Server-Sent Events<\/em>\r\nThis is the server side support for services which can be consumed from java script with <a href=\"http:\/\/www.w3.org\/TR\/2009\/WD-eventsource-20091029\/\" target=\"_blank\">EventSource<\/a>.\r\nThe resource method should return org.glassfish.jersey.media.sse.EventOutput which is a ChunkedOutput<OutboundEvent> - this makes the method automatically asynchronous. Then one uses EventOutput in order to write OutboundEvent which is a wrapper for the actual entity one wants to send. Finally one would close the EventOutput in order to end the communication.\r\n\r\nClient side one gets a EventInput instance from where reads InboundEvent which is a wrapper for the actual entity sent by server. The connection is closed when null EventInput is received or InboundEvent.isClosed() returns true.\r\ninstead of getting an EventInput instance one could use EventSource then register an EventListener in order to receive InboundEvent.\r\n\r\n<em>security<\/em>\r\nSecurity information of a request is available by injecting a JAX-RS SecurityContext instance using @Context annotation.\r\nYou can define the access to resources using annotations from package javax.annotation.security defined by JSR-250 (PermitAll, RolesAllowed).\r\n\r\n<em>bean validation support<\/em>\r\nJersey does not support, and doesn't validate, constraints placed on constructors and Bean Validation groups (only Default group is supported at the moment). Constraint annotations are allowed in resource method parameters, fields and property getters as well as resource classes, entity parameters and resource methods (return values). E.g. validation on resource method parameters:\r\n@NotNull @FormParam(\"lastName\") String lastName, @Email @FormParam(\"email\") String email, @Valid User user.\r\nThe @Email annotation is defined as:\r\n@Constraint(validatedBy = EmailValidator.class)\r\npublic @interface Email { ...\r\nThe constraint class is defined as:\r\npublic class EmailValidator implements ConstraintValidator<Email, String> { ...\r\n\r\n<em>Entity Data Filtering<\/em>\r\nEntity filtering is achived with:\r\n- custom annotations (server and client side support)\r\n- role-based Entity Filtering using (javax.annotation.security) annotations (server and client side support)\r\n- dynamic and configurable query parameters\r\nWith <em>custom annotations<\/em> one uses @EntityFiltering meta-annotation to creates a custom annotation e.g. @UserDetailedView.\r\nThen creates a response e.g.:\r\nResponse.ok().entity(new User(), isDetailed ? new Annotation[]{UserDetailedView.Factory.get()} : new Annotation[0]).build();\r\nor \r\nsimply annotates with @ProjectDetailedView the resource method.\r\nThen the client shall receive an User entity populated only for the fields annotated with @UserDetailedView or not annotated at all with @EntityFiltering.\r\nWith <em>role-based Entity Filtering using (javax.annotation.security) annotations<\/em> one uses javax.annotation.security annotations same way as he would with custom annotations entity-filtering. Instances of security annotations can be created using SecurityAnnotations factory class that is part of the Jersey Entity Filtering API.\r\n<em>Entity Filtering based on dynamic and configurable query parameters<\/em> allows one to specify the <em>select<\/em> query parameter in order to filter the entity's fields e.g. http:\/\/example.com\/user\/51234?select=name,surname,country.name -> here only name, surname, country.name fields from User entity shall be populated.\r\n\r\n<em>MVC Templates<\/em>\r\nUse @Template(templateName) on a resource method in order to define a template (jep, freemarker, mustache) processing the entity returned. \r\nJersey will assign the entity instance to an attribute named <em>model<\/em> which can be user with e.g. ${model} in jsp or freemarker.\r\nOne could use @ErrorTemplate the same way where Bean Validation errors will be accessible with the attribute name <em>error<\/em>.\r\n\r\n<strong>Configuration<\/strong>\r\njersey specific: org.glassfish.jersey.client.ClientConfig implements javax.ws.rs.core.Configurable<ClientConfig>, ...\r\njersey specific: org.glassfish.jersey.client.ResourceConfig implements javax.ws.rs.core.Configurable<ResourceConfig>, ...\r\nClientConfig and ResourceConfig both use javax.ws.rs.core.Configurable's ergonomic methods in order to construct javax.ws.rs.core.Configuration.\r\nWhile constructing javax.ws.rs.core.Configuration also ResourceConfig constructs javax.ws.rs.core.Application (main objective by the way).\r\nClientConfig aim is the construct of a javax.ws.rs.core.Configuration which further would be used by \r\njavax.ws.rs.client.ClientBuilder.newClient(Configuration configuration) to construct javax.ws.rs.client.Client.\r\n\r\n<strong>Filters<\/strong> can be used when you want to modify any request or response parameters like headers.\r\n\r\n<strong>Interceptors<\/strong> share a common API for the server and the client side. Whereas filters are primarily intended to manipulate request and response parameters like HTTP headers, URIs and\/or HTTP methods, interceptors are intended to manipulate entities, via manipulating entity input\/output streams.\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Terms resource method designator &#8211; annotation such as @GET, @PUT, @POST, @DELETE sub-resource methods &#8211; methods annotated with @Path and also with resource method designators such as @GET or @POST sub-resource locators &#8211; methods annotated with @Path but not with [&hellip;]<\/p>\n<div class=\"link-more\"><a href=\"https:\/\/adrhc.go.ro\/blog\/jaxrs-jersey\/#more-2469\" class=\"more-link\">Continue reading &#10142; <span class=\"screen-reader-text\">JAX-RS with Jersey<\/span><\/a><\/div>","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[36,10],"tags":[74,75,69],"class_list":["post-2469","post","type-post","status-publish","format-standard","hentry","category-java","category-programming","tag-jaxrs","tag-jersey","tag-rest"],"_links":{"self":[{"href":"https:\/\/adrhc.go.ro\/blog\/wp-json\/wp\/v2\/posts\/2469","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/adrhc.go.ro\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/adrhc.go.ro\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/adrhc.go.ro\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/adrhc.go.ro\/blog\/wp-json\/wp\/v2\/comments?post=2469"}],"version-history":[{"count":0,"href":"https:\/\/adrhc.go.ro\/blog\/wp-json\/wp\/v2\/posts\/2469\/revisions"}],"wp:attachment":[{"href":"https:\/\/adrhc.go.ro\/blog\/wp-json\/wp\/v2\/media?parent=2469"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/adrhc.go.ro\/blog\/wp-json\/wp\/v2\/categories?post=2469"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/adrhc.go.ro\/blog\/wp-json\/wp\/v2\/tags?post=2469"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}