Pageable in controller not instantiated - spring

I have a spring-boot app with controller that uses Pageable as an argument to one of its methods. It works fine. But I want to use spring-contract-verifier to generate and execute tests.
Base class for tests looks like this:
public class MvcTest {
#Before
public void setup() {
RestAssuredMockMvc.standaloneSetup(new Controller());
}
}
The exception I'm getting is:
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.data.domain.Pageable]: Specified class is an interface
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:99)
I searched SO and I found out that I should add
#EnableSpringDataWebSupport
to my configuration class. I created a class:
#Configuration
#EnableWebMvc
#EnableSpringDataWebSupport
public class WebConfig {
}
However, I'm not sure how to tell contract verifier to pull this class into configuration.
Thanks

Its the wrong pagable: use org.springframework.data.domain.Pageable instead of java.awt.print.Pageable.
you need to enable
#EnableSpringDataWebSupport
or
<bean class="org.springframework.data.web.config.SpringDataWebConfiguration" />
#see: http://docs.spring.io/spring-data/jpa/docs/current/reference/html/#core.web

Related

IllegalStateException: Spring Data REST controller ... must not use #RequestMapping on class level as this would cause double registration

After Spring Boot Upgrade to version 2.5.6 I am not able to compile the project because of the following error:
Caused by: org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'restHandlerMapping' defined in class
path resource
[org/springframework/data/rest/webmvc/config/RepositoryRestMvcConfiguration.class]:
Bean instantiation via factory method failed; nested exception is
org.springframework.beans.BeanInstantiationException: Failed to
instantiate
[org.springframework.data.rest.webmvc.config.DelegatingHandlerMapping]:
Factory method 'restHandlerMapping' threw exception; nested exception
is java.lang.IllegalStateException: Spring Data REST controller
MyController must not use #RequestMapping on class level as this would
cause double registration with Spring MVC!
This is my controller:
#BasePathAwareController
#RequestMapping("/api/my")
public class MyController {
#GetMapping("/x")
public ResponseEntity<...> x
#GetMapping("/y")
public ResponseEntity<...> y
#GetMapping("/z")
public ResponseEntity<...> z
}
I was able to solve the problem by removing #RequestMapping annotation and moving "/api/my" to each method, but is there any way to change it on the class level?
EDIT:
To be precise, there is already a config class
#Configuration
public class RestModuleConfiguration implements RepositoryRestConfigurer {
#Override
public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config, CorsRegistry cors) {
config.setReturnBodyOnCreate(true);
config.setReturnBodyOnUpdate(true);
config.setBasePath(Constants.API_BASE_URI); // "/api"
...
}
so in fact my controller does not contain base uri ("/api"), previously I just wanted to simplify the example as much as possible.
#BasePathAwareController
#RequestMapping("/my")
public class MyController {
#GetMapping("/x")
public ResponseEntity<...> x
#GetMapping("/y")
public ResponseEntity<...> y
#GetMapping("/z")
public ResponseEntity<...> z
}
Does it mean that the only way is to define constant paths for each Controller? (e.g. Constants.MY_CONTROLLER_BASE_URI)
Try using the following configuration, which is intended to be used by Spring Data REST to expose repository resources:
spring.data.rest.basePath=/api/my
And defining the controller as:
#BasePathAwareController
public class MyController {
#GetMapping("/x")
public ResponseEntity<...> x
#GetMapping("/y")
public ResponseEntity<...> y
#GetMapping("/z")
public ResponseEntity<...> z
}
Add
server.servlet.context-path=/api/my
to your application.properties equivalent thing if using yaml

#EnableAspectJAutoProxy deactivate my bean definition

