Facing an error with BigDecimal question in java - java-8

The problem is :
You’ve received a stream that represents a set pf laboratory samples. B before the inout data is passed on further processing, you are required to perform some pre((-)) processing on it, what you must do is:
Eliminate all null and negative values(noises).
Divide the data into triple((-)) groups of three samples and retain only complete triples.
Eliminate all triples whose average is higher that 30.
Join all triplets again.
Use SampleNormalizer to normalise the values. Unfortunately, due to poor design it returns optional<optional> and is it a bit buggy: it may return nulls(empty optionals), which you must eliminate. SampleNormalizer’s normalise method accepts a single Big Decimal.
Return a stream
You mustn’t return null.
The thing is I am supposed to solve this in java 8
`. import java.util.*;
import java.math.BigDecimal;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Stream;
import static java.math.BigDecimal.ZERO;
import static java.util.stream.Collectors.averagingDouble;
import static java.util.stream.Collectors.groupingBy;
class SamplePreprocessor {`your text`
private final SampleNormalizer normalizer;
SamplePreprocessor(SampleNormalizer normalizer) {
this.normalizer = normalizer;
}
Stream<BigDecimal> preprocess(Stream<BigDecimal> input) {
input = input.filter(bd -> bd != null && bd.compareTo(ZERO) > 0);
// Step 2: Divide the data into triple groups and filter out the ones whose average is higher than 30
input = input.collect(groupingBy(new AtomicInteger()::getAndIncrement, averagingDouble(BigDecimal::doubleValue)))
.values()
.stream()
.filter(avg -> avg.doubleValue() <= 30)
.flatMap(group -> Stream.of(group.toArray(new BigDecimal[3])))
.map(Arrays::asList)
.filter(list -> list.size() == 3)
.map(list -> list.stream().reduce(BigDecimal.ZERO, BigDecimal::add).divide(BigDecimal.valueOf(3)));
// Step 3: Use SampleNormalizer to normalize the values
input = input.map(normalizer::normalize)
.filter(Optional::isPresent)
.map(Optional::get);
// Step 4: Return the preprocessed stream of BigDecimal values
return input;
}
}
`
ERROR
Compiler output:
Starting a Gradle Daemon (subsequent builds will be faster)
Task :compileJava
/task/src/main/java/com/codility/SamplePreprocessor.java:27: error: no suitable method found for groupingBy(new Atomic[...]ement,Collector<BigDecimal,CAP#1,Double>)
input = input.collect(groupingBy(new AtomicInteger()::getAndIncrement, averagingDouble(BigDecimal::doubleValue)))
^
method Collectors.<T#1,K#1,D#1,A#1,M>groupingBy(Function<? super T#1,? extends K#1>,Supplier,Collector<? super T#1,A#1,D#1>) is not applicable
(cannot infer type-variable(s) T#1,K#1,D#1,A#1,M
(actual and formal argument lists differ in length))
method Collectors.<T#2,K#2,A#2,D#2>groupingBy(Function<? super T#2,? extends K#2>,Collector<? super T#2,A#2,D#2>) is not applicable
(cannot infer type-variable(s) T#2,K#2,A#2,D#2
(argument mismatch; invalid method reference
method getAndIncrement in class AtomicInteger cannot be applied to given types
required: no arguments
found: T#2
reason: actual and formal argument lists differ in length))
method Collectors.<T#3,K#3>groupingBy(Function<? super T#3,? extends K#3>) is not applicable
(cannot infer type-variable(s) T#3,K#3
(actual and formal argument lists differ in length))
where T#1,K#1,D#1,A#1,M,T#2,K#2,A#2,D#2,T#3,K#3 are type-variables:
T#1 extends Object declared in method <T#1,K#1,D#1,A#1,M>groupingBy(Function<? super T#1,? extends K#1>,Supplier,Collector<? super T#1,A#1,D#1>)
K#1 extends Object declared in method <T#1,K#1,D#1,A#1,M>groupingBy(Function<? super T#1,? extends K#1>,Supplier,Collector<? super T#1,A#1,D#1>)
D#1 extends Object declared in method <T#1,K#1,D#1,A#1,M>groupingBy(Function<? super T#1,? extends K#1>,Supplier,Collector<? super T#1,A#1,D#1>)
A#1 extends Object declared in method <T#1,K#1,D#1,A#1,M>groupingBy(Function<? super T#1,? extends K#1>,Supplier,Collector<? super T#1,A#1,D#1>)
M extends Map<K#1,D#1> declared in method <T#1,K#1,D#1,A#1,M>groupingBy(Function<? super T#1,? extends K#1>,Supplier,Collector<? super T#1,A#1,D#1>)
T#2 extends Object declared in method <T#2,K#2,A#2,D#2>groupingBy(Function<? super T#2,? extends K#2>,Collector<? super T#2,A#2,D#2>)
K#2 extends Object declared in method <T#2,K#2,A#2,D#2>groupingBy(Function<? super T#2,? extends K#2>,Collector<? super T#2,A#2,D#2>)
A#2 extends Object declared in method <T#2,K#2,A#2,D#2>groupingBy(Function<? super T#2,? extends K#2>,Collector<? super T#2,A#2,D#2>)
D#2 extends Object declared in method <T#2,K#2,A#2,D#2>groupingBy(Function<? super T#2,? extends K#2>,Collector<? super T#2,A#2,D#2>)
T#3 extends Object declared in method <T#3,K#3>groupingBy(Function<? super T#3,? extends K#3>)
K#3 extends Object declared in method <T#3,K#3>groupingBy(Function<? super T#3,? extends K#3>)
where CAP#1 is a fresh type-variable:
CAP#1 extends Object from capture of ?
/task/src/main/java/com/codility/SamplePreprocessor.java:51: error: incompatible types: inference variable R has incompatible bounds
.map(Optional::get);
^
equality constraints: BigDecimal
lower bounds: Optional
where R,T are type-variables:
R extends Object declared in method map(Function<? super T,? extends R>)
T extends Object declared in interface Stream
2 errors
Task :compileJava FAILED
FAILURE: Build failed with an exception.
What went wrong:
Execution failed for task ':compileJava'.
Compilation failed; see the compiler error output for details.
Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
Get more help at https://help.gradle.org
Deprecated Gradle features were used in this build, making it incompatible with Gradle 5.0.
See https://docs.gradle.org/4.8.1/userguide/command_line_interface.html#sec:command_line_warnings
BUILD FAILED in 9s
1 actionable task: 1 executed
Exit code: 1

Related

How do I solve Class Cast Exception when it comes to Unit Testing?

I have been generating Test Cases for some classes using a tool called Diff Blue. Now Diff Blue is an AI tool that can generate multiple Test Cases for some functions. I have a particular class for which I have generated Test Cases using Diff Blue but one Test Case has failed. My main goal is to get all of the Test Cases to pass. The Test Case I'm working on is for the below class with function getDashboardById.
#RequiredArgsConstructor
#Transactional
#Service
#Slf4j
public class DashboardServiceImpl implements DashboardService {
private final DashboardRepository dashboardRepository;
private final PlatformDataExtractHistoryService platformDataExtractHistoryService;
private final ShopifyService shopifyService;
private final ModelMapper modelMapper;
/**
* Get Dashboard by its id
*
* #param id dashboard id
* #return DashboardGetDto
*/
#Override
public DashboardGetDto getDashboardById(String id) {
Dashboard dashboard = dashboardRepository.findById(id)
.orElseThrow(() -> new ResourceNotFoundException(GlobalErrorUtils.DASHBOARD_NOT_FOUND_404));
log.info("Get dashboard details by id: {}", id);
// convert entity to DTO
return modelMapper.map(dashboard, DashboardGetDto.class);
}
Diffblue has generated 3 Test Cases for the function getDashboardById. Two of the Test Cases passed while one failed. My goal is to get it to pass too. The below code is the code of the failed test case.
void testGetDashboardById3() {
DashboardGetDto dashboardGetDto = new DashboardGetDto();
when(dashboardRepository.findById((String) any())).thenReturn(Optional.empty());
when(modelMapper.map((Object) any(), any())).thenReturn("Map");
when(modelMapper.map((Object) any(), (Class<DashboardGetDto>) any())).thenReturn(dashboardGetDto);
assertThrows(ResourceNotFoundException.class, () -> dashboardServiceImpl.getDashboardById("42"));
verify(dashboardRepository).findById((String) any());
verify(modelMapper).map((Object) any(), (Class<Object>) any());
}
The problem I'm experiencing is that I'm getting a Class Cast Exception.
java.lang.ClassCastException: class java.lang.String cannot be cast to class com.unicorn.dashboard.dto.dashboard.DashboardGetDto (java.lang.String is in module java.base of loader 'bootstrap'; com.unicorn.dashboard.dto.dashboard.DashboardGetDto is in unnamed module of loader 'app')
at com.unicorn.dashboard.serviceImpl.DashboardServiceImplTest.testGetDashboardById3(DashboardServiceImplTest.java:127)
Now I do understand that this occurs when you try to cast a class of one type to another. But what I'm struggling to understand is where the error is being generated and how do I solve it since this is a Test Case. The Error points at line 127 which is in the above Test Function testGetDashboardById3. For reference I'll give the line below
when(modelMapper.map((Object) any(), (Class<DashboardGetDto>) any())).thenReturn(dashboardGetDto);
Now what I don't understand is that where exactly in the above line is the Cast occurring and what must be changed in order to get the Test Case working?
Edit
I have edited my code as per the answers and displayed it below. However there is an error within the code. What necessary changes must be done to fix the error?
When I hover over the highlighted area I get this message
when(modelMapper.map((Object) any(), any())).thenReturn("Map"); matches any second argument. You want to mock method <D> D map(Object source, Class<D> destinationType) which you would call as map(input, String.class) and map(input, DashboardGetDto.class) in your production code. Therefore, you want to set up this method as:
when(modelMapper.map(any(), eq(String.class)))
.thenReturn("Map");
when(modelMapper.map(any(), eq(DashboardGetDto.class)))
.thenReturn(dashboardGetDto);
to select the correct overloads. Your test was matching calls such as map(input, new DashboardGetDto()), which returns void.
Note that ArgumentMatchers#any() is already generic, so you don't have to cast the return value. You can either use ArgumentMatchers.<Object>any() or any(Object.class).
Important to note is that the Java runtime cannot distinguish between Class<X> and Class<Y> (or List<A> and List<B>). For the JVM, both are of type Class (or List, respectively). Your first when call was already matching all calls to your mock.

no suitable method found for create() method reactor.test.StepVerifier.create

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);
}

