QueryDSL web support on custom controller POST request - spring-data-rest

I would like to create a custom controller in Spring Data Rest with a QueryDSL predicate. I have 3 requirements: a body, headers and query a filter on the result.
It searches resources based on
The URL will be:
POST /geosearch?type=a with body {"geo": {..geojson..}} and with header crs=crs-value.
#RepositoryRestController
#RequestMapping("/geo")
public class GeoController {
...
...
#PostMapping(value = "geosearch", consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity customFind(#QuerydslPredicate(root = Domain.class) Predicate predicate,
#RequestBody GeoRequest geoRequest,
#RequestHeader("someheader") String someHeader) throws HttpMediaTypeNotAcceptableException {}
I get the following error:
org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.querydsl.core.types.Predicate]: Specified class is an interface
suppose the controller does not accept query parameters

Related

Mono or Flux request body in WebFlux controller

What is the difference between a controller that gets input regular java payload and that of reactive payload? For example, say I have the following 2 endpoints:
#RestController
public class MyController {
#PostMapping
public Flux<SomeObject> doThing(#RequestBody MyPayload playlod) {
// do things that return flux - reactive all the way from this controller
and this one:
#RestController
public class MyController {
#PostMapping
public Flux<SomeObject> doThing(#RequestBody Mono<MyPayload> playlod) {
I don't understand the difference between the 2 methods in reactive point of view.
According to WebFlux documentation:
The request body can be one of the following way and it will be decoded automatically in both the annotation and the functional programming models:
Account account — the account is deserialized without blocking
before the controller is invoked.
Mono<Account> account — the
controller can use the Mono to declare logic to be executed after the
account is deserialized.
Flux<Account> accounts — input streaming
scenario.

how to validate header params using Bean Validation and jax-rs

I have jax-rs resources and each have a same header. what is the best way to validate that the header is present using Bean Validation. I know about #HeaderParam but I don't want to change all my methods in all resources to include the header param.
It's as simple as implementing javax.ws.rs.container.ContainerRequestFilter. For example:
#Provider
public class ContentTypeValidatorFilter implements ContainerRequestFilter {
#Override
public void filter(ContainerRequestContext reqContext) {
String contentType = getHeader(reqContext, "Content-Type");
// Content-type validation, but you can valid as many headers as you want.
if (Objects.isNull(contentType)) {
throw new InvalidRequestException("Content-Type header is missing");
}
}
private String getHeader(ContainerRequestContext requestContext, String header) {
return requestContext.getHeaders().getFirst(header);
}
}
Later, to handle this exception gracefully just implement ExceptionMapper for this InvalidRequestException.
The above filter will be applied globally. But if you want to exclude some endpoints, then make use of #NameBinding to annotate your custom annotation and apply it only to specific endpoints.

Web Api routing with parameter option?

I would like to provide a ASP.Net Web API that can be called by the following formats:
http
://myApiServer/API/MyLookupMethod/GetForIVR/PhoneNumber/8005551212
or
http
://myApiServer/API/MyLookupMethod/GetForIVR?LookupType=PhoneNumber&LookUpValue=8005551212
Is it possible to set up a route that works with either call?
My current route is
config.Routes.MapHttpRoute(
name:"MyRoute",
routeTemplate:"api/{controller}/{action}/{Lookuptype}/{lookupvalue}"
);
Try to use attribute routing
[Route("api/user/YourMethodName/{id}/{param2}")]
[HttpGet]
public HttpResponseMessage YourMethodName(int id = 0, bool param2= true)
Hope it works!!
You can use Attribute based routing i.e. specific routing on controllers and methods. Further you should pass your 2 parameters as query-string like in this URL MyLookupMethod/GetForIVR?LookupType=PhoneNumber&LookUpValue=8005551212 and they will be automatically parsed as method parameters.
public class SomeController : ApiController
{
// GET MyLookupMethod/GetForIVR?LookupType=PhoneNumber&LookUpValue
[Route("MyLookupMethod/GetForIVR")]
public Book Get(int LookupType, int LookUpValue) { ... }
}

Spring data REST content negotiation

I have an annotated RepositoryRestResource for domain objects whose fields also contain binary data (images.) The Spring Rest machinery will create nice RESTful links for these fields, but I would also like to introduce a handler that returns the bare binary when browsers send an "image/*" accept header.
I could overlay a controller on the same paths, but it's brittle and I'd rather write a strategy class for this.
Possible? Any idea where to plug it in the Spring plumbing?
TIA,
Edoardo
Using the #RepositoryRestController annotation "properly", you should be able to restrict the controller override to the "image/*" only.
Say you have a simple domain object model (getters/setters and a some annotations omitted...)
public class Item {
#Id
private String id;
private String name;
}
Let's override the controller for image/* only
#RepositoryRestController
#ResponseBody
public class ItemRepositoryRestController {
#Autowired
private ItemRepository repository;
#RequestMapping(value = "/items/{id}", method = RequestMethod.GET,
produces = "image/*")
public Item getItem(#PathVariable(value = "id") String id)
{
Item item = repository.findOne(id);
/* do some magic with your item */
return item;
}
Obviously, no image/* data is returned here - you'll actually get a 400 error - but you do only get to this controller if asking if accepting image/*, while going through the automagic Spring Rest Controller when not asking for image/* if and only if you use #RequestMapping at the method level.
I haven't been to the point where I return raw binary data, you may have to use the HttpServletResponse directly as shown here. Or perhaps you already have an answer for this since in your comment you mention having added another resource path already (in which case I'm interested in how you return the raw data).

WCF Polymorphism in service contract

I am trying to create a service that with an operation that accepts, as a parameter, an any object that implements a specific interface. I would have thought this would be easy to accomplish, but I am running into problems (what I am guessing to be serialization problems but I am not certain). I have the following contract:
//Unsustainable because I would need a method for each of the (currently)
//3 student types, plus I have 2 more root categories that have multiple subtypes
public interface IEmailTemplateAccess
{
[FaultContract(typeof(ValidationFault))]
[FaultContract(typeof(ErrorResponse))]
[OperationContract]
[TransactionFlow(TransactionFlowOption.Allowed)]
TemplateResponse GetStudentTemplate(ITemplateRequest request);
}
And this is what I would like it to look like:
public interface IEmailTemplateAccess
{
[FaultContract(typeof(ValidationFault))]
[FaultContract(typeof(ErrorResponse))]
[OperationContract]
[TransactionFlow(TransactionFlowOption.Allowed)]
TemplateResponse GetTemplate(ITemplateRequest request);
}
In my service I use an abstract factory to return the correct template based on the type of request that comes in. In addition, I have created concrete ITemplateRequests for the different kinds of templates that could be returned. For example, I have Template Request types A and B. Template Request Type A can have one of 3 sub types, SubType1, SubType2 and SubType3. I then created a SubType3 request that implemented the ITemplateRequest interface (SubType3Request).
I would hate to have to create a method for each request type I have (i.e. GetSubType1Template, GetSubType2Template, GetSubType3Template, GetTypeBTemplate, etc) as this would quickly become unwieldy as the types of templates I can get will be changing occasionally.
Is there a way to have a contract method accept anything that implements ITemplateRequest as a parameter and let my factory do the work of figuring out what type of template to get?
So far, I have the following methods in my service:
//Not a part of the contract right now although I would like it to be
public IEmailTemplate GetTemplate(ITemplateRequest request)
{
TemplateFactoryBuilder builder = new TemplateFactoryBuilder();
ITemplateFactory factory = builder.GetTemplateFactory(request.Type);
var template = factory.GetTemplate(request);
return template;
}
//contract method --This would be my Parent Request Type (RequestTypeA) from above.
//There are 3 subtypes of the Student type
public TemplateResponse GetStudentTemplate(StudentEmailTemplateRequest request)
{
var response = new TemplateResponse
{
RequiresProcessing = true
};
response.Template = (EmailMergeTemplate) GetTemplate(request);
return response;
}
Sorry for the link-ish answer, but it's pretty long.. What you're after (I think) is here: http://blogs.msdn.com/b/morgan/archive/2009/08/05/polymorphism-in-wcf.aspx
It boils down to using known types. Something like this;
[ServiceContract]
[ServiceKnownType("GetKnownTypes", typeof(CommandServiceHelper))]
public interface ICommandService