manipulating gs spring project - java

I'm trying to use a spring getting started project, and I have a problem I cannot figure out: when I move the restController from the default "hello" package to another one (say com.mydomain.controllers) I get a 404 error page. Any ideas how to solve this?
PS: I'm using intellij + gradle

In this case, this controller is located in a package that's not scanned by Spring. In the Application class:
package hello;
#SpringBootApplication
public class Application {
//...
}
The #SpringApplication annotation is a convenience annotation - see the full explanation in the guide itself.
If you want to scan other locations and customize more your configuration, you can change your application class to this:
package hello;
#Configuration
#EnableAutoConfiguration
#ComponentScan({"hello", "com.mydomain.controllers"})
public class Application {
//...
}

Related

#ComponentScan seens not to be working after migrate from Spring Boot 2.0 to 2.5

I have an application that was working in Spring Boot 1.5, than worked in 2.0.
Now I'm migrating to 2.5.7
This application uses a external lib. This lib also written using Spring Boot 2.5.7 and it users OpenFeign.
But now, when running, the main application seens not to be scanning the lib.
The error is:
***************************
APPLICATION FAILED TO START
***************************
Description:
Field usersRestClient in my.library.package.infrastructure.acl.facade.user.UserFacade required a bean of type 'my.library.package.infrastructure.acl.restclient.user.UsersRestClient' that could not be found.
The injection point has the following annotations:
- #javax.inject.Inject()
Action:
Consider defining a bean of type 'my.library.package.acl.restclient.user.UsersRestClient' in your configuration.
I already tried to use ComponentScan at diferent places. I tried to Create a Configuration Class with ComponentScan at the lib and point in the main application using #Import.
Nothing worked.
I've edited the code leaving just whats matters.
In the lib:
The Service UserFacade uses the Component UsersRestClient
#Service
// I've already tried to put #ComponentScan here, didn't work.
public class UserFacade {
#Autowired
private UsersRestClient usersRestClient;
...
}
This is the component:
#RequestMapping("/users")
#Component("usersRestClient")
public interface UsersRestClient {
...
}
In the main App:
The main class
#SpringBootApplication
#ComponentScan(basePackages = {"my.library.package"})
#EnableAutoConfiguration
#EnableFeignClients({"my.library.package"})
public class ResourceAllocationServiceApplication {
...
}
Than, where I use the UseFacade Service:
#Component
public class RetrieveUserByIdUseCase {
#Autowired
private UserFacade userFacade;
...
}
Can anyone help? I found a similar issue here, but no answers worked.
#ComponentScan on external library not working

Can I use an instance of a WebMvcConfigurer in another module?

I've written an interceptor to generate service logs for a SpringBoot Java Rest API. I have the code below to define the custom WebMvcConfigurer:
package com.gem.common.interceptors;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
#Configuration
public class InterceptorConfig implements WebMvcConfigurer {
#Autowired
LoggerInterceptor logInterceptor;
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(logInterceptor);
}
}
I'd like to use this InterceptorConfig across different modules. Can I package it and use it or do I need to define it in each module?
I suppose with "other modules" you are asking if you could make that code available to other spring boot applications too?
If that's the case - then: yes you can package it in a jar and add it as a dependency to all your other modules. I'll post the way to do this just below, however - just to warn you - if it's just for that simple class, the solution is not going to be worth it.
In short, what you'd need to do is to create your own external artifact (this usually is done via maven or gradle. You create a new maven project for your shared code. It will need to depend on some base libraries so that you have your #Configuration annotation available. Put your class as described in that project, and create a file src/main/resources/META-INF/spring.factories file. There you'll need to point to that class.
Then you build that project and upload the resulting jar to a package repository. Once that's done, you can add it as a dependency to your project. At startup, Spring boot will find the spring.factories file and automatically include the classes that are mentioned there in its initialization.
Please also note, that this is just a high level explanation and you will need more details. Spring has good documentation on this use case and they also have a demo project to show this extension mechanism.

CommandLineRunner functionality in Spring MVC application

We have a Spring MVC project with multiple Maven modules. We package it into an EAR and deploy it to a WildFly server.
I am trying to do a single time job on project start up. Thus, I thought about the CommandLineRunner interface, the project would compile and run but the commandLineRunner run method wouldn't run.
I guess it's because we are using an MVC Spring project and not a SpringBoot one with its own embedded server.
Can you suggest any ways to implement such a concept in Spring MVC ?
Thanks.
You can do something like that:
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;
#Component
public class StartupExec implements {
#EventListener(ContextRefreshedEvent.class)
public void contextRefreshedEvent() {
// do whatever you need here
}
}
This is from this answer.

Mocking Spring Boot

I want to implements tests in Spring Boot (Spring Boot 1.4.2.RELEASE), so I am checking this example
https://spring.io/blog/2016/04/15/testing-improvements-in-spring-boot-1-4
but not able to find the given method anywhere in this package
import static org.mockito.Mockito.*
On the bottom of the article there is a link to the github repo with the full source of the test. There you can see the following line:
import static org.mockito.BDDMockito.given;

SpringBoot ComponentScan issue with multi-module project

I have a myapp parent pom type maven project with myapp-core and myapp-web modules. myapp-core module is added as dependency to myapp-web.
All the classes in myapp-core module reside in root package com.myapp.core and all classes in myapp-web module reside in root package com.myapp.web
The main Application.java is also in com.myapp.web package. As my core module root package is different I am including common base package "com.myapp" for ComponentScan as follows:
#Configuration
#ComponentScan(basePackages="com.myapp")
#EnableAutoConfiguration
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Now the surprising thing is if I run this app using Run As -> Spring Boot App it is working fine. But if I run it as Run As -> Java Application it is failing with error saying it can't found beans defined in myapp-core module.
If I move my Application.java to com.myapp package it is working fine.
It should work even if i run it as Java Application also, right?
After enabling debug log level for spring and going through extensive logs I found that scanning for various components like JPA Repositories, JPA Entities etc are depending on the Application.java's package name.
If the JPA Repositories or Entities are not in sub packages of Application.java's package then we need to specify them explicitly as follows:
#Configuration
#ComponentScan(basePackages="com.sivalabs.jcart")
#EnableAutoConfiguration
#EnableJpaRepositories(basePackages="com.sivalabs.jcart")
#EntityScan(basePackages="com.sivalabs.jcart")
public class Application{
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
With the above additional #EnableJpaRepositories, #EntityScan I am able to run it using Run As -> Java Application.
But still not sure how it is working fine when Run As -> Spring Boot App!!
Anyway I think it is better to move my Application.java to com.myapp package rather than fighting with SpringBoot!
I have the same problem. Only adding the #EnableJpaRepositories annotation can solve the issue. I tried to define basePackages in #SpringBootApplication, to no avail.
I think the package of the Application class is fed to the scanning process of JpaRepositories, but other packages defined in #SpringBootApplication are ignored.
It looks like a bug/improvement of Spring Boot.
I had a similar issue with Redis repositories that was fixed in a similar way:
#Configuration
#EnableConfigurationProperties({RedisProperties.class})
#RequiredArgsConstructor
#EnableRedisRepositories(basePackages = {"com.example.another"})
public class RedisConfig {
private final RedisConnectionFactory redisConnectionFactory;
#Bean
public RedisTemplate<?, ?> redisTemplate() {
RedisTemplate<byte[], byte[]> template = new RedisTemplate<byte[], byte[]>();
template.setConnectionFactory(redisConnectionFactory);
template.afterPropertiesSet();
return template;
}
}

Categories