Java implement multiple interfaces results in compilation error

I'm building an application using Spring webmvc + data jpa with Java 8. I have entities inheritance like:
public class BaseEntity {...}
public class Report extends BaseEntity {...}
public class BlahBlah extends BaseEntity {...}
On the other hand, to enable CRUD operations on the entities, some repository interfaces are created as below:
/**
* Read-only repository.
* See reference article
*/
#NoRepositoryBean
public interface BaseRepository<T extends BaseEntity> extends Repository<T, Long> {
T findOne(Long id);
Iterable<T> findAll();
Iterable<T> findAll(Sort sort);
Page<T> findAll(Pageable pagable);
}
And for each inherited entity class there's a repository interface:
public interface ReportRepository extends BaseRepository<Report>, PagingAndSortingRepository<Report, Long> { }
The client code looks like this: (ReportController.java)
Report entity = reportRepo.findOne(id);
The application compiles and runs as we expected in eclipse. However when I try to package it using maven, there're several compilation errors, which are all similar to:
ReportController.java:[66,43] reference to findOne is ambiguous
both method findOne(ID) in org.springframework.data.repository.CrudRepository
and method findOne(java.lang.Long) in com.myapp.repositories.BaseRepository
match
I don't quite understand the problem here. Yes, there's Type Erasure. But I also remember that if class BaseRepository<T> extends Repository<T, Long>, then BaseRepository will carry some information about the Type Argument passed to Repository. Isn't it?
If no, then how does JDK provides methods java.lang.Class.getGenericSuperclass() and java.lang.reflect.ParameterizedType.getActualTypeArguments()?
If yes, then there should not be ambiguous methods because both interfaces have the same method findOne(Long)...
Any explaination? Thanks.
Updated:
For you to reproduce the issue with ease, I created a tiny project at https://github.com/guogin/problemapp. Please checkout.
OK, I'm back to answer the question myself.
Inspired by comment from Didier L, I tried to look up in the JLS. And now I have the answer.
First, jls-§9.4.1 states:
An interface I inherits from its direct superinterfaces all abstract and default methods m for which all of the following are true:
m is a member of a direct superinterface, J, of I.
No method declared in I has a signature that is a subsignature (§8.4.2) of the signature of m.
There exists no method m' that is a member of a direct superinterface, J', of I (m distinct from m', J distinct from J'), such that m' overrides from J' the declaration of the method m.
In my sample code:
I = ReportRepository
J1 = BaseRepository<Report>
m1 = findOne(Long) from J1
J2 = PagingAndSortingRepository<Report, Long>
m2 = findOne(Long) from J2
Because J2 is not superinterface of J1 - So I actually inherits both m1 and m2 - that is to say, one findOne(Long) from BaseRepository<Report>, the other from PagingAndSortingRepository<Report, Long>.
The interface ReportRepository is itself syntax correct because both methods are inherit from super interfaces:
jls-§9.4
It is a compile-time error for the body of an interface to declare, explicitly or implicitly, two methods with override-equivalent signatures (§8.4.2). However, an interface may inherit several abstract methods with such signatures (§9.4.1).
And no clashes occurs.
In my example, the compilation error actually occurs at the caller method. So I further refer to jls-§15.12.2.5: Choosing the Most Specific Method.
It turns out that, when compiling the code ReportController especially the call to ReportRepository.findOne(Long), the compiler must find the more specific method between m1 and m2. But then it find both are equally specific. Thus a compile-time error of 'ambiguous method call' occurs. That's what happened.
It turns out the eclipse compilation is not as standard as maven.

