In a spring boot (1.4.1) application, i try to consume a rest template
#GetMapping(value = "/visits")
public ResponseEntity<CustomPageImpl<VisitDto>> getVisits(Pageable pageRequest) {
return restTemplate.getForEntity("", new TypeReference<CustomPageImpl<VisitDto>>() {});
}
like the answer of Ali Dehghani in this thread, i create a CustomPageImpl
about TypeReference, import com.fasterxml.jackson.core.type.TypeReference;
i get this message
no suitable method found for getForEntity(String,<anonymous TypeReference<CustomPageImpl<VisitDto>>>)
method RestTemplate.<T#1>getForEntity(String,Class<T#1>,Object...) is not applicable
(cannot infer type-variable(s) T#1
(argument mismatch; <anonymous TypeReference<CustomPageImpl<VisitDto>>> cannot be converted to Class<T#1>))
method RestTemplate.<T#2>getForEntity(String,Class<T#2>,Map<String,?>) is not applicable
(cannot infer type-variable(s) T#2
(actual and formal argument lists differ in length))
method RestTemplate.<T#3>getForEntity(URI,Class<T#3>) is not applicable
(cannot infer type-variable(s) T#3
(argument mismatch; String cannot be converted to URI))
where T#1,T#2,T#3 are type-variables:
T#1 extends Object declared in method <T#1>getForEntity(String,Class<T#1>,Object...)
T#2 extends Object declared in method <T#2>getForEntity(String,Class<T#2>,Map<String,?>)
T#3 extends Object declared in method <T#3>getForEntity(URI,Class<T#3>)
With
ResponseEntity<CustomPageImpl<VisitDto>> response = restTemplate.getForEntity(URI.create("url"), new TypeReference<ResponseEntity<CustomPageImpl<VisitDto>>>() {});
get same error
try getForEntity(URI url,Class responseType)
#GetMapping(value = "/visits")
public ResponseEntity<CustomPageImpl<VisitDto>> getVisits(Pageable pageRequest) {
ResponseEntity<CustomPageImpl<VisitDto>> response = restTemplate.getForEntity(Uri.parse("url"), new TypeReference<CustomPageImpl<VisitDto>>() {});
return response;
}
Related
I have 2 services with request/response pattern on Kotlin Spring Boot.
In producer I tried to use generic for send method to don't write several methods with different return types:
fun <T> sendMessage(data: String) : T {
val listenableFuture = asyncRabbitTemplate.convertSendAndReceiveAsType(
directExchange.name,
"routing-key",
data,
object : ParameterizedTypeReference<T>() {}
)
return listenableFuture.get()
}
And for instance I use this method with one of Model classes:
Producer:
fun getData(): ExampleDto {
...
return rabbitTemplate.sendMessage<ExampleDto>("data")
}
Consumer:
...
#RabbitListener(...)
fun consumer(data: String): ExampleDto {
...
// processing with data
return ExampleDto(...)
}
So I get exception class java.util.LinkedHashMap cannot be cast to class com.example.model.ExampleDto (java.util.LinkedHashMap is in module java.base of loader 'bootstrap'; com.example.model.ExampleDto is in unnamed module of loader 'app')
If I write method without generics and declare return type directly, then everything works well. But I don't want to write dozens of methods that are different only in return type.
Looks like ParameterizedTypeReference is used to implement Super Type Token pattern. When you pass T as a parameter type, the underlying logic in convertSendAndReceiveAsType cannot infer the exact type due to generic type erasure.
You either need to parametrize your sendMessage method with ParameterizedTypeReference and create it with concrete type in getData() or you can use Reified type parameters Kotlin feature to overcome this with synthetic sugar. E.g.
inline fun <reified T> sendMessage(data: String) : T {
val listenableFuture = asyncRabbitTemplate.convertSendAndReceiveAsType(
directExchange.name,
"routing-key",
data,
object : ParameterizedTypeReference<T>() {}
)
return listenableFuture.get()
}
I am facing issue in spring program, the issue is Why type casting is applied in spring application?
below is the program for reference.
public class Test {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
Hello obj= (Hello)context.getBean("hello");
obj.getMessge();
}
}
The getBean(String) method returns an object of the type Object. Since you know that the method you annotated with #Bean(name = "hello") returns an instance of Hello you can safely cast getBean's return value to Hello.
Object getBean(String name) returns an instance of type Object; hence, you must cast it to whatever you expect it to return.
<T> T getBean(String name, Class<T> requiredType) overloaded method can be used alternatively, and it will return the object of type T.
You can change your code as follows:
Hello obj = context.getBean("hello", Hello.class);
and in this case, you will not need to cast the returned object explicitly.
I am trying to perform reactive repository test however even compiler do not throw any error in code editor code won't compile. Why is that?
Error:(52, 21) java: no suitable method found for create(com.geborskimateusz.microservices.core.recommendation.persistence.RecommendationEntity)
method reactor.test.StepVerifier.<T>create(org.reactivestreams.Publisher<? extends T>) is not applicable(inferred type does not conform to upper bound(s) inferred: com.geborskimateusz.microservices.core.recommendation.persistence.RecommendationEntity
upper bound(s): org.reactivestreams.Publisher<? extends java.lang.Object>,com.geborskimateusz.microservices.core.recommendation.persistence.RecommendationEntity)method reactor.test.StepVerifier.<T>create(org.reactivestreams.Publisher<? extends T>,long) is not applicable(cannot infer type-variable(s) T
(actual and formal argument lists differ in length))
method reactor.test.StepVerifier.<T>create(org.reactivestreams.Publisher<? extends T>,reactor.test.StepVerifierOptions) is not applicable
(cannot infer type-variable(s) T
(actual and formal argument lists differ in length))
This is the code I am trying to run:
#Test
void create() {
recommendationRepository.deleteAll();
RecommendationEntity given = RecommendationEntity.builder()
.recommendationId(BASE_RECOMMENDATION_ID)
.movieId(BASE_MOVIE_ID)
.content("Fake recommendation")
.build();
StepVerifier.create(recommendationRepository.save(given))
.expectNextMatches(recommendationEntity -> assertRecommendation(given, recommendationEntity))
.verifyComplete();
}
And repository looks like this:
public interface RecommendationRepository extends ReactiveCrudRepository<RecommendationEntity, String> {
Flux<RecommendationEntity> findByMovieId(int movieId);
}
I am getting
java.lang.IllegalArgumentException: Cannot get property 'objects' on null object
error when I intentionally test spring data rest api simulating a user passing bad url as in
http://myurl/findByDate?year=&month="
The year and month are Integers , but in this case I am simulating the user not passing any value.
The app is using the:
public interface myRepo extends PagingAndSortingRepository<myClass, Long> {}
interface and there is no explicit controller provided in a controller class. The data rest interface provides the following:
#Query("Select c from myPOJO c where (YEAR(c.myDate) = :year AND MONTH(c.myDate) = :month)")
Page findByDate(#Param("year") int year,
#Param("month") int month,
Pageable pageable);
I can see why the exception is being thrown ... but providing a generic exception handler to handle it does not seem to resolve the issue.
#ControllerAdvice
public class ExceptionControllerAdvice {
#ExceptionHandler(Exception.class)
public ResponseEntity<ErrorResponse> exceptionHandler(Exception ex) {
ErrorResponse error = new ErrorResponse();
error.setErrorCode(HttpStatus.INTERNAL_SERVER_ERROR.value());
error.setMessage("Please contact your administrator");
//return new ResponseEntity<ErrorResponse>(error, HttpStatus.OK);
return new ResponseEntity<ErrorResponse>(error, HttpStatus.METHOD_NOT_ALLOWED);
}
}
Any advise on how to trap this data rest exception would be appreciate it.
java.lang.IllegalArgumentException: Cannot get property 'objects' on null object
Thank you
This is resolved by using the object Integer instead of the primitive Int for the param. This appears to handle the conversion to default value and avoid nulls.
Thanks
I'm using this tutorial https://spring.io/guides/gs/rest-service/
I want to pass to web service API method parameter other then String:
#RestController
public class ApiClass {
#RequestMapping("/service")
public int service(#RequestParam(value="paramIn") CustomClass paramIn) {
if (paramIn.value != 0) return 1;
else return 0;
}
}
But when I try it I get this error:
HTTP Status 500 - Failed to convert value of type 'java.lang.String' to required type 'CustomClass'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [java.lang.String] to required type [CustomClass]: no matching editors or conversion strategy found`
Thnaks,
Usual way to do this is to use POST or PUT method and annotate the the custom object with #RequestBody. For example:
#RequestMapping(value = "/service",
method = RequestMethod.POST,
consumes = MediaType.APPLICATION_JSON_VALUE)
public int service(#RequestBody CustomClass paramIn) {
// do something with the paramIn
}
If you POST a JSON representation of your CustomClass instance to endpoint /service Spring will deserialize it and pass it as an argument to your controller.