I setting up a new Spring App(not spring boot) in IDEA,and manual download aspectjweaver,
writing the following code to practice aop.
A root configuration class is:
#Configuration
/*#EnableAspectJAutoProxy*/
#ComponentScan
public class Main {
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx=new AnnotationConfigApplicationContext();
ctx.register(Main.class);
ctx.refresh();
Performance performance=ctx.getBean(WoodStock.class);
//System.out.println(ctx.getBean(Audience.class));
performance.performance();
}
}
and the project layout is:
+com.dawn.www
-Main.java
+aspect
-Audience.java
+music
-Performance.java
-WoodStock.java
I want the Audience being the aspect of WoodStock(seeing it in spring in action)
#Aspect
#Component
public class Audience {
#Before("execution(* com.dawn.www.music.Performance.performance(..))")
public void silenceCellPhones(){
System.out.println("-----------Silencing cell phones");
}
}
Performance is a simple interface which implements by WoodStock
public interface Performance {
void performance();
}
#Component
public class WoodStock implements Performance{
#Override
public void performance() {
System.out.println("WoodStock Performance start,singer singing+++++");
}
}
#ComponentScan should find theWoodStockbean which is defined in application context,however when I run it:
No qualifying bean of type 'com.dawn.www.music.WoodStock' available
but when I comment out #EnableAspectJAutoProxy, WoodStock can be fetched from
application context?that's why?
When you are using #EnableAspecjAutoProxy, spring will automatically
create proxy for all the matching beans(i.e. WoodStock via Audience aspect).
Now, Since you haven't used 'proxyTargetClass=true' on
#EnableAspectJAutoProxy, it will fall back on JDK proxy instead of
CGLIB.
JDK proxy is interface based, hence your proxy is of type
'Performance'.
Thats the reason you are getting 'No qualifying bean of type
'com.dawn.www.music.WoodStock' available' when you try to find bean
using WoodStock type
Now, after commenting out #EnableAspectJAutoProxy, WoodStock becomes a
simple bean and is accessible via ctx.getBean(..)
with 'proxyTargetClass=true', CGLIB proxy is enabled and it creates
proxy of type WoodStock
Suggestions
Use 'proxyTargetClass=true' with ctx.getBean(WoodStock.class)
or
Use 'proxyTargetClass=false' with ctx.getBean(Performance.class)
Performance performance=ctx.getBean(Performance.class);
Spring Aop only support Interface-level proxy when not using CGLIB,so don't use class,use interface.

Spring Autowired annotation with service implementation

I have few doubts in the scenario below.
Having one interface and two implementation classes:
Interface:
interface ServiceInt
{
public void save();
}
First implementation class:
Public class ServiceIntImpOne implements ServiceInt
{
public void save()
{
// I am first service implementation
}
}
Second implementation class:
Public class ServiceIntImpTwo implements ServiceInt
{
public void save()
{
// I am Second service implementation
}
}
Main class calling the save method of an implementation class:
Public class controller
{
#Autowired ServiceInt;
public void save()
{
ServiceInt.save()
}
}
My Questions:
ServiceInt.save() – which save method of service class implementation will it invoke?
How we can use the save method implementation of the ServiceIntImpTwo class?
How does autowired work?
ServiceInt.save() – which save method of service class implementation
will it invoke?
If you have two beans of the same type (beans defined via annotations or via xml) when you autowire that beans it will fail (throw exception), because Spring don't know what bean to inject.
caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException:
No unique bean of type [ServiceInt] is defined:
How we can use the save method implementation of the ServiceIntImpTwo
class?
If you defined your bean in a xml file, then you can use the id property
<bean id="beanTwo" class="ServiceIntImpTwo" />
then you can autowire using Qualifier annotation
#Autowired
#Qualifier("beanTwo")
ServiceInt myServiceTwo;
if you are using annotations instead.
#Component
Class ServiceIntImpTwo impl...{}
Then you can autowire
#Autowired
#Qualifier("serviceIntImpTwo ")
ServiceInt myServiceTwo;
How does autowired work?
This you can read it on Internet.
http://memorynotfound.com/handling-multiple-autowire-dependencies-with-spring-qualifier/
https://www.mkyong.com/spring/spring-autowiring-qualifier-example/
https://www.tutorialspoint.com/spring/spring_qualifier_annotation.htm
If you have two implementation to one interface you will need to provide spring hint which one to use:
you can use #Qaulifier annotation
you can use #Profile and choose the active profile.

spring data JPA & spring data elasticsearch; No property index found for type?