Consume a service with restTemplate

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;
}

Why do I see ClassCastException in Groovy through #Delegate method

I have a class (I'm using the library Glisten) that defines a #Delegate member.
class PendingActionWorkflowImpl implements PendingActionWorkflow, WorkflowOperator<PendingActionWorkflow> {
/***
* The #Delegate transformation makes all the methods from WorkflowOperations
* available to owning class (PendingActionWorkflowImpl)
*/
#Delegate
WorkflowOperations<PendingActionActivities> workflowOperations =
SwfWorkflowOperations.of(PendingActionActivities)
}
When I access a nested member of WorkflowOperations ('activities') i get a ClassCastException however if I access the WorkflowOperations property first, then everything works okay...
Promise<List<String>> promise = promiseFor(activities.fetchPendingActions())
Scratching my head on this one.
Here is the exception for completeness:
Details = org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot
cast object 'com.netflix.glisten.impl.swf.AsyncCaller(interface
com..wf.pending.PendingActionActivities, null,
com.netflix.glisten.impl.swf.AsyncCaller$DynamicActivitiesClientFactory(class
com.amazonaws.services.simpleworkflow.flow.DynamicActivitiesClientImpl))'
with class 'com.netflix.glisten.impl.swf.AsyncCaller' to class
'com..wf.pending.PendingActionActivities' at
org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation.continueCastOnSAM(DefaultTypeTransformation.java:405)
at
org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation.continueCastOnNumber(DefaultTypeTransformation.java:319)
at
org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation.castToType(DefaultTypeTransformation.java:232)
at
org.codehaus.groovy.runtime.ScriptBytecodeAdapter.castToType(ScriptBytecodeAdapter.java:603)

Resources