Why get warning in repository "Unnecessary `#Repository`" - java

I am working on Spring Boot project. I have repository file in my project but it will show me a warning message in repository class Unnecessary #Repository. I am extending a JpaRepository<> with my repository. My Spring version is 4 and JDK version is 17.
Here is my dependencies
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
Here is my repository
#Repository // Here I get a warning to remove this annotation becasue its unnecessary
public interface CollegeRepo extends JpaRepository<College, Integer>{
}

You are extending JpaRepository<T, ID> interface, it means that spring boot must autoconfigure this repository bean for you, namely, it will be configured a proxy bean of SimpleJpaRepository<T, ID>.
In simple words, we do not just create a bean using #Repository or #Component annotation, we extend the spring-data interface and then our repository bean will be autoconfigured.

When to use #Repository
You want to provide your own implementation of how to access the data layer and what should be done. In this case marking your implementation class with #Repository will allow you to have this class managed by spring so that you can autowire necessary fields to access data layer like EntityManager , JdbcTemplate ...etc. Although Component, and #Repository in the most fundamental level just register spring beans there are some slight enhancements using #Repository which might make it neccessary to use and also best practice in the current case.
As per doc1
A class thus annotated with #Repository is eligible for Spring
DataAccessException translation when used in conjunction with a
PersistenceExceptionTranslationPostProcessor.,
and doc2
PersistenceExceptionTranslationPostProcessor
Bean post-processor that
automatically applies persistence exception translation to any bean
marked with Spring's #Repository annotation, adding a corresponding
PersistenceExceptionTranslationAdvisor to the exposed proxy
Example of above case use with #Repository.
#Repository
public class CustomCarRepositoryImpl implements CustomCarRepository {
#PersistenceContext
private EntityManager entityManager;
#Override
public List<CarEntity> findCarsWithSpeed(Integer speed) {
return entityManager.createQuery("Query to execute")
.setMaxResults(50).getResultList();
}
}
public interface CustomCarRepository {
List<CarEntity> findCarsWithSpeed(Integer speed);
}
Then you can autowire in your other components the CustomCarRepository and access the data layer as you have implemented.
When Not to use #Repository
When you just declare your interface and you extend from any Spring child interface of Repository from org.springframework.data.repository.
Example
public interface CarRepository extends JpaRepository<CarEntity, Long> {
List<CarEntity> findCarsWithSpeed(Integer speed);
}
In that case Spring Boot will be able to create the repository bean for you automatically from auto configuration.
The only further action needed is if your own interfaces extending from Repository do not exist in the same package or subpackage of where your #Configuration or #SpringBootApplication exists then you would need
either #EnableJpaRepositories(basePackages = {"base-package-where-repositories-exist"})
or #AutoConfigurationPackage(basePackages = {"base-package-where-repositories-exist"})
as to help spring boot identify the package it should look for the auto configuration of that repository. ( The later #AutoConfigurationPackage will affect both repositories and other things required for auto configuration like entities scan and more. So it should be used with care in a project and not just for repositories.)

The Solution depends upon what type of database you intend to use. "Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured." Error you're getting is because you have not set the url for the database in the application.properties. To solve this issue I would recommend you to Open the application.properties and add the following according to your system:
spring.datasource.url=jdbc:mysql://localhost:3306/restapi
spring.datasource.username=root
spring.datasource.password=

Related

How to use Annotations in a Spring Boot Library (without Main Class)?

I am new to spring boot and trying to figure out some of its working. Here I am getting Null Pointer Exception for the below implementation. I am not sure can we use #Autowire annotation for a Library project without a Main class. Maybe this sounds stupid,I believe we can do a #ComponentScan for the Library Project from a Service project that's created.My Question is looking at the below implementation is there any possibility to use annotation in the below library project, because Annotations are throwing NullPointerException for the below code?
Library
The below code is a library and it Doesn't have a Main Class
#Service
class Data {
public String getData(){
return "DATA";
}
}
class Access{
#Autowired
private Data data;
public String myData(){
return data.getData(); // Null pointer exception
}
}
pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
Service
The below code is of a Service which is accessing the above library
Controller
#GetMapping("/")
String print(){
// Accesses the Library
Access access=new Access();
return access.myData();
}
#SpringBootApplication
#ComponentScan(basePackages = { "com.service", "com.library" }) // Hopes this Scans the library package
public class UserApplication {
public static void main(String[] args) {
SpringApplication.run(UserApplication.class, args);
}
}
pom.xml
<dependency>
<groupId>com.library</groupId>
<artifactId>library</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
If I remove the Autowired from the library code, and create the object normally (using new keyword), everything works fine. So my question is, Main class with #SpringBootApplication is required inorder to use annotations, without a Main class can't we run it?
The best practice if you're not relying on any Spring AOP features (such as #Transactional) is don't do it at all. #Autowired on fields is fragile; instead, use a normal constructor. Spring needs no annotations to instantiate a bean if you have only a single constructor, and this makes your class usable in a different DI environment or in plain Java (such as for testing).
Similarly, don't put #Service on a class in a library; clients who want it can simply use #Import to pull it in.
The one exception to this is that if you are providing a Boot auto-configuration setup, that module will need to depend on spring-boot-autoconfigure to access the annotations. Note that it is customary to put your starter in a separate dependency that contains only the Boot classes and metafiles.
All you need to do is annotate your library Access class with #Service Or #Component
And in your Controller class create a field for Access class and autowire it.
Then use it inside your method
#Service
class Access{
#Autowired
private Data data;
public String myData(){
return data.getData();
}
}
#RestController
class YourController {
#Autowired
Access access
#GetMapping("/")
String print(){
return access.myData();
}
With SpringBootApplication annotation, It will create application context with all required beans when starting the application. The object will be injected whenever it needed.
But in the Normal java application, the Object will be created while calling the new keyword.
#SpringBootApplication it required when you have #Autowired annotation otherwise you will get error.

Swagger UI with springdoc-openapi-ui doesn't show the APIs in the generated "#Controller" class

I have a Spring Boot application where the API is specified as a OpenAPI 3.0.2 YAML document. I used the openapi-generator-maven-plugin to generate code from the spec. When I open up http://localhost:8080/swagger-ui.html, it displays: "No operations defined in spec!"
In the spec, I have:
servers:
- url: /books/api/v1
Which results in this in the controller class:
#javax.annotation.Generated(value = "org.openapitools.codegen.languages.SpringCodegen", date = "2021-06-17T14:52:43.686820-07:00[America/Los_Angeles]")
#Controller
#RequestMapping("${openapi.axmPlatformKeyService.base-path:/books/api/v1}")
public class SvcApiController implements SvcApi {
// ...
// ...
}
If I load the openapi-definition.yaml in editor.swagger.io, it shows the definitions as expected.
If I create another controller this way:
#RestController
public class AddonController implements SvcApi {
// ...
// ...
}
then Swagger UI shows the APIs, which basically means that if the generated code had "#RestController" it would have worked okay.
Since the generated controller is annotated with #Controller, Swagger UI is not able to pick it up. Even after adding this extra #RestController, Swagger UI's Try it out function doesn't include "/books/api/v1" in the URL it generates.
Net-effect is with this AddonController, if I have one request /book/{id} in the spec, there are two endpoints in the service:
/books/api/v1/book/{id}
/book/{id}
and the latter is invoked by Swagger UI.
These are the relevant dependencies:
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>
<version>1.5.0</version>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
<version>1.6.2</version>
</dependency>
Adding a static initializer that does
SpringDocUtils.getConfig().addRestControllers(SvcApiController.class)
resolves the issue. The AddonController is not needed in this case.

Which class is responsible for scanning #Entity annotation in Spring JPA, Hibernate?

I'm looking for a Class which is responsible for Scanning all classes annotated with #Entity in JPA, Hibernate, or Spring.
I want to extend that class and add some logic while scanning the class.
I have searched everywhere( spring docs, JPA, Hibernate docs) but could not find it.
As soon as Spring boot detects you need that, the auto configuration of the JPA repositories is enabled.
From the #JpaRepositoriesAutoConfiguration specification (emphasis is mine) :
Auto-configuration for Spring Data's JPA Repositories. Activates when
there is a bean of type DataSource configured in the context, the
Spring Data JPA JpaRepository type is on the classpath, and there is
no other, existing JpaRepository configured. Once in effect, the
auto-configuration is the equivalent of enabling JPA repositories
using the EnableJpaRepositories annotation. This configuration class
will activate after the Hibernate auto-configuration.
To override that, add explicitly the #EnableJpaRepositories annotation but you could not add any logic in but fields defined in the annotation.
Can't help you with the native class, which is responsible for scanning, but can tell you how to scan in your own class. The code is borrowed from my project - it enables exposing of id for each entity. You don't have to add new into the list each time - it's easy to forget this step.
You need to have a configuration extending RepositoryRestConfigurerAdapter or RepositoryRestMvcConfiguration and to add a method as follows:
#Override
public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
// getting a list of all classes annotated with #Entity
List<Class<?>> classes = CPScanner.scanClasses(new PackageNameFilter("ru.outofrange.*"),
new ClassFilter().appendAnnotation(Entity.class));
Class[] arrayClasses = new Class[classes.size()];
for (int i = 0; i < classes.size(); i++) {
arrayClasses[i] = classes.get(i);
}
config.exposeIdsFor(arrayClasses);
}
This dependency is required:
<dependency>
<groupId>net.sf.corn</groupId>
<artifactId>corn-cps</artifactId>
<version>1.0.1</version>
</dependency>
I think this is a very broad question but you need to look at the source code to understand that.

Spring Data Solr repositories using JavaConfig

I'm trying to create a SpringBoot application which uses solr repositories. I'm following this tutorial:
http://docs.spring.io/spring-data/solr/docs/current/reference/html/#solr.repositories
which says to configure my application with the following class (Example 43):
#Configuration
#EnableSolrRepositories
class ApplicationConfig {
#Bean
public SolrClient solrClient() {
EmbeddedSolrServerFactory factory = new EmbeddedSolrServerFactory("classpath:com/acme/solr");
return factory.getSolrServer(); // getSolrServer does not exist
}
#Bean
public SolrOperations solrTemplate() {
return new SolrTemplate(solrClient());
}
}
The problem is if I do that it doesn't recognise getSolrServer() as a method of factory. Indeed, if you look at the most recent API for EmbeddedSolrServerFactory you don't find that method, but it apparently existed in a previous version of the same class.
Maybe it was renamed from getSolrServer to getSolrClient, for some reason, from one version to another.
Here's my dependencies in the pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-solr</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
Anyway, I tried to change getSolrServer to getSolrClient, but the return type, i.e. SolrClient, is now incompatible. If I try to return org.apache.solr.client.solrj.embedded.EmbeddedSolrServer, it gives me an error because it doesn't find org.apache.solr.client.solrj.embedded...
Another problem using this would be that SolrTemplate doesn't require a EmbeddedSolrServer, so this is not a good option...
I am using eclipse not spring suite, Assuming spring suite using latest version of spring-boot-starter-data-solr ( 1.4.2 ) and you need to add an entry for solr-core 5.x in your pom.
Since EmbeddedSolrServer is extending SolrClient, follows Java IS-A relationship and it should be compatible with SolrClient. This binary is part of solr-core.
Your code need to use getSolrClient itself and it should be compatible with SolrClient
Dependencies in pom.xml is as follows
Here we go with our code base without any errors.
Instead of creating SolrClient bean, create EmbeddedSolrServerFactoryBean object and pass that object to solr template to create SolrTemplate object. Here is my config file:
#Configuration
#EnableSolrRepositories(basePackages = "com.ida.*.repository")
#Profile("dev")
public class SolrConfigDev {
#Autowired
private Environment environment;
#Bean
public EmbeddedSolrServerFactoryBean solrServerFactoryBean() {
EmbeddedSolrServerFactoryBean factory = new EmbeddedSolrServerFactoryBean();
factory.setSolrHome(environment.getRequiredProperty("solr.solr.home"));
return factory;
}
#Bean
public SolrTemplate solrTemplate() throws Exception {
return new SolrTemplate(solrServerFactoryBean().getObject());
}
}
In addition, you have to add solr-core to you pom.xml file.
<dependency>
<groupId>org.apache.solr</groupId>
<artifactId>solr-core</artifactId>
<version>5.5.3</version>
</dependency>
More information about this topic, you can find here in this blog by Petri Kainulainen.

Spring Boot with MongoTemplate

I am new to Spring Boot and MongoDb.
Trying some examples with Mongo Repositories and Spring Boot.
But after going through some of the documents found that Mongo Template is will be a better option. Unable to get a proper Spring Boot with Mongo Template example.
Can someone please help me out with an example for the same.
Do we need to create a User defined Repositories interface and extend Repositories or CRUD Repository, while trying for Mongo Template ?
For further explanation, you can even use both at the same time.
MongoRepository is just an abstraction layer, like MongoTemplate, but with simpler interface.
If you found doing some kind of operation is too complicated with Spring query-creation, and somehow doesn't want to use #Query (for example, you want IDE type hint when constructing queries), you can extend the MongoRepository and use MongoTemplate as the query mechanism.
First we extend our repository with our custom interface.
#Repository
public interface ArticleRepository extends MongoRepository<Article, String>, CustomArticleRepository {
}
Then declare the interface.
public interface CustomArticleRepository {
List<Article> getArticleFilteredByPage(int page, int num);
}
And then implement our custom repository. We can autowire the MongoTemplate here and use it to query the database.
public class CustomArticleRepositoryImpl implements CustomArticleRepository {
#Autowired
MongoTemplate mongoTemplate;
#Override
public List<Article> getArticleFilteredByPage(int page, int num) {
return mongoTemplate.findAll(Article.class)
.skip(page * num)
.take(num);
}
}
Last, we use the ArticleRepository.
#Service
public class ArticleServiceImpl {
#Autowired
private ArticleRepository articleRepository;
public List<Article> getArticleByPage() {
return articleRepository.getArticleFilteredByPage(1, 10);
}
}
I have found some examples using Mongo Template
http://docs.spring.io/spring-data/data-document/docs/current/reference/html/#mongo-template
http://www.mkyong.com/mongodb/spring-data-mongodb-hello-world-example/
If you are interested in using JPA, please see below
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<version>{mongo.driver.version}</version>
</dependency>
application.properties
#Mongo DB
spring.data.mongodb.database=
spring.data.mongodb.host=
spring.data.mongodb.password=
spring.data.mongodb.port=
spring.data.mongodb.repositories.enabled=
spring.data.mongodb.uri=
spring.data.mongodb.username=
SpringBoot class
#SpringBootApplication
#EnableAutoConfiguration(exclude = { DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class })
public class UserApp {
Mongo Repository
#Repository
public interface UserRepository extends MongoRepository<User, Long> {}

Categories

Resources