I'm unsure why this is happening! I've got a class that is used by spring data elasticsearch and spring data jpa, but when I try run my application I get an error.
Error creating bean with name 'articleSearch':
Invocation of init method failed; nested exception is
org.springframework.data.mapping.PropertyReferenceException:
No property index found for type Article!
Caused by: org.springframework.data.mapping.PropertyReferenceException:
No property index found for type Article!
at org.springframework.data.mapping.PropertyPath.<init>(PropertyPath.java:77) ~[spring-data-commons-1.11.4.RELEASE.jar:na]
I've got the following application class:
#SpringBootApplication
#EnableAsync
#ComponentScan(basePackages = {"com.article.models", "com.user"})
public class ArticleApplication {
And the following elasticsearch config:
#Configuration
#EnableElasticsearchRepositories(basePackages = "com.article.search")
public class ElasticSearchConfiguration {
#Resource
private Environment environment;
#Bean
public Client client() {
TransportClient client = new TransportClient();
TransportAddress address = new InetSocketTransportAddress(environment.getProperty("elasticsearch.host"), Integer.parseInt(environment.getProperty("elasticsearch.port")));
client.addTransportAddress(address);
return client;
}
#Bean
public ElasticsearchOperations elasticsearchTemplate() {
return new ElasticsearchTemplate(client());
}
}
This is how I've setup my model class:
#Entity
#Table(name="article")
#Document(indexName="article", type="articles")
public class Article implements Serializable {
I've then got a package search that extends the elasticsearchrepository, like so:
public interface ArticleSearch extends ElasticsearchRepository<Article, String> {
I'm trying to autowire the articlesearch class inside another service which is causing the error to occur:
#Autowired
ArticleSearch articleSearch;
What am I missing here?! I guess it's a bit more complex when trying to use data-jpa + data-elasticsearch.
I found out why this was happening. I'm not sure why, but spring didn't seem to be picking up my ElasticSearchConfiguration configuration class!
So I simply moved all the contents from that and dumped it in my main application class (where all my other config is).
I also removed component scan & added the enablejparepository + enableelasticsearchrepository annotations to my main class. Here is what it looks like now:
#SpringBootApplication
#EnableAsync
#EnableElasticsearchRepositories(basePackages = "com.article.search")
#EnableJpaRepositories(basePackages = {"com.article.dao", "com.user.dao"})
public class ArticleApplication {

Superclass has no null constructors but no arguments were given. Spring Integration

I'm developing web application supported by Spring Integration. I'm using 1.0.4.RELEASE. I use CGLib proxies. I have a transactional message endpoint. Everything worked correctly, but I experimented a little bit with annotations. I use annotation-config, which works fine. I started from switching my service-activator configuration from xml to annotations, but it failed.
The following configuration worked correctly:
spring-integration.xml
<channel id="inChannel" />
<channel id="outChannel" />
<service-activator method="myMethod" input-channel="inChannel" ref="myService" output-channel="outChannel" />
MyService.java
#MessageEndpoint
#Transactional
public class MyService {
#Autowired
private MyDao myDao;
public MyObject myMethod(String message) throws Exception {
...
}
}
Trying to achieve exactly the same functionality using annotations (having in mind that I use CGLIB, so I do not need interface, but default constructor) I
removed service-activator from my .xml
changed MyService:
Changed MyService.java
#MessageEndpoint
#Transactional
public class MyService {
#Autowired
private MyDao myDao;
public MyService () {
}
#ServiceActivator(inputChannel="inChannel", outputChannel="outChannel")
public MyObject myMethod(String message) throws Exception {
...
}
}
I get the following error:
java.lang.IllegalArgumentException: Superclass has no null constructors but no arguments were given
I've seen many threads describing the following error article, but the problem was about custom classes. My problem regards Spring class.
Error creating bean with name 'myService'
nested exception is org.springframework.aop.framework.AopConfigException
Could not generate CGLIB subclass of class [class org.springframework.integration.handler.ServiceActivatingHandler]
java.lang.IllegalArgumentException: Superclass has no null constructors but no arguments were given
What's wrong? Why Spring tries to create proxy for spring class but not only for MyService? Is my class somehow wrapped? I don't understand what's happening. Help greatly appreciated.
Try taking off the #Autowired Tag. That looks for a constructor or setter method in order to populate that field. Considering you have neither of those, that might be the problem. Just a guess though.
OR you can make myDao package-protected or public (so that Spring can actually autowire it)
for instance:
#Autowired
myDao

Resources