https://www.logicbig.com/tutorials/java-ee-tutorial/jax-rs/filters-pre-matching.html
http://stackoverflow.com/questions/35906403/jersey-containerrequestfilter-getting-404-after-throwing-abortwith-with-statu
https://jersey.java.net/documentation/latest/filters-and-interceptors.html
It's a good practice to assign a priority to filters and interceptors. Use Priorities class which defines standardized priorities in JAX-RS for different usages, rather than inventing your own priorities. So, when you for example write an authentication filter you would assign a priority 1000 which is the value of
http://jmchung.github.io/blog/2013/08/11/cross-domain-on-jersey-restful-web-services/
@OPTIONS public Response myResource() { return Response.ok().build(); }
https://simplapi.wordpress.com/2013/04/10/jersey-jax-rs-implements-a-cross-domain-filter/
You need to escape all options, so at the beginning of the filter, add like this (see from methods.equals(« OPTIONS »)) :
http://www.codingpedia.org/ama/how-to-add-cors-support-on-the-server-side-in-java-with-jersey/
https://java.net/jira/browse/JERSEY-2553
http://www.developerscrappad.com/2308/java/java-ee/rest-jax-rs/java-rest-jax-rs-2-0-how-to-handle-date-time-and-timestamp-data-types/
If you change the type of your
http://kingsfleet.blogspot.com/2014/01/selecting-level-of-detail-returned-by_29.html
https://jersey.java.net/documentation/latest/entity-filtering.html
http://blog.dejavu.sk/2014/02/04/filtering-jax-rs-entities-with-standard-security-annotations/
@DenyAll
public String getSecret() { ... }
@RolesAllowed({"manager", "user"})
public List<Task> getTasks() { ... }
@RolesAllowed({"manager"})
public List<User> getUsers() { ... }
@RolesAllowed({"manager", "client"})
public List<Report> getReports() { ... }
http://blog.dejavu.sk/2015/02/04/jerseys-entity-filtering-meets-jackson/
@GET
@Path("{id}")
public Person getPerson() {
// ...
return person;
}
And for
{
"addresses":[
{
"phoneNumber":{
"number": "867-5309"
}
}
],
"familyName": "Dowd",
"givenName": "Andrew"
}
http://howtodoinjava.com/jersey/jersey-selectable-entityfilteringfeature-example/
you want to make RESTful API consumers capable of filtering data what they need from a GET API, rather than forcing them to consume all the response data unnecessary. There are two ways to achieve this filtering : server side response filtering and client side response filtering.
To demonstrate the use of client side response filtering using
Spring MVC is a full Web frontend framework including support for HTML and other templating, plus other features, in addition to the JSON/XML REST features provided by Jersey.
Jersey first runs ExceptionMapper then ContainerResponseFilter
http://www.makeinjava.com/execution-flow-filters-interceptors-jax-rs-jersey-example/
[[FATAL] No injection source found for a parameter of type public
-- this means jersey can not map something to your parameter
Jersey can map string to complex PathParam, but you need follow some rules.
Method register(class, priority) is not retaining the default priority
https://java.net/jira/browse/JERSEY-2640
http://stackoverflow.com/questions/34639434/why-jersey-doesnt-honor-the-priorities-in-dynamically-bind-filters
. So, a request filter with priority defined with
http://stackoverflow.com/questions/26989608/jersey-2-3-setting-priority-for-containerrequestfilter
https://jersey.java.net/documentation/latest/filters-and-interceptors.html
Customize QueryParam/PathParam
https://github.com/javaee-samples/javaee7-samples/blob/master/jaxrs/paramconverter/src/main/java/org/javaee7/jaxrs/paramconverter/MyBeanConverterProvider.java
@Provider
public class MyBeanConverterProvider implements ParamConverterProvider {
@Override
public <T> ParamConverter<T> getConverter(Class<T> clazz, Type type, Annotation[] annotations) {
if (clazz.getName().equals(MyBean.class.getName())) {
return new ParamConverter<T>() {
@SuppressWarnings("unchecked")
@Override
public T fromString(String value) {
MyBean bean = new MyBean();
bean.setValue(value);
return (T) bean;
}
@Override
public String toString(T bean) {
return ((MyBean) bean).getValue();
}
};
}
return null;
}
}
http://stackoverflow.com/questions/29207562/how-to-use-custom-type-for-pathparam
http://blog.dejavu.sk/2014/02/11/inject-custom-java-types-via-jax-rs-parameter-annotations/
ParamConverterProvider and ParamConverter. With the first one we simply tell the runtime whether we’re able to convert String to a particular type and with the second one we’re doing the actual conversion.
http://docs.oracle.com/javaee/6/tutorial/doc/gknav.html
HK2
http://www.justinleegrant.com/?p=516
Lastly, we need to identify where you need these and apply the @Inject annotation. I advise people to use constructor injection, which ensures all mandatory properties have been satisfied, and it is simply not possible to instantiate an object in an invalid state. Plus, it’s significantly easier to test this way.
https://hk2.java.net/spring-bridge/
http://stackoverflow.com/questions/26230642/jersey-hk2-injecting-service-annotated-classes
we have moved on with the project and eventually gave up on hk2; instead we rely on spring bridge and spring for DI.
https://newfivefour.com/java-jersey-dependency-injection.html
https://github.com/jersey/jersey/tree/master/examples/helloworld-spring-webapp
http://stackoverflow.com/questions/30987153/is-it-possible-to-construct-an-object-partially-with-spring-di-and-partially-wit
https://hk2.java.net/2.5.0-b05/introduction.html
* Jersey Spring integration example.
* Demonstrate how to inject a Spring bean into a Jersey managed JAX-RS resource class.
https://blogs.oracle.com/enterprisetechtips/entry/jersey_and_spring
https://java.net/jira/browse/JERSEY-2055
http://stackoverflow.com/questions/32574887/purpose-of-component-annotation-on-spring-boot-starter-jersey-resources-in-spri
http://stackoverflow.com/questions/26408084/jersey-what-is-the-difference-in-injecting-uriinfo-as-class-instance-variable
Jersey implementation allows you to directly inject HttpServletRequest instance into your JAX-RS components. It is quite straight forward to get the appropriate
http://download.oracle.com/otn-pub/jcp/jaxrs-2_0-fr-eval-spec/jsr339-jaxrs-2.0-final-spec.pdf?AuthParam=1464813534_ca389fd17d2b252b377a52c65cb808e5
Chapter 9 Context
@Context UriInfo
@Context HttpHeaders
@Context Request request,
The methods of Request allow a caller to determine the best matching representation variant and to evaluate
whether the current state of the resource matches any preconditions in the request. Precondition support
methods return a ResponseBuilder that can be returned to the client to inform it that the request preconditions
were not met. E.g. the following checks if the current entity tag matches any preconditions in the
request before updating the resource:
. An instance of SecurityContext can be injected into a class field or method parameter using the
@Context annotation
https://jersey.java.net/documentation/latest/jaxrs-resources.html
http://www.theotherian.com/2013/08/jersey-client-2.0-httpclient-timeouts-max-connections.html
// values are in milliseconds
clientConfig.property(ClientProperties.READ_TIMEOUT, 2000);
clientConfig.property(ClientProperties.CONNECT_TIMEOUT, 500);
using httpclient with connection pooling
Now let's set up a ClientConnectionManager that uses pooling. We should also set the limits on the number of connections a little bit higher, since 20 total and 2 per host is on the low side (we'll use 100 and 20 instead):
PoolingClientConnectionManager connectionManager = new PoolingClientConnectionManager();
connectionManager.setMaxTotal(100);
connectionManager.setDefaultMaxPerRoute(20);
You can also be much more fine grained about how many connections per host are allowed with the setMaxPerRoute method. For example, let's say it was ok to have 40 max connections when hitting localhost:
connectionManager.setMaxPerRoute(new HttpRoute(new HttpHost("localhost")), 40);
We need to create a new ApacheConnector from the configuration, which specifies the pooled connection manager, and then set the connector in the configuration
ClientConfig clientConfig = ...;
PoolingClientConnectionManager connectionManager = ...;
// tell the config about the connection manager
clientConfig.property(ApacheClientProperties.CONNECTION_MANAGER, connectionManager);
// tell the connector about the config, which includes the connection manager and timeouts
ApacheConnector connector = new ApacheConnector(clientConfig);
// tell the config about the connector
clientConfig.connector(connector);
client.register(JacksonFeature.class);
https://blogs.oracle.com/japod/entry/how_to_use_jersey_client
https://jersey.java.net/documentation/latest/async.html
http://blog.dejavu.sk/2015/01/21/intercepting-jersey-resource-method-calls/
http://stackoverflow.com/questions/20556200/jersey-async-containerrequestfilter
https://jersey.java.net/documentation/latest/filters-and-interceptors.html
All the request filters shown above was implemented as post-matching filters. It means that the filters would be applied only after a suitable resource method has been selected to process the actual request i.e. after request matching happens. Request matching is the process of finding a resource method that should be executed based on the request path and other request parameters. Since post-matching request filters are invoked when a particular resource method has already been selected, such filters can not influence the resource method matching process.
To overcome the above described limitation, there is a possibility to mark a server request filter as a pre-matching filter, i.e. to annotate the filter class with the @PreMatchingannotation. Pre-matching filters are request filters that are executed before the request matching is started. Thanks to this, pre-matching request filters have the possibility to influence which method will be matched. Such a pre-matching request filter example is shown here:
http://howtodoinjava.com/jersey/jersey-2-hello-world-application-tutorial/
http://stackoverflow.com/questions/25701658/integrating-jersey-2-and-spring-with-java-based-configuration
https://jersey.java.net/documentation/latest/spring.html
https://github.com/jersey/jersey/tree/2.22.2/examples/helloworld-spring-webapp
<servlet>
<servlet-name>SpringApplication</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>org.glassfish.jersey.examples.helloworld.spring.MyApplication</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
http://www.theotherian.com/2013/07/creating-resource-filters-with-jersey.html
public class IE6NotSupportedFilter implements ContainerRequestFilter {
@Override
public void filter(ContainerRequestContext requestContext) throws IOException {
if (isIE6Browser(requestContext.getHeaderString("User-Agent"))) {
requestContext.abortWith(Response.status(Status.PRECONDITION_FAILED).entity(getFailurePage()).build());
}
}
}
@ApplicationPath("/")
public class MyApplication extends ResourceConfig {
public MyApplication() {
// Register resources and providers using package-scanning.
packages("my.package");
// Register my custom provider - not needed if it's in my.package.
register(SecurityRequestFilter.class);
// Register an instance of LoggingFilter.
register(new LoggingFilter(LOGGER, true));
// Enable Tracing support.
property(ServerProperties.TRACING, "ALL");
}
}
http://stackoverflow.com/questions/18268827/how-do-i-get-jersey-2-2-jax-rs-to-generate-log-output-including-json-request
<servlet>
<servlet-name>my.package.MyApplication</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<!-- Register JAX-RS Application, if needed. -->
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>my.package.MyApplication</param-value>
</init-param>
<!-- Register resources and providers under my.package. -->
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>my.package</param-value>
</init-param>
<!-- Register my custom provider (not needed if it's in my.package) AND LoggingFilter. -->
<init-param>
<param-name>jersey.config.server.provider.classnames</param-name>
<param-value>my.package.SecurityRequestFilter;org.glassfish.jersey.filter.LoggingFilter</param-value>
</init-param>
<!-- Enable Tracing support. -->
<init-param>
<param-name>jersey.config.server.tracing</param-name>
<param-value>ALL</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
Filters prioties:
http://stackoverflow.com/questions/26989608/jersey-2-3-setting-priority-for-containerrequestfilter
Jersey client:
https://jersey.java.net/documentation/latest/client.html
http://howtodoinjava.com/jersey/jersey-restful-client-examples/
http://stackoverflow.com/questions/29434312/is-it-possible-in-jersey-to-have-access-to-an-injected-httpservletrequest-inste
https://java.net/jira/browse/JERSEY-2506
Issues:
jersey-spring3 doesn't support Spring Java config properly
https://java.net/jira/browse/JERSEY-2038
The new jersey-spring3 module expects an XML based spring configuration
http://stackoverflow.com/questions/4121722/how-to-make-jersey-to-use-slf4j-instead-of-jul
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
connectionManager.setMaxTotal(maxTotal);
connectionManager.setDefaultMaxPerRoute(maxPerRoute());
ClientConfig clientConfig = new ClientConfig();
clientConfig.property(ClientProperties.READ_TIMEOUT, readTimeout);
clientConfig.property(ClientProperties.CONNECT_TIMEOUT, connectionTimeout);
clientConfig.property(ApacheClientProperties.CONNECTION_MANAGER, connectionManager);
clientConfig.property(ClientProperties.FOLLOW_REDIRECTS, false);
clientConfig.property(ClientProperties.PROXY_URI, proxy);
ApacheConnectorProvider connector = new ApacheConnectorProvider();
clientConfig.connectorProvider(connector);
JacksonJaxbJsonProvider jacksonProvider = new JacksonJaxbJsonProvider();
jacksonProvider.setMapper(new ObjectMapper());
clientConfig.register(jacksonProvider);
clientConfig.property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, suppressHttpValidation);
http://blogs.sourceallies.com/2011/08/spring-injection-with-resource-and-autowired/
In JAX-Rs, filters can be divided into two categories: pre-matching filters and post-matching filters.
A post-matching filter is applied only after a suitable resource method has been selected to process the request. Such filters can not influence the resource method matching process. We have seen such filter example in the last tutorial.
A pre-matching filter (annotated with @RequestMatching) is executed before the request matching process is started. This filter can influence which resource method will be matched e.g. by changing the HTTP method or by changing the URI etc.
http://stackoverflow.com/questions/17143514/how-to-add-custom-response-and-abort-request-in-jersey-1-11-filters
In case of error, if you want to send a custom response then you need to throw a WebApplicationException. Create a Response object and send it back using the following exception constructor:
WebApplicationException(Response response)
Construct a new instance using the supplied response
Try this:
@Override
public ContainerRequest filter(ContainerRequest request) {
User user = Helper.getCurrentUser();
if(user == null){
ResponseBuilder builder = null;
String response = "Custom message";
builder = Response.status(Response.Status.UNAUTHORIZED).entity(response);
throw new WebApplicationException(builder.build());
}
return request;
}
http://stackoverflow.com/questions/35906403/jersey-containerrequestfilter-getting-404-after-throwing-abortwith-with-statu
requestContext.abortWith(Response.status(Response.Status.FORBIDDEN).build());
https://jersey.java.net/documentation/latest/filters-and-interceptors.html
It's a good practice to assign a priority to filters and interceptors. Use Priorities class which defines standardized priorities in JAX-RS for different usages, rather than inventing your own priorities. So, when you for example write an authentication filter you would assign a priority 1000 which is the value of
Priorities
.AUTHENTICATION
. The following example shows the filter from the beginning of this chapter with a priority assigned.http://jmchung.github.io/blog/2013/08/11/cross-domain-on-jersey-restful-web-services/
@OPTIONS public Response myResource() { return Response.ok().build(); }
@OPTIONS
@Path("/myresource")
public Response corsMyResource(@HeaderParam("Access-Control-Request-Headers") String requestH) {
_corsHeaders = requestH;
return makeCORS(Response.ok(), requestH);
}
You need to escape all options, so at the beginning of the filter, add like this (see from methods.equals(« OPTIONS »)) :
@Override
public
ContainerRequest filter(ContainerRequest containerRequest)
throws
WebApplicationException {
//GET, POST, PUT, DELETE, ...
String method = containerRequest.getMethod();
// myresource/get/56bCA for example
String path = containerRequest.getPath(
true
);
if
(method.equals(
"OPTIONS"
)) {
throw
new
WebApplicationException(Status.OK);
}
https://java.net/jira/browse/JERSEY-2553
http://www.developerscrappad.com/2308/java/java-ee/rest-jax-rs/java-rest-jax-rs-2-0-how-to-handle-date-time-and-timestamp-data-types/
public class RESTTimestampWithTZDParam {
private SimpleDateFormat df = new SimpleDateFormat( "yyyy-MM-dd'T'HH:mm:ssZ" );
private java.util.Date date;
public RESTTimestampWithTZDParam( String dateTimeStr ) throws WebApplicationException {
try {
date = new java.util.Date( df.parse( dateTimeStr ).getTime() );
} catch ( final ParseException ex ) {
throw new WebApplicationException( ex );
}
}
public java.util.Date getDate() {
return date;
}
@Override
public String toString() {
if ( date != null ) {
return date.toString();
} else {
return "";
}
}
}
https://www.mkyong.com/webservices/jax-rs/jax-rs-queryparam-example/@QueryParam("orderBy") List<String> orderBy
URI Pattern : “users/query?from=100&to=200&orderBy=age&orderBy=name”
public Response getUsers(@Context UriInfo info) {
String from = info.getQueryParameters().getFirst("from");
String to = info.getQueryParameters().getFirst("to");
List<String> orderBy = info.getQueryParameters().get("orderBy");
http://stackoverflow.com/questions/6154861/handling-multiple-query-parameters-in-jerseyIf you change the type of your
item
method parameter from String
to a collection such as List<String>
, you should get a collection that holds all the values you are looking for.
The JAX-RS specification (section 3.2) says the following regarding the
@QueryParam
annotation:The following types are supported:
- Primitive Types
- Types that have a constructor that accepts a single
String
argument.- Types that have a static method named
valueOf
with a singleString
argument.List<T>
,Set<T>
, orSortedSet<T>
whereT
satisfies 2 or 3 above.
List<String> items=ui.getQueryParameters().get("item");
where
ui
is declared as a member in the rest resource like so :@Context UriInfo ui;
Some libs like axios js use the square brackets notation when sending a multi-value param request: /stats?store[]=A&store[]=B&item[]=C&item[]=D
To handle all cases (with or without square brackets) you can add another param like this:
public String methodImCalling(
@QueryParam(value = "store") final List<String> store,
@QueryParam(value = "store[]") final List<String> storeWithBrackets,
@QueryParam(value = "item") final List<String> item,
@QueryParam(value = "item[]") final List<String> itemWithBrackets) {
...
}
https://jersey.java.net/documentation/latest/entity-filtering.html
http://blog.dejavu.sk/2014/02/04/filtering-jax-rs-entities-with-standard-security-annotations/
@DenyAll
public String getSecret() { ... }
@RolesAllowed({"manager", "user"})
public List<Task> getTasks() { ... }
@RolesAllowed({"manager"})
public List<User> getUsers() { ... }
@RolesAllowed({"manager", "client"})
public List<Report> getReports() { ... }
http://blog.dejavu.sk/2015/02/04/jerseys-entity-filtering-meets-jackson/
@GET
@Path("{id}")
public Person getPerson() {
// ...
return person;
}
And for
people/1234?select=familyName,givenName,addresses.phoneNumber.number
the response would be:{
"addresses":[
{
"phoneNumber":{
"number": "867-5309"
}
}
],
"familyName": "Dowd",
"givenName": "Andrew"
}
@Path("projects")
@Produces("application/json")
public class ProjectsResource {
@GET
public List<Project> getProjects() {
return getDetailedProjects();
}
@GET
@Path("detailed")
@ProjectDetailedView
public List<Project> getDetailedProjects() {
return EntityStore.getProjects();
}
}
http://howtodoinjava.com/jersey/jersey-selectable-entityfilteringfeature-example/
you want to make RESTful API consumers capable of filtering data what they need from a GET API, rather than forcing them to consume all the response data unnecessary. There are two ways to achieve this filtering : server side response filtering and client side response filtering.
To demonstrate the use of client side response filtering using
SelectableEntityFilteringFeature
,public
class
CustomApplication
extends
ResourceConfig
{
public
CustomApplication()
{
packages(
"com.howtodoinjava.jersey"
);
// Configure MOXy Json provider. Comment this line to use Jackson. Uncomment to use MOXy.
// register(new MoxyJsonConfig().setFormattedOutput(true).resolver());
// Configure Jackson Json provider. Comment this line to use MOXy. Uncomment to use Jackson.
register(JacksonFeature.
class
);
register(SelectableEntityFilteringFeature.
class
);
property(SelectableEntityFilteringFeature.QUERY_PARAM_NAME,
"select"
);
}
}
If you want to enable this feature through
web.xml
file, then you can add the feature to the list of provider class names:< init-param > < param-name >jersey.config.server.provider.classnames</ param-name > < param-value > org.glassfish.jersey.filter.LoggingFilter, org.glassfish.jersey.message.filtering.SelectableEntityFilteringFeature, org.glassfish.jersey.jackson.JacksonFeature </ param-value > </ init-param > |
And for setting the query selector property, use the below code:
< init-param > < param-name >jersey.config.entityFiltering.selectable.query</ param-name > < param-value >select</ param-value > </ init-param >
|
Hit HTTP GET: http://localhost:8080/JerseyDemos/rest/employees?select=employeeList,id
Response:{"employeeList":[{"id":1},{"id":2},{"id":3}]}
Spring MVC is a full Web frontend framework including support for HTML and other templating, plus other features, in addition to the JSON/XML REST features provided by Jersey.
Jersey first runs ExceptionMapper then ContainerResponseFilter
http://www.makeinjava.com/execution-flow-filters-interceptors-jax-rs-jersey-example/
[[FATAL] No injection source found for a parameter of type public
-- this means jersey can not map something to your parameter
Jersey can map string to complex PathParam, but you need follow some rules.
Method register(class, priority) is not retaining the default priority
https://java.net/jira/browse/JERSEY-2640
http://stackoverflow.com/questions/34639434/why-jersey-doesnt-honor-the-priorities-in-dynamically-bind-filters
Try to use
javax.annotation.Priority
annotations instead of the 2nd parameter in FeatureContext::register
and ResourceConfig::register
calls, which overrides the annotation.@Priority(1)
public class MyDynamicFilter implements ContainerRequestFilter {
...
@Priority(2)
public class MyStaticFilter implements ContainerRequestFilter {
https://jersey.java.net/documentation/latest/filters-and-interceptors.html#d0e10129. So, a request filter with priority defined with
@Priority(1000)
will be executed before another request filter with priority defined as @Priority(2000)
. Providers used during response processing (ContainerResponseFilter
, ClientResponseFilter
) are executed in the reverse order (using descending manner), so a provider with the priority defined with @Priority(2000)
will be executed before another provider with priority defined with @Priority(1000)
.http://stackoverflow.com/questions/26989608/jersey-2-3-setting-priority-for-containerrequestfilter
Use the
@Priority
for your filter classes, passing in a value (e.g. @Priority(1)
). The lower the number, the higher the priority (Don't need for anything special in web.xml or Application subclass)@Priority(6000)
public class MyFilter1 ... {}
@Priority(6001)
public class MyFilter2 ... {}
See Priorities
Option 2:
Configure it programmatically into the application via an inject-able
Configurable
. Something like@ApplicationPath("/")
public class MyApplication extends Application {
public MyApplication(@Context Configurable configurable) {
configurable.register(MyFilter1.class, 1000);
configurable.register(MyFilter2.class, 1001);
}
}
https://servicesunavailable.wordpress.com/2014/05/23/jersey-filters-containerrequestfilter-and-containerresponsefilter/https://jersey.java.net/documentation/latest/filters-and-interceptors.html
Interceptors 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. If you for example need to encode entity body of a client request then you could implement an interceptor to do the work for you.
Context is specific to a particular request but instances of certain JAX-RS components (providers and resource classes with a lifecycle other than per-request) may need to support multiple concurrent requests. When injecting an instance of one of the types listed in Section 9.2, the instance supplied MUST be capable of selecting the correct context for a particular request. Use of a thread-local proxy is a common way to achieve this.
So, as per the specification, JAX-RS implementations (e.g. Jersey) are required to ensure that the context is safe. Keep doing what you're doing.
You're safe. When you're injecting
HttpServletRequest
/ HttpServletResponse
you're not dealing with a particular instance but rather with a proxy through which you're invoking calls on a real instance stored in a ThreadLocal object. Each request is processed by a separate thread which has access to it's own HttpServletRequest
/ HttpServletResponse
. Beside injecting HttpServletRequest
/ HttpServletResponse
you can also inject ThreadLocal<HttpServletRequest>
/ ThreadLocal<HttpServletResponse>
and through '#get()` method you can obtain the real request / response instances intead of proxies.https://github.com/javaee-samples/javaee7-samples/blob/master/jaxrs/paramconverter/src/main/java/org/javaee7/jaxrs/paramconverter/MyBeanConverterProvider.java
@Provider
public class MyBeanConverterProvider implements ParamConverterProvider {
@Override
public <T> ParamConverter<T> getConverter(Class<T> clazz, Type type, Annotation[] annotations) {
if (clazz.getName().equals(MyBean.class.getName())) {
return new ParamConverter<T>() {
@SuppressWarnings("unchecked")
@Override
public T fromString(String value) {
MyBean bean = new MyBean();
bean.setValue(value);
return (T) bean;
}
@Override
public String toString(T bean) {
return ((MyBean) bean).getValue();
}
};
}
return null;
}
}
http://stackoverflow.com/questions/29207562/how-to-use-custom-type-for-pathparam
The thing is path parameters come in String form. As per the specification, if we want the have a custom type be injected as a
@PathParam
, the custom class, should have one of three things:- A public static
valueOf(String param)
that returns the type - A public static
fromString(String param)
that returns the type - Or a public constructor that accepts a String
- Another option implement a
ParamConverter
. You can see an example here.
If you don't own the class (it's a third-party class that you can't change) then your only option is to use the
ParamConverter/ParamConverterProvider
pair.
In either of these cases you'll want to construct the instance accordingly by parsing the String either in the constructor or in one of the above mentioned methods. After doing this, the custom type can be made a method parameter with the annotation.
The same holds true for other params, such as
http://stackoverflow.com/questions/30403033/passing-custom-type-query-parameter@FormParam
, @HeaderParam
, @QueryParam
, etc.
Take a look at the
@QueryParam
documentation, in regards to acceptable types to inject. (The same applies to all the other @XxxParam
annotations also)- Be a primitive type
- Have a constructor that accepts a single String argument
- Have a static method named
valueOf
orfromString
that accepts a single String argument (see, for example,Integer.valueOf(String)
) - Have a registered implementation of ParamConverterProvider JAX-RS extension SPI that returns a ParamConverter instance capable of a "from string" conversion for the type.
- Be
List<T>
,Set<T>
orSortedSet<T>
, whereT
satisfies 2, 3 or 4 above. The resulting collection is read-only.
The reason for these requirements is that the value comes in as a string. The runtime needs to know how to convert a string to the type to inject. The reason for the exception is that there is an initial resource model validation on startup. This validation checks to make sure all your injection points are valid. It sees that the injected type
MyRequest
doesn't meet any of the above requirements, and throws an exception.
Basically you with points 2 and 3, you will need to parse the string yourself, for instance
public class MyRequest {
public static MyRequest fromString(string param) {
// 1. Parse string
// 2. Create MyRequest request;
return request;
}
ParamConverterProvider and ParamConverter. With the first one we simply tell the runtime whether we’re able to convert String to a particular type and with the second one we’re doing the actual conversion.
JAX-RS 2.0 implementations have to support the following types:
- Primitive types.
- Types that have a constructor that accepts a single String argument.
- Types that have a static method named valueOf or fromString with a single String argument that return an instance of the type. If both methods are present then valueOf MUST be used unless the type is an enum in which case fromString MUST be used.
- List<T>, Set<T>, or SortedSet<T>, where T satisfies 2 or 3 above.
This basically tells us that when there are only a few classes which we want to inject it’s sufficient to create static methods fromString /valueOf in these classes (or make sure the classes have a constructor which accepts one string argument) and we can use them as injection targets.
http://stackoverflow.com/questions/31612687/jackson-jsondeserialize-not-being-called-for-queryparamMessageBodyReader
s aren't used for @QueryParam
. You seem to be expecting the Jackson MessageBodyReader
to handle this deserialization, but it doesn't work like that.
Instead you will want to use a
ParamConverter
, which will need to be registered through a ParamConverterProvider
.@Provider
public class LocalDateParamConverterProvider implements ParamConverterProvider {
final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");
@Override
public <T> ParamConverter<T> getConverter(
Class<T> rawType, Type genericType, Annotation[] antns) {
if (LocalDate.class == rawType) {
return new ParamConverter<T>() {
@Override
public T fromString(String string) {
try {
LocalDate localDate = LocalDate.parse(string, formatter);
return rawType.cast(localDate);
} catch (Exception ex) {
throw new BadRequestException(ex);
}
}
@Override
public String toString(T t) {
LocalDate localDate = (LocalDate) t;
return formatter.format(localDate);
}
};
}
return null;
}
}
http://docs.oracle.com/javaee/6/tutorial/doc/gknav.html
A subresource locator returns an object that will handle an HTTP request. The method must not be annotated with a request method designator. You must declare a subresource locator within a subresource class, and only subresource locators are used for runtime resource resolution.
The following code snippet shows a subresource locator:
// Root resource class @Path("/employeeinfo") public class EmployeeInfo { // Subresource locator: obtains the subresource Employee // from the path /employeeinfo/employees/{empid} @Path("/employees/{empid}") public Employee getEmployee(@PathParam("empid") String id) { // Find the Employee based on the id path parameter Employee emp = ...; ... return emp; } } // Subresource class public class Employee { // Subresource method: returns the employee's last name @GET @Path("/lastname") public String getEmployeeLastName() { ... return lastName } }
http://www.justinleegrant.com/?p=516
Jersey, by default uses HK2 (aka Hundred Kilobyte Kernel) for Dependency Injection. This was developed by Oracle for the Glassfish Application Server. HK2 follows the the JSR-330 specification entirely. What does that mean? It means that this library can be swapped out for another with ease. So, if you develop with it, just remember that you can swap it out later. Unfortunately, with Jersey, they are using HK2 for Dependency Injection, so you are forced to either use it, or bridge it with the Spring Bridge or Guice Bridge (there may be others, but those are the most popular DI libraries right now).
@javax.inject.Contract | Annotation to identify interfaces that match a component |
@javax.inject.Service | Annotation to identify components that can be injected – used for scanning |
@javax.inject.Inject | Inject an instantiated class into an placeholder variable or method |
@javax.inject.Named | Differentiate between different objects of the same type |
@javax.inject.Qualifier | Used for annotating new annotations (because named annotations are evil) |
@javax.inject.Scope | By placing this annotation, you can tell the injector to retain the instance for possible reuse in a later injection |
@javax.inject.Singleton | Since HK2 defines that everything is a Prototype, this is necessary for a Singleton instance. Please note, this doesn’t apply when using the @Service annotation (which you should be using most of the time anyways), which is a singleton |
Lastly, we need to identify where you need these and apply the @Inject annotation. I advise people to use constructor injection, which ensures all mandatory properties have been satisfied, and it is simply not possible to instantiate an object in an invalid state. Plus, it’s significantly easier to test this way.
https://hk2.java.net/spring-bridge/
http://stackoverflow.com/questions/26230642/jersey-hk2-injecting-service-annotated-classes
we have moved on with the project and eventually gave up on hk2; instead we rely on spring bridge and spring for DI.
https://newfivefour.com/java-jersey-dependency-injection.html
https://github.com/jersey/jersey/tree/master/examples/helloworld-spring-webapp
http://stackoverflow.com/questions/30987153/is-it-possible-to-construct-an-object-partially-with-spring-di-and-partially-wit
It should work. Given you have the required Spring-Jersey integration dependency[1] and have correctly configured the application[2]
What happens is HK2 (Jersey's DI framework) will look for an
https://hk2.java.net/2.5.0-b05/introduction.htmlInjectionResolver
for the @Autowired
annotation, in order to resolve the dependency. The jersey-spring3
dependency has the AutowiredInjectionResolver
, which holds a reference to Spring's ApplicationContext
. From there it's just matter of looking it up in the application context, to resolve the dependency.https://hk2.java.net/2.5.0-b05/introduction.html
* Jersey Spring integration example.
* Demonstrate how to inject a Spring bean into a Jersey managed JAX-RS resource class.
@Scope("request")
The
@Component
annotation declares that the class is a Spring bean class. The @Scope("request")
annotation declares that instances of this class will be instantiated within the scope of the HTTP request. This highlights a difference between the default scopes for JAX-RS or Jersey and Spring. The default scope for JAX-RS is per request. By comparison, the default scope for Spring is a singleton, that is, one instance per web application. See Supported Scopes for more information about the scopes that Jersey supports.
Jersey supports the following Spring scopes:
- Request. Scopes a single Spring bean definition to the lifecycle of a single HTTP request, that is, each HTTP request has its own instance of a Spring bean created from a single Spring bean definition. This scope requires that you declare the Spring
RequestContextListener
servlet context in theweb.xml
file for the web application. - Singleton. Scopes a single Spring bean definition to a single object instance per web application.
- Prototype. Scopes a single Spring bean definition to multiple object instances. A new Spring bean instance is created for each request for that specific bean.
According to the documentation https://jersey.java.net/documentation/latest/jaxrs-resources.html#d0e2030, Table 3.2. and if i remember, in jersey 1.x, the HttpServletRequest can be inject into resource's field directly. but now i only can inject the HttpServletRequest using setter method mode or resource methods mode:
private @Context HttpServletRequest request; // this will not work private @Context HttpServletRequest request2; // valid via setter method @Context public void setRequest2(HttpServletRequest request2) { this.request2 = request2; } @Path("server") @POST @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) public AgentConfiguration register(AgentMachine agent, @Context HttpServletRequest request) throws RemoteException { // valid in resource method. }
http://stackoverflow.com/questions/32574887/purpose-of-component-annotation-on-spring-boot-starter-jersey-resources-in-spri
"To enable JAX-RS resources to work Spring functionality that requires proxying, such as Spring transaction management (with @Transactional), Spring Security and aspect oriented programming (such as @Aspect), the resources must themselves be managed by Spring, by annotating with @Component, @Service, @Controller or @Repository:"
Afaig, there is no preferred way for injecting UriInfo. It more or less depends on programming style guidelines you working or not working with. The injection should work while you are working in Jersey-managed components.
I for one, prefer the field injection variant.
I for one, prefer the field injection variant.
Please note: The object you will inject isn't UriInfo itself, it's a proxy pointing on the UriInfo for the current request. You can just picture it as a direct hotline to your container/connector.
The default scope is
https://jersey.java.net/documentation/latest/ioc.htmlRequest Scoped
.Jersey implementation allows you to directly inject HttpServletRequest instance into your JAX-RS components. It is quite straight forward to get the appropriate
HttpSession
instance out of the injected request instancehttp://download.oracle.com/otn-pub/jcp/jaxrs-2_0-fr-eval-spec/jsr339-jaxrs-2.0-final-spec.pdf?AuthParam=1464813534_ca389fd17d2b252b377a52c65cb808e5
Chapter 9 Context
@Context UriInfo
@Context HttpHeaders
@Context Request request,
The methods of Request allow a caller to determine the best matching representation variant and to evaluate
whether the current state of the resource matches any preconditions in the request. Precondition support
methods return a ResponseBuilder that can be returned to the client to inform it that the request preconditions
were not met. E.g. the following checks if the current entity tag matches any preconditions in the
request before updating the resource:
. An instance of SecurityContext can be injected into a class field or method parameter using the
@Context annotation
By default the life-cycle of root resource classes is per-request which, namely that a new instance of a root resource class is created every time the request URI path matches the root resource. This makes for a very natural programming model where constructors and fields can be utilized (as in the previous section showing the constructor of the
SparklinesResource
class) without concern for multiple concurrent requests to the same resource.
In general this is unlikely to be a cause of performance issues. Class construction and garbage collection of JVMs has vastly improved over the years and many objects will be created and discarded to serve and process the HTTP request and return the HTTP response.
Instances of singleton root resource classes can be declared by an instance of Application.
Request scope | @RequestScoped (or none) | org.glassfish.jersey.process.internal.RequestScoped | Default lifecycle (applied when no annotation is present). In this scope the resource instance is created for each new request and used for processing of this request. If the resource is used more than one time in the request processing, always the same instance will be used. This can happen when a resource is a sub resource is returned more times during the matching. In this situation only on instance will server the requests. |
Per-lookup scope | @PerLookup | org.glassfish.hk2.api.PerLookup | In this scope the resource instance is created every time it is needed for the processing even it handles the same request. |
Singleton | @Singleton | javax.inject.Singleton | In this scope there is only one instance per jax-rs application. Singleton resource can be either annotated with @Singleton and its class can be registered using the instance of Application. You can also create singletons by registering singleton instances into Application. |
Class fields | Inject value directly into the field of the class. The field can be private and must not be final. Cannot be used in Singleton scope except proxiable types mentioned above. |
Constructor parameters | The constructor will be invoked with injected values. If more constructors exists the one with the most injectable parameters will be invoked. Cannot be used in Singleton scope except proxiable types mentioned above. |
Resource methods | The resource methods (these annotated with @GET, @POST, ...) can contain parameters that can be injected when the resource method is executed. Can be used in any scope. |
When deploying a JAX-RS application using servlet then ServletConfig, ServletContext, HttpServletRequest and HttpServletResponse are available using @Context.
http://stackoverflow.com/questions/18914130/when-to-use-singleton-annotation-of-jerseyhttp://www.theotherian.com/2013/08/jersey-client-2.0-httpclient-timeouts-max-connections.html
The defaults when using HttpClient are as follows:
- Infinite connection and read timeouts
- By default when using Jersey's
ApacheConnector
you will get an instance ofBasicClientConnectionManager
which limits you to a single connection (though it is thread safe) - If you're configuring a
PoolingClientConnectionManager
instead, you'll have a maximum of 20 total connections with a maximum of 2 connections per host (or route)
To begin, we need to start with a class called
ClientConfig clientConfig = new ClientConfig();ClientConfig
. Jersey uses this to configure client instances via its ClientBuilder
API. We can set the connection and read timeouts with this class, as shown below:// values are in milliseconds
clientConfig.property(ClientProperties.READ_TIMEOUT, 2000);
clientConfig.property(ClientProperties.CONNECT_TIMEOUT, 500);
using httpclient with connection pooling
Now let's set up a ClientConnectionManager that uses pooling. We should also set the limits on the number of connections a little bit higher, since 20 total and 2 per host is on the low side (we'll use 100 and 20 instead):
PoolingClientConnectionManager connectionManager = new PoolingClientConnectionManager();
connectionManager.setMaxTotal(100);
connectionManager.setDefaultMaxPerRoute(20);
You can also be much more fine grained about how many connections per host are allowed with the setMaxPerRoute method. For example, let's say it was ok to have 40 max connections when hitting localhost:
connectionManager.setMaxPerRoute(new HttpRoute(new HttpHost("localhost")), 40);
We need to create a new ApacheConnector from the configuration, which specifies the pooled connection manager, and then set the connector in the configuration
ClientConfig clientConfig = ...;
PoolingClientConnectionManager connectionManager = ...;
// tell the config about the connection manager
clientConfig.property(ApacheClientProperties.CONNECTION_MANAGER, connectionManager);
// tell the connector about the config, which includes the connection manager and timeouts
ApacheConnector connector = new ApacheConnector(clientConfig);
// tell the config about the connector
clientConfig.connector(connector);
client.register(JacksonFeature.class);
In Jersey 1.x it was suggested to reuse Client instances (see here for details). In Jersey 2, reusing Client instances is still recommended, but as such it is not sufficient to keep things running efficiently. Application performance can easily be undermined here. Related documentation could be found in Jersey User Guide and the key sentence is quoted bellow:
The configuration principles used in JAX-RS client API apply to WebTarget as well.The documentation does not state this explicitly, so i will write it here in bold once more: be careful when touching configuration of a web target!. What does it mean? Whenever you create a new web target with updated configuration, Jersey will effectively create a new client runtime. To keep your application performing well, you should think of reusing all such web targets.
Tip 2: Avoid WebTarget.register()
If you need to register some extra components, do it on the client already to prevent another client runtime creation. If you need another runtime, just try to register things once and reuse the resulting target instance.
Tip 3: Avoid WebTarget.property()
The same applies to updating properties. These you can happily set on an Invocation or its builder
Tip 4: Use response.close() to release network connections!
When i wrote a simple test to get data for the above graph, i was getting short of available network ports. The problem is well described e.g. here. To avoid this i had to close responses. So as the last tip i recommend you close coming responses as well.
If you are closing 500 connection per second you will run out of sockets. If you are connecting to the same locations (web servers) that use keepalive you can implement connection pools, so you don't close and reopen sockets.
This will save cpu too.
Use of tcp_tw_recycle and tcp_tw_reuse can result in packets coming in from the previous
connecction, that is why there is a 1 minute wait for the packets to clear.
connecction, that is why there is a 1 minute wait for the packets to clear.
Another important ramification of the ephemeral port range is that it limits the maximum number of connections from one machine to a specific service on a remote machine! The TCP/IP protocol uses the connection's 4-tuple to distinguish between connections, so if the ephemeral port range is only 4000 ports wide, that means that there can only be 4000 unique connections from a client machine to a remote service at one time.
So maybe you run out of available ports. To get the number of available ports, see
$ cat /proc/sys/net/ipv4/ip_local_port_range
32768 61000
The output is from my Ubuntu system, where I'd have 28,232 ports for client connections. Hence, your test would fail as soon as you have 280+ clients.
Asynchttps://jersey.java.net/documentation/latest/async.html
Request processing on the server works by default in a synchronous processing mode, which means that a client connection of a request is processed in a single I/O container thread. Once the thread processing the request returns to the I/O container, the container can safely assume that the request processing is finished and that the client connection can be safely released including all the resources associated with the connection. This model is typically sufficient for processing of requests for which the processing resource method execution takes a relatively short time. However, in cases where a resource method execution is known to take a long time to compute the result, server-side asynchronous processing model should be used. In this model, the association between a request processing thread and client connection is broken. I/O container that handles incoming request may no longer assume that a client connection can be safely closed when a request processing thread returns. Instead a facility for explicitly suspending, resuming and closing client connections needs to be exposed. Note that the use of server-side asynchronous processing model will not improve the request processing time perceived by the client. It will however increase the throughput of the server, by releasing the initial request processing thread back to the I/O container while the request may still be waiting in a queue for processing or the processing may still be running on another dedicated thread. The released I/O container thread can be used to accept and process new incoming request connections.
http://stackoverflow.com/questions/20556200/jersey-async-containerrequestfilter
https://jersey.java.net/documentation/latest/filters-and-interceptors.html
All the request filters shown above was implemented as post-matching filters. It means that the filters would be applied only after a suitable resource method has been selected to process the actual request i.e. after request matching happens. Request matching is the process of finding a resource method that should be executed based on the request path and other request parameters. Since post-matching request filters are invoked when a particular resource method has already been selected, such filters can not influence the resource method matching process.
To overcome the above described limitation, there is a possibility to mark a server request filter as a pre-matching filter, i.e. to annotate the filter class with the @PreMatchingannotation. Pre-matching filters are request filters that are executed before the request matching is started. Thanks to this, pre-matching request filters have the possibility to influence which method will be matched. Such a pre-matching request filter example is shown here:
@PreMatching
public
class
PreMatchingFilter
implements
ContainerRequestFilter {
@Override
public
void
filter(ContainerRequestContext requestContext)
throws
IOException {
// change all PUT methods to POST
if
(requestContext.getMethod().equals(
"PUT"
)) {
requestContext.setMethod(
"POST"
);
}
}
}
As written above, pre-matching filters can fully influence the request matching process, which means you can even modify request URI in a pre-matching filter by invoking the
setRequestUri(URI)
method of ContainerRequestFilter
so that a different resource would be matched.http://stackoverflow.com/questions/25701658/integrating-jersey-2-and-spring-with-java-based-configuration
https://jersey.java.net/documentation/latest/spring.html
If you want to use Jersey Spring DI support you will need to add the
jersey-spring3
module into the list of your dependencies:
1
2
3
4
5
| < dependency > < groupId >org.glassfish.jersey.ext</ groupId > < artifactId >jersey-spring3</ artifactId > < version >2.22.2</ version > </ dependency > |
<servlet>
<servlet-name>SpringApplication</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>org.glassfish.jersey.examples.helloworld.spring.MyApplication</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
http://www.theotherian.com/2013/07/creating-resource-filters-with-jersey.html
public class IE6NotSupportedFilter implements ContainerRequestFilter {
@Override
public void filter(ContainerRequestContext requestContext) throws IOException {
if (isIE6Browser(requestContext.getHeaderString("User-Agent"))) {
requestContext.abortWith(Response.status(Status.PRECONDITION_FAILED).entity(getFailurePage()).build());
}
}
}
Now that we have an annotation, a filter, and a way to link the filter to a resource, we need to tell our application to invoke this upon startup.
http://blog.dejavu.sk/2013/11/19/registering-resources-and-providers-in-jersey-2/@ApplicationPath("/")
public class MyApplication extends ResourceConfig {
public MyApplication() {
// Register resources and providers using package-scanning.
packages("my.package");
// Register my custom provider - not needed if it's in my.package.
register(SecurityRequestFilter.class);
// Register an instance of LoggingFilter.
register(new LoggingFilter(LOGGER, true));
// Enable Tracing support.
property(ServerProperties.TRACING, "ALL");
}
}
http://stackoverflow.com/questions/18268827/how-do-i-get-jersey-2-2-jax-rs-to-generate-log-output-including-json-request
// Enable LoggingFilter & output entity.
registerInstances(new LoggingFilter(Logger.getLogger(MyApplication.class.getName()), true));
<servlet>
<servlet-name>my.package.MyApplication</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<!-- Register JAX-RS Application, if needed. -->
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>my.package.MyApplication</param-value>
</init-param>
<!-- Register resources and providers under my.package. -->
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>my.package</param-value>
</init-param>
<!-- Register my custom provider (not needed if it's in my.package) AND LoggingFilter. -->
<init-param>
<param-name>jersey.config.server.provider.classnames</param-name>
<param-value>my.package.SecurityRequestFilter;org.glassfish.jersey.filter.LoggingFilter</param-value>
</init-param>
<!-- Enable Tracing support. -->
<init-param>
<param-name>jersey.config.server.tracing</param-name>
<param-value>ALL</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
Filters prioties:
http://stackoverflow.com/questions/26989608/jersey-2-3-setting-priority-for-containerrequestfilter
Option 1:
Use the
@Priorty
for your filter classes, passing in a value (e.g. @Priority(1)
). The lower the number, the higher the priority (Don't need for anything special in web.xml or Application subclass)@Priority(6000)
public class MyFilter1 ... {}
@Priority(6001)
public class MyFilter2 ... {}
See Priorities
Option 2:
Configure it programmatically into the application via an inject-able
Configurable
. Something like@ApplicationPath("/")
public class MyApplication extends Applciation {
public MyApplication(@Context Configurable configurable) {
configurable.register(MyFilter1.class, 1000);
configurable.register(MyFilter2.class, 1001);
}
}
Or with
ResourceConfig
simply calling register
without the injected Configurable
. See the API for overloaded register
public ResourceConfig register(Object component, int bindingPriority)
e.g.
public class MyApplication extends ResourceConfig {
public MyApplication() {
...
register(TestFilter.class, 6000);
register(TestFilter2.class, 6001);*/
}
}
Note:
Just an FYI, there are built in constants from the
Priorites
class.public final class Priorities {
private Priorities() { }
public static final int AUTHENTICATION = 1000;
public static final int AUTHORIZATION = 2000;
public static final int HEADER_DECORATOR = 3000;
public static final int ENTITY_CODER = 4000;
public static final int USER = 5000;
}
Jersey client:
https://jersey.java.net/documentation/latest/client.html
Client client = ClientBuilder.newClient(
new
ClientConfig()
.register(MyClientResponseFilter.
class
)
.register(
new
AnotherClientFilter());
Client client = ClientBuilder.newClient();
Form form =
new
Form();
form.param(
"x"
,
"foo"
);
form.param(
"y"
,
"bar"
);
MyJAXBBean bean =
target.request(MediaType.APPLICATION_JSON_TYPE)
.post(Entity.entity(form,MediaType.APPLICATION_FORM_URLENCODED_TYPE),
MyJAXBBean.
class
);
http://howtodoinjava.com/jersey/jersey-restful-client-examples/
Client client = ClientBuilder.newClient( new ClientConfig().register( LoggingFilter. class ) ); Invocation.Builder invocationBuilder = webTarget.request(MediaType.APPLICATION_XML); Response response = invocationBuilder.get(); Employees employees = response.readEntity(Employees. class ); |
Invocation.Builder invocationBuilder = webTarget.request(MediaType.APPLICATION_XML);
Response response = invocationBuilder.post(Entity.entity(emp, MediaType.APPLICATION_XML));
System.out.println(response.getStatus());
System.out.println(response.readEntity(String.
class
));
http://stackoverflow.com/questions/29434312/is-it-possible-in-jersey-to-have-access-to-an-injected-httpservletrequest-inste
Or inject it as a method param. Singleton or not, you will get the actual instance
@GET
public String getType(@Context HttpServletRequest request) {
return request.getClass().getName();
}
Issues:https://java.net/jira/browse/JERSEY-2506
Issues:
jersey-spring3 doesn't support Spring Java config properly
https://java.net/jira/browse/JERSEY-2038
The new jersey-spring3 module expects an XML based spring configuration
If you are using spring boot with jersey and plan to deploy the resulting WAR on a JBoss container, this issue will probably randomly bite you during startup. If the org.glassfish.jersey.server.spring.SpringWebApplicationInitializer is detected on the classpath first and runs before org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration initializer, you will most likely end up with a duplicate context exception. In a spring boot app that already extends the SpringBootServletInitializer, all you need is this:
@Priority(value = 1) public class MySpringWebInitializer implements WebApplicationInitializer { @Override public void onStartup(ServletContext container) { //Tell jersey-spring3 the context is already initialized container.setInitParameter("contextConfigLocation", "NOTNULL"); } }
public class SpringWebApplicationInitializer implements WebApplicationInitializer {
private static final String PAR_NAME_CTX_CONFIG_LOCATION = "contextConfigLocation";
@Override
public void onStartup(ServletContext sc) throws ServletException {
if (sc.getInitParameter(PAR_NAME_CTX_CONFIG_LOCATION) == null) {
LOGGER.config(LocalizationMessages.REGISTERING_CTX_LOADER_LISTENER());
sc.setInitParameter(PAR_NAME_CTX_CONFIG_LOCATION, "classpath:applicationContext.xml");
sc.addListener("org.springframework.web.context.ContextLoaderListener");
sc.addListener("org.springframework.web.context.request.RequestContextListener");
} else {
LOGGER.config(LocalizationMessages.SKIPPING_CTX_LODAER_LISTENER_REGISTRATION());
}
}
}
How to make Jersey to use SLF4J instead of JUL?
http://stackoverflow.com/questions/33746425/pure-jerseytest-without-letting-spring-messing-with-servicesHow to make Jersey to use SLF4J instead of JUL?
http://stackoverflow.com/questions/4121722/how-to-make-jersey-to-use-slf4j-instead-of-jul
If you are using the client API you can manually redirect the logs to slf4j (note that it may break in future versions although it seems unlikely):
Logger LOG = LoggerFactory.getLogger(MyClass.class); //slf4j logger
WebTarget ws = ClientBuilder.newClient(config)
.register(new LoggingFilter(new JulFacade(), true));
private static class JulFacade extends java.util.logging.Logger {
JulFacade() { super("Jersey", null); }
@Override public void info(String msg) { LOG.info(msg); }
}
The best way to do it is through a custom Listener. Being initialized before JSF servlet it should configure jul-to-slf4j bridge in
contextInitialized(ServletContextEvent)
.
I try to use SLF4JBridgeHandler to bridge JUL to SLF4J and I've got a lot of uninteresting log in my log file
I need to filter but it seems to work fine
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
connectionManager.setMaxTotal(maxTotal);
connectionManager.setDefaultMaxPerRoute(maxPerRoute());
ClientConfig clientConfig = new ClientConfig();
clientConfig.property(ClientProperties.READ_TIMEOUT, readTimeout);
clientConfig.property(ClientProperties.CONNECT_TIMEOUT, connectionTimeout);
clientConfig.property(ApacheClientProperties.CONNECTION_MANAGER, connectionManager);
clientConfig.property(ClientProperties.FOLLOW_REDIRECTS, false);
clientConfig.property(ClientProperties.PROXY_URI, proxy);
ApacheConnectorProvider connector = new ApacheConnectorProvider();
clientConfig.connectorProvider(connector);
JacksonJaxbJsonProvider jacksonProvider = new JacksonJaxbJsonProvider();
jacksonProvider.setMapper(new ObjectMapper());
clientConfig.register(jacksonProvider);
clientConfig.property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, suppressHttpValidation);
http://blogs.sourceallies.com/2011/08/spring-injection-with-resource-and-autowired/
Spring Annotation Style Best Practices
- Explicitly name your component [@Component(“beanName”)]
- Use ‘@Resource’ with the ‘name’ attribute [@Resource(name=”beanName”)]
- Avoid ‘@Qualifier’ annotations unless you want to create a list of similar beans. For example you may want to mark a set of rules with a specific ‘@Qualifier’ annotation. This approach makes it simple to inject a group of rule classes into a list that can be used for processing data.
- Scan specific packages for components [context:component-scan base-package=”com.sourceallies.person”]. While this will result in more component-scan configurations it reduces the chance that you’ll add unnecessary components to your Spring context.
RESTful Java Web Services - Second Edition
Reporting errors using ResponseBuilder
Reporting errors using WebApplicationException
Some of the exceptions extended from WebApplicationException are as follows: BadRequestException, ForbiddenException, NotAcceptableException, NotAllowedException, NotAuthorizedException, NotFoundException, NotSupportedException, RedirectionException, InternalServerErrorException, and ServiceUnavailableException
in the request processing cycle, the default exception mapper class deployed by the JAX-RS runtime will intercept the exception thrown by the method and will generate an appropriate HTTP response object. WebApplicationException can be created by wrapping the response content, error text, or HTTP status code.
@NotNull
@Null
@AssertTrue
@AssertFalse
@DecimalMax
@DecimalMin
@Digits
@Max
@Min
@Future
The annotated variable must be a date in the future.
@Past
@Pattern
@Size
MARSHALLING CSV REPRESENTATION TO JAVA OBJECTS WITH MESSAGEBODYREADER
MARSHALLING JAVA OBJECTS TO THE CSV REPRESENTATION WITH MESSAGEBODYWRITER
public void findAllDepartments(@Suspended final
AsyncResponse asyncResponse) {
//Set time out for the request
asyncResponse.setTimeout(10, TimeUnit.SECONDS);
Runnable longRunningDeptQuery = new Runnable(){
EntityManagerFactory emf =
Persistence.
createEntityManagerFactory("HRPersistenceUnit");
EntityManager entityManagerLocal = emf.createEntityManager();
public void run() {
CriteriaQuery cq =
entityManagerLocal.
getCriteriaBuilder().createQuery();
cq.select(cq.from(Department.class));
List<Department> depts =
entityManagerLocal.createQuery(cq).getResultList();
GenericEntity<List<Department>> entity
= new GenericEntity<List<Department>>(depts) {
};
asyncResponse.
resume(Response.ok().entity(entity).build());
}
};
executorService.execute(longRunningDeptQuery);
}
WebTarget webTarget =
client.target(BASE_URI).path("hr").path("departments");
AsyncInvoker asyncInvoker = webTarget.
request(javax.ws.rs.core.MediaType.APPLICATION_JSON).async();
Future<List<Department>> entity = asyncInvoker.get(
new InvocationCallback<List<Department>>() {
@Override
public void completed(List<Department> response) {
//Call back on request completion
//You can process the result here, if required
client.close();
}
@Override
public void failed(Throwable throwable) {
//Call back on request failure
//Handle the exception
//log(...) method definition is not shown here
log(throwable);
}
});
@Provider
public class CORSFilter implements ContainerResponseFilter {
@Override
public void filter(ContainerRequestContext requestContext,
ContainerResponseContext cres) throws IOException {
//Specify CORS headers: * represents allow all values
cres.getHeaders().add("Access-Control-Allow-Origin", "*");
cres.getHeaders().add("Access-Control-Allow-Headers",
"*");
cres.getHeaders().add("Access-Control-Allow-Credentials",
"true");
cres.getHeaders().add("Access-Control-Allow-Methods",
"GET, POST, PUT, DELETE, OPTIONS, HEAD");
cres.getHeaders().add("Access-Control-Max-Age",
"1209600");
}
}
You use the javax.ws.rs.ext.ReaderInterceptor interface to intercept and manipulate the incoming message body.
While processing a request, the request filter with the least priority will be executed first and followed by the next one in the sequence. While processing a response, filters are executed in the reverse order.
Selectively applying filters and interceptors on REST resources by using @NameBinding
@NameBinding
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD,ElementType.TYPE})
public @interface RequestLogger {
}
@RequestLogger
public class RequestLoggerFilter implements ContainerRequestFilter {
@Override
public void filter(ContainerRequestContext requestContext)
throws IOException {
//Method implementation is not shown in this
//example for brevity
}
}
The javax.ws.rs.container.DynamicFeature contract is used by the JAX-RS runtime to register providers, such as interceptors and filters, to a particular resource class or method during application deployment.
<plugin>
<groupId>org.raml.plugins</groupId>
<artifactId>jaxrs-raml-maven-plugin</artifactId>
<!-- Specify the appropriate version -->
<version>1.3.3</version>
<configuration>
<sourceDirectory>
${basedir}/src/main/java
</sourceDirectory>
<baseUrl>
http://localhost:8080/hrapp/webresources
</baseUrl>
<title>Department Resource</title>
<outputFile>
${project.build.directory}/generated-sources/dept-api.raml
</outputFile>
<removeOldOutput>true</removeOldOutput>
</configuration>
<executions>
<execution>
<goals>
<goal>generate-raml</goal>
</goals>
<phase>process-classes</phase>
</execution>
</executions>
</plugin>
Including the version in a HTTP Accept header – the media type versioning
The media type versioning approach adds the version information to the media content type. You can do this by introducing custom vendor media types that hold the version information along with the media type details.
Accept: application/vnd.{app_name}.{version}+{response_type}
@Stateless
@Api(value = "/departments", description = "Get departments details")
@ApiOperation(value = "Find department by id",
notes = "Specify a valid department id",
response = Department.class)
@ApiResponses(value = {
@ApiResponse(code = 200, message = "successful operation"),
@ApiResponse(code = 404, message = "Department not found")
})
@ApiParam(value = "The department id", required = true)
@Produces({"application/json", "application/vnd.packtpub.v1+json"})
@Consumes({"application/json", "application/vnd.packtpub.v1+json"})
public class DepartmentResource{
//The following method is a modified implementation
//to read the list of employees, so the version number has been
//incremented
@GET
@Produces({"application/vnd.packtpub.v2+json"})
public List<Department> findDepartmentsInRangeV2(
@QueryParam("offset") @DefaultValue("1") Integer offset,
@QueryParam("limit") @DefaultValue("20") Integer limit) {
return findDepartmentEntitiesWithDetails(offset, limit);
}
The REST API client can specify an X-HTTP-Method-Override request header with a string value containing either PUT, PATCH, or DELETE. When the server gets the request, the server replaces the POST method call with the method string value set for X-HTTP-Method-Override.
JAX-RS allows you to implement this behavior via prematching javax.ws.rs.container.ContainerRequestFilter.
@PreMatching
// A provider impl for handling the X-Http-Method-Override header
public class HttpOverride implements ContainerRequestFilter {
public void filter(ContainerRequestContext ctx) {
String method = ctx.getHeaderString
("X-Http-Method-Override");
//override header should only be accepted on POST
if (method != null
&& ctx.getMethod().equals("POST"))
//Set the method to the X-HTTP-Method-Override header value
ctx.setMethod(method);
}
}
You can use PUT for creating or updating a resource when the client has the full resource content available. In this case, all values are with the client, and the server does not generate a value for any of the fields.
You will use POST for creating or updating a resource if the client has only partial resource content available. Note that you are losing the idempotency support with POST. An idempotent method means that you can call the same API multiple times without changing the state. This is not true for the POST method; each POST method call may result in a server state change. PUT is idempotent, and POST is not
Implementing partial response
/employees/1234?select=firstName,lastName,email
SelectableEntityFilteringFeature
https://github.com/jersey/jersey/tree/2.18/examples/entity-filtering-selectable
register(SelectableEntityFilteringFeature.class);
property(SelectableEntityFilteringFeature.QUERY_PARAM_NAME, "select");
// Configure MOXy Json provider. Comment this line to use Jackson. Uncomment to use MOXy.
register(new MoxyJsonConfig().setFormattedOutput(true).resolver());
final HttpServer server = GrizzlyHttpServerFactory.createHttpServer(BASE_URI,
new SelectableEntityFilteringApplication());
UriBuilder builder = uriInfo.getAbsolutePathBuilder();
builder.path(deptId.toString());
return Response.created(builder.build()).build();
http://stackoverflow.com/questions/38133680/why-do-we-need-component-spring-annotation-for-jersey-resource-in-spring-boot-s
You don't need it. Jersey uses HK2 as it's internal DI framework, and HK2 has a Spring bridge. This is what's used internally to bridge Spring components into the HK2 IoC container, so that they can be injected into Jersey components. And Jersey implements an
AutowiredInjectionResolver
1 that allows for injection of Spring components using @Autowired
. You don't even need @Autowired
though. All the Spring components can be injected with the normal @Inject
.
The only drawback I've ran into, not making the Jersey components a Spring
@Component
is that it doesn't support @Value
when you want to inject property values.
The one thing I don't like is that when you declare something a Spring
@Component
, it automatically makes it a singleton. But Jersey resources are by default request scoped. You can add a Spring @Scope("request")
, and it should change the resource to a request scoped resource. Jersey hasdeclared the Spring RequestScope, so we can use it. How exactly it ties in to Jersey's request scope, I am not a hundred percent sure. I ran into a problem a while back. I can't remember what it was, but that has kept me from ever using the Spring request scope again.
Assuming I want to keep all my resources request scoped, I would take sticking to the normal Jersey request scope, and not being able to inject
@Value
s, over having to use Spring's request scope. Maybe I'm imagining things, and there was no issue using it, but personally I'll just stick to what I know works :-)