What is the Jersey 2 equivalent of FEATURE_NORMALIZE_URI?
Answering my own question: It doesn't look like Jersey 2 has an equivalent feature, but it's quite simple to implement yourself:
/**
* Normalizes incoming URIs.
* <p>
* #author Gili Tzabari
*/
#PreMatching
public class NormalizeUriFilter implements ContainerRequestFilter
{
#Override
public void filter(ContainerRequestContext requestContext) throws IOException
{
URI requestUri = requestContext.getUriInfo().getRequestUri();
URI normalized = requestUri.normalize();
if (!requestUri.equals(normalized))
requestContext.setRequestUri(normalized);
}
}
Don't forget to register() the filter in your Application.
Related
My goal is to add a dynamic Predicate to the findAll method of QuerydslPredicateExecutor. This should be used to filter entities based on the organization of the currently active user.
I'm using Spring Data together with Spring Data REST to get the REST API out of the box, i.e. I have no dedicated REST service where I can intercept the incoming data and modify it.
By extending a SimpleJpaRepository and registering it with #EnableJpaRepositories it is possible to overwrite a method and change its default behavior. I wanted to do this, but my Repository interfaces are implementing QuerydslPredicateExecutor and this does not seem to work.
My failed approach started as:
public class CustomizedJpaRepositoryIml<T, ID extends Serializable> extends
SimpleJpaRepository<T, ID> {
private EntityManager entityManager;
#Autowired
public CustomizedJpaRepositoryIml(JpaEntityInformation<T, ?>
entityInformation,
EntityManager entityManager) {
super(entityInformation, entityManager);
this.entityManager = entityManager;
}
}
but obviously this extension does not provide the method to be overwritten. I debugged how the implementing QuerydslJpaPredicateExecutor is wired, but this is rather complex and I see no way of plugging in here something easily.
Another idea was to use a filter intercepting the URL call and adding parameters but this does not sound nice.
I could also override the controller path for the finder with a #BasePathAwareController, but this would mean to do this for all entities I have and not in a single place.
Any ideas to achieve my goal? maybe there are also completely different options possible to achieve my goal of add additional filtering to the Querydsl Predicate
I found a way in the meanwhile. It requires to provide an own implementation of QuerydslPredicateExecutor. But this is not made easy in Spring Data. The answer is motivated by https://stackoverflow.com/a/53960209/3351474, but in the meanwhile a constructor has changed in newer Spring Data, why this cannot be taken 1:1.
I use a different example as in my question, but with this solution you have complete freedom also to add and append any Predicate. As an example I take here a customized Querydsl implementation using always the creationDate of an entity as sort criteria if nothing is is passed. I assume in this example that this column exists in some #MappedSuperClass for all entities. Use generated static metadata in real life instead the hard coded string "creationDate".
As first the wrapped delegating all CustomQuerydslJpaRepositoryIml delegating all methods to the QuerydslJpaPredicateExecutor:
/**
* Customized Querydsl JPA repository to apply custom filtering and sorting logic.
*
*/
public class CustomQuerydslJpaRepositoryIml<T> implements QuerydslPredicateExecutor<T> {
private final QuerydslJpaPredicateExecutor querydslPredicateExecutor;
public CustomQuerydslJpaRepositoryIml(QuerydslJpaPredicateExecutor querydslPredicateExecutor) {
this.querydslPredicateExecutor = querydslPredicateExecutor;
}
private Sort applyDefaultOrder(Sort sort) {
if (sort.isUnsorted()) {
return Sort.by("creationDate").ascending();
}
return sort;
}
private Pageable applyDefaultOrder(Pageable pageable) {
if (pageable.getSort().isUnsorted()) {
Sort defaultSort = Sort.by(AuditableEntity_.CREATION_DATE).ascending();
pageable = PageRequest.of(pageable.getPageNumber(), pageable.getPageSize(), defaultSort);
}
return pageable;
}
#Override
public Optional<T> findOne(Predicate predicate) {
return querydslPredicateExecutor.findOne(predicate);
}
#Override
public List<T> findAll(Predicate predicate) {
return querydslPredicateExecutor.findAll(predicate);
}
#Override
public List<T> findAll(Predicate predicate, Sort sort) {
return querydslPredicateExecutor.findAll(predicate, applyDefaultOrder(sort));
}
#Override
public List<T> findAll(Predicate predicate, OrderSpecifier<?>... orders) {
return querydslPredicateExecutor.findAll(predicate, orders);
}
#Override
public List<T> findAll(OrderSpecifier<?>... orders) {
return querydslPredicateExecutor.findAll(orders);
}
#Override
public Page<T> findAll(Predicate predicate, Pageable pageable) {
return querydslPredicateExecutor.findAll(predicate, applyDefaultOrder(pageable));
}
#Override
public long count(Predicate predicate) {
return querydslPredicateExecutor.count(predicate);
}
#Override
public boolean exists(Predicate predicate) {
return querydslPredicateExecutor.exists(predicate);
}
}
Next the CustomJpaRepositoryFactory doing the magic and providing the Querydsl wrapper class instead of the default one. The default one is passed as parameter and wrapped.
/**
* Custom JpaRepositoryFactory allowing to support a custom QuerydslJpaRepository.
*
*/
public class CustomJpaRepositoryFactory extends JpaRepositoryFactory {
/**
* Creates a new {#link JpaRepositoryFactory}.
*
* #param entityManager must not be {#literal null}
*/
public CustomJpaRepositoryFactory(EntityManager entityManager) {
super(entityManager);
}
#Override
protected RepositoryComposition.RepositoryFragments getRepositoryFragments(RepositoryMetadata metadata) {
final RepositoryComposition.RepositoryFragments[] modifiedFragments = {RepositoryComposition.RepositoryFragments.empty()};
RepositoryComposition.RepositoryFragments fragments = super.getRepositoryFragments(metadata);
// because QuerydslJpaPredicateExecutor is using som internal classes only a wrapper can be used.
fragments.stream().forEach(
f -> {
if (f.getImplementation().isPresent() &&
QuerydslJpaPredicateExecutor.class.isAssignableFrom(f.getImplementation().get().getClass())) {
modifiedFragments[0] = modifiedFragments[0].append(RepositoryFragment.implemented(
new CustomQuerydslJpaRepositoryIml((QuerydslJpaPredicateExecutor) f.getImplementation().get())));
} else {
modifiedFragments[0].append(f);
}
}
);
return modifiedFragments[0];
}
}
Finally the CustomJpaRepositoryFactoryBean. This must be registered with the Spring Boot application, to make Spring aware where to get the repository implementations from, e.g. with:
#SpringBootApplication
#EnableJpaRepositories(basePackages = "your.package",
repositoryFactoryBeanClass = CustomJpaRepositoryFactoryBean.class)
...
Here now the class:
public class CustomJpaRepositoryFactoryBean<T extends Repository<S, I>, S, I> extends JpaRepositoryFactoryBean<T, S, I> {
/**
* Creates a new {#link JpaRepositoryFactoryBean} for the given repository interface.
*
* #param repositoryInterface must not be {#literal null}.
*/
public CustomJpaRepositoryFactoryBean(Class<? extends T> repositoryInterface) {
super(repositoryInterface);
}
protected RepositoryFactorySupport createRepositoryFactory(EntityManager entityManager) {
return new CustomJpaRepositoryFactory(entityManager);
}
}
I'm trying to debug an web application running on Glassfish and I want to cause the server to return a CLIENT_ERROR or SERVER_ERROR.
The returned javax.ws.rs.core.Response to the calling server should include an entity. What is the best way to do this?
Create a filter and make it return the required Response:
javax.ws.rs.container.ContainerRequestFilter
#Provider
public class RequestFilter implements ContainerRequestFilter {
/** {#inheritDoc} */
#Override
public void filter(final ContainerRequestContext req) throws IOException {
if (req.getUriInfo().getPath().toLowerCase().contains("pathToMatch")) {
final Response newResp = Response.status(500).entity("<test>test</test>").type(MediaType.valueOf(MediaType.TEXT_HTML)).build();
req.abortWith(newResp);
}
}
}
We are planning on using Jersey's reference implementation for our REST APIs. As a prototype effort, I was also playing around with the ContainerRequestFilters and I implemented multiple of them. Is there a way in which we can control the order in which these filters are executed?
The scenario that I am thinking over here is to ensure that the security filter must be the first one to run, and if required establish the SecurityContext and then execute other filters.
Yes you can control this with the javax.annotation.Priority attribute and the default javax.ws.rs.Priorities. For example if you wanted:
Logging filter always runs first
Authentication filter should run next
Authorization filter should run next
Custom filter should always run after others
You could do:
#Priority(Integer.MIN_VALUE)
public class CustomLoggingFilter implements ContainerRequestFilter
{
#Override
public void filter(ContainerRequestContext requestContext) throws IOException
{
// DO LOGGING HERE, THIS RUNS FIRST
}
}
#Priority(Priorities.AUTHENTICATION)
public class AuthenticationFilter implements ContainerRequestFilter
{
#Override
public void filter(ContainerRequestContext requestContext) throws IOException
{
String authHeader = requestContext.getHeaderString(HttpHeaders.WWW_AUTHENTICATE);
// DO AUTHENTICATION HERE, THIS RUNS SECOND
}
}
#Priority(Priorities.AUTHORIZATION)
public class AuthorizationFilter implements ContainerRequestFilter
{
#Override
public void filter(ContainerRequestContext requestContext) throws IOException
{
String authHeader = requestContext.getHeaderString(HttpHeaders.AUTHORIZATION);
// DO AUTHORIZATION HERE, THIS RUNS THIRD
}
}
#Priority(Priorities.USER)
public class MyAwesomeStuffFilter implements ContainerRequestFilter
{
#Override
public void filter(ContainerRequestContext requestContext) throws IOException
{
// DO AWESOME STUFF HERE, THIS RUNS LAST
}
}
I have a little problem with a list that contains different types of elements and i would like to see if anyone of you have met the problem before. The issue should be solved with the use of #ExtraTypes, but it is not working for me, so i guess i am not using it correctly. So, the scenario is (bean names are changed for clarity):
GENERAL:
I am using GWT 2.5 with RequestFactory.
SERVER-SIDE:
I have a RootBean that contains, among other stuff, a List <ChildBean>.
This ChildBean contains some primitive attributes.
ChildBean is also extended by a MoreSpecificChildBean that inherits all the parent attributes and adds a few more.
The RootBean gets its list filled up with elements of type ChildBean and MoreSpecificChildBean depending on some logic.
CLIENT-SIDE:
IRootBeanProxy is a ValueProxy with these annotations:
#ProxyFor (value = RootBean.class)
#ExtraTypes ({IMoreSpecificChildBeanProxy.class})
and contains a list
List <IChildBeanProxy> getChildren ();
IChildBeanProxy is a ValueProxy:
#ProxyFor (value=ChildBean)
public interface IChildBeanProxy extends ValueProxy
IMoreSpecificChildBeanProxy is a ValueProxy:
#ProxyFor (value=MoreSpecificChildBean)
public interface IMoreSpecificChildBeanProxy extends IChildBeanProxy
the Request context has a method that returns Request and i added the #ExtraTypes annotation here too:
#Service (value = CompareService.class, locator = SpringServiceLocator.class)
#ExtraTypes ({IChildBeanProxy.class, IMoreSpecificChildBeanProxy.class})
public interface ICompareRequestContext extends RequestContext {
Request <IRootBeanProxy> compare (Integer id1, Integer id2);
Question
Supposedly with those annotations, RF should be aware of the existence of polymorphic inherited classes, but all i get in the client is an IRootBeanProxy with a list of IChildBeanProxy elements. This list includes the MoreSpecificChildBean, but in the shape of a IChildBeanProxy, so that i cannot tell it from the others.
So i am wondering what i am doing wrong, if i am setting the ExtraTypes annotation at the wrong place or something.
Anyone?
Thx for all the help!!
I do the exact same thing for quite a few classes but it will always return me the base type which I can iterate through and test for instanceof if needed. You will probably have to cast the object to the subclass. If you do not add the #ExtraTypes you will know because on the server side you will get a message stating that MoreSpecificChildBean cannot be sent to the client.
I only annotate the service and not the proxy, I ran into some quirks with 2.4 adding #ExtraTypes to the proxy.
/**
* Base proxy that all other metric proxies extend. It is used mainly for it's
* inheritence with the RequestFactory. It's concrete implementation is
* {#link MetricNumber}.
*
* #author chinshaw
*/
#ProxyFor(value = Metric.class, locator = IMetricEntityLocator.class)
public interface MetricProxy extends DatastoreObjectProxy {
/**
* Name of this object in the ui. This will commonly be extended by
* subclasses.
*/
public String NAME = "Generic Metric";
/**
* This is a list of types of outputs that the ui can support. This is
* typically used for listing types of supported Metrics in the operation
* output screen.
*
* #author chinshaw
*/
public enum MetricOutputType {
MetricNumber, MetricString, MetricCollection, MetricStaticChart, MetricDynamicChart
}
/**
* See {#link MetricNumber#setName(String)}
*
* #param name
*/
public void setName(String name);
/**
* See {#link MetricNumber#setContext(String)}
*
* #return name of the metric.
*/
public String getName();
/**
* Get the list of violations attached to this metric.
*
* #return
*/
public List<ViolationProxy> getViolations();
}
#ProxyFor(value = MetricNumber.class, locator = IMetricEntityLocator.class)
public interface MetricNumberProxy extends MetricProxy {
public List<NumberRangeProxy> getRanges();
public void setRanges(List<NumberRangeProxy> ranges);
}
...
#ProxyFor(value = MetricDouble.class, locator = IMetricEntityLocator.class)
public interface MetricDoubleProxy extends MetricNumberProxy {
/* Properties when fetching the object for with clause */
public static String[] PROPERTIES = {"ranges"};
public Double getValue();
}
...
#ProxyFor(value = MetricPlot.class, locator = IMetricEntityLocator.class)
public interface MetricPlotProxy extends MetricProxy {
/**
* UI Name of the object.
*/
public String NAME = "Static Plot";
public String getPlotUrl();
}
This is a made up method from because I usually always return composite classes that may contain a list of metrics. That being said this will return me the base type of metrics, and then I can cast them.
#ExtraTypes({ MetricProxy.class, MetricNumberProxy.class, MetricDoubleProxy.class, MetricIntegerProxy.class})
#Service(value = AnalyticsOperationDao.class, locator = DaoServiceLocator.class)
public interface AnalyticsOperationRequest extends DaoRequest<AnalyticsOperationProxy> {
Request<List<<MetricProxy>> getSomeMetrics();
}
Not an exact method I use but will work for getting a proxy of type.
context.getSomeMetrics().with(MetricNumber.PROPERTIES).fire(new Receiver<List<MetricProxy>>() {
public void onSuccess(List<MetricProxy> metrics) {
for (MetricProxy metric : metrics) {
if (metric instanceof MetricDoubleProxy) {
logger.info("Got a class of double " + metric.getValue());
}
}
}
}
You will know if you are missing an #ExtraTypes annotation when you get the error stated above.
Hope that helps
My app has many RPC calls, and they all have a .onFailure(Throwable caught) method. I have a class shared between the client and the server code NotLoggedInException. This is thrown by the server, if the user doesn't have the relevant permissions based on sessions/cookies/permissions etc.
Ideally I would like to handle this exception in one place BEFORE others are passed to the .onFailure() code, given how ubiquitous this handling is and needs to be for security. There is a GWT.setUncaughtExceptionHandler() but this appears to get called after the handling which isn't ideal (in case an .onFailure accidentally consumes too much).
Does anybody have an elegant solution to this? An ugly solution is to wrap the deferred binded .create() proxy in the same aggregated class implementing the async interface.
Sidenote: The server was issuing a redirect before, but I don't like this paradigm, and would prefer it to be handled by the eventbus of the app.
Update: ugly answer referred to above
public abstract class CustomAsyncCallback implements AsyncCallback{
#Override
public CustomAsyncCallback(AsyncCallback<T> callback)
{
this.wrap = callback ;
}
AsyncCallback<T> wrap ;
#Override
public void onFailure(Throwable caught) {
if (!handleException())
{
wrap.onFailure(caught) ;
}
}
#Override
public void onSuccess(T t) {
wrap.onSuccess(t) ;
}
}
public class WrapDeferredBinding implements RpcInterfaceAsync
{
RpcInterfaceAsync service = GWT.create(RpcInterface.class);
public void method1(int arg1, AsyncCallback<Boolean> callback)
{
service.method1(arg1, new CustomAsyncCallback<Boolean>(callback)) ;
}
public void method2 ....
public void method3 ....
}
In order to wrap every AsynCallback<T> that is passed to any RemoteService you need to override RemoteServiceProxy#doCreateRequestCallback() because every AsynCallback<T> is handed in here before an RPC call happens.
Here are the steps to do so:
To begin you need to define your own Proxy Generator to step in every time a RemoteService proxy gets generated. Start by extending ServiceInterfaceProxyGenerator and overriding #createProxyCreator().
/**
* This Generator extends the default GWT {#link ServiceInterfaceProxyGenerator} and replaces it in the
* co.company.MyModule GWT module for all types that are assignable to
* {#link com.google.gwt.user.client.rpc.RemoteService}. Instead of the default GWT {#link ProxyCreator} it provides the
* {#link MyProxyCreator}.
*/
public class MyServiceInterfaceProxyGenerator extends ServiceInterfaceProxyGenerator {
#Override
protected ProxyCreator createProxyCreator(JClassType remoteService) {
return new MyProxyCreator(remoteService);
}
}
In your MyModule.gwt.xml make use of deferred binding to instruct GWT to compile using your Proxy Generator whenever it generates something of the type RemoteService:
<generate-with
class="com.company.ourapp.rebind.rpc.MyServiceInterfaceProxyGenerator">
<when-type-assignable class="com.google.gwt.user.client.rpc.RemoteService"/>
</generate-with>
Extend ProxyCreator and override #getProxySupertype(). Use it in MyServiceInterfaceProxyGenerator#createProxyCreator() so that you can define the base class for all the generated RemoteServiceProxies.
/**
* This proxy creator extends the default GWT {#link ProxyCreator} and replaces {#link RemoteServiceProxy} as base class
* of proxies with {#link MyRemoteServiceProxy}.
*/
public class MyProxyCreator extends ProxyCreator {
public MyProxyCreator(JClassType serviceIntf) {
super(serviceIntf);
}
#Override
protected Class<? extends RemoteServiceProxy> getProxySupertype() {
return MyRemoteServiceProxy.class;
}
}
Make sure both your MyProxyCreator and your MyServiceInterfaceProxyGenerator are located in a package that will not get cross-compiled by GWT into javascript. Otherwise you will see an error like this:
[ERROR] Line XX: No source code is available for type com.google.gwt.user.rebind.rpc.ProxyCreator; did you forget to inherit a required module?
You are now ready to extend RemoteServiceProxy and override #doCreateRequestCallback()! Here you can do anything you like and apply it to every callback that goes to your server. Make sure that you add this class, and any other class you use here, in my case AsyncCallbackProxy, to your client package to be cross-compiled.
/**
* The remote service proxy extends default GWT {#link RemoteServiceProxy} and proxies the {#link AsyncCallback} with
* the {#link AsyncCallbackProxy}.
*/
public class MyRemoteServiceProxy extends RemoteServiceProxy {
public MyRemoteServiceProxy(String moduleBaseURL, String remoteServiceRelativePath, String serializationPolicyName,
Serializer serializer) {
super(moduleBaseURL, remoteServiceRelativePath, serializationPolicyName, serializer);
}
#Override
protected <T> RequestCallback doCreateRequestCallback(RequestCallbackAdapter.ResponseReader responseReader,
String methodName, RpcStatsContext statsContext,
AsyncCallback<T> callback) {
return super.doCreateRequestCallback(responseReader, methodName, statsContext, new AsyncCallbackProxy<T>(callback));
}
}
Now, your AsyncCallbackProxy can look something like this:
public class AsyncCallbackProxy<T> implements AsyncCallback<T> {
private AsyncCallback<T> delegate;
public AsyncCallbackProxy(AsyncCallback<T> delegate) {
this.delegate = delegate;
}
#Override
public final void onFailure(Throwable caught) {
GWT.log("AsyncCallbackProxy#onFailure() : " + caught.getMessage(), caught);
if (caught instanceof NotLoggedInException) {
// Handle it here
}
delegate.onFailure(proxy);
}
#Override
public final void onSuccess(T result) {
delegate.onSuccess(result);
}
}
References:
DevGuideCodingBasicsDeferred.html
An example applied to performance tracking
You can wrap AsyncCallback class with an abstract class:
public abstract class CustomAsyncCallback<T> implements AsyncCallback<T>{
#Override
public void onFailure(Throwable caught) {
GWT.log(caught.getMessage());
handleException();
this.customOnFailure(yourDesireParam);
}
/**
* this method is optional
*/
public abstract void customOnFailure(Param yourDesireParam);
}
And then send a CustomAsyncCallback object to your RPC asynch methods.