I understand how Spring JPA repository works. I am using an open source project (Apereo CAS 6.4),
CAS uses Spring Boot 2.x and JdbcTemplate for DB access, it does not use Spring JPA Data Repository. I was able to easily add that in CAS 5.3 (Spring Boot 1.5.18), but run into difficulty with CAS 6.4 (Spring Boot 2.4.5).
I keep getting error: NoSuchBeanDefinition when deploy WAR to Tomcat9, in other words, Spring Data JPA did not instantiate beans for repository interfaces as it should. All my Spring Data Repository configuration is correct and that is why it is working in CAS5.3, such as the spring-data-jpa dependencies, specifying packages for @EnableJpaRepository, @EntityScan in a @Configuration class.
How can I debug this, to figure out why Spring does not instantiate beans that implements Repository interfaces? For instance, what would show up in logs if Spring Data JPA is correctly instantiating beans?
I just realized that I have not tried starting up at command line as executable WAR/Jar, i would not think that makes any difference.
Thanks, Yan
Here is the CAS 6.3 code with my modification to use Spring Data JPA.
== Main Class ==
@SpringBootApplication(
scanBasePackages = {"org.apereo.cas", "com.quest.cas"},
exclude = {
GroovyTemplateAutoConfiguration.class
},
proxyBeanMethods = false)
@EnableJpaRepositories(basePackages = {"com.quest.cas.prs.model"})
@EntityScan(basePackages = {"com.quest.cas.prs.model"})
@EnableConfigurationProperties(CasConfigurationProperties.class)
@EnableAsync
@EnableAspectJAutoProxy(proxyTargetClass = true)
@EnableTransactionManagement(proxyTargetClass = true)
@EnableScheduling
@NoArgsConstructor
@Slf4j
public class CasWebApplication {
/**
*
* Main entry point of the CAS web application.
*
* @param args the args
*/
public static void main(final String[] args) {
val banner = CasEmbeddedContainerUtils.getCasBannerInstance();
new SpringApplicationBuilder(CasWebApplication.class)
.banner(banner)
.web(WebApplicationType.SERVLET)
.logStartupInfo(true)
.contextClass(CasWebApplicationContext.class)
.contextFactory(webApplicationType -> new CasWebApplicationContext())
.applicationStartup(CasEmbeddedContainerUtils.getApplicationStartup())
.run(args);
}
/**
* Handle application ready event.
*
* @param event the event
*/
@EventListener
public void handleApplicationReadyEvent(final ApplicationReadyEvent event) {
AsciiArtUtils.printAsciiArtReady(LOGGER, StringUtils.EMPTY);
LOGGER.info("QuestCAS: Ready to process requests @ [{}]", DateTimeUtils.zonedDateTimeOf(Instant.ofEpochMilli(event.getTimestamp())));
}
}
=== Repository Class ===
package com.quest.cas.prs.model;
import org.springframework.data.jpa.repository.JpaRepository;
public interface PrsUserRepository extends JpaRepository<PrsUser, Long> {
public PrsUser findByLoginNameIgnoreCase(String name);
}
=== Entity Class ===
package com.quest.cas.prs.model;
import java.io.Serializable;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
import com.fasterxml.jackson.annotation.JsonIgnore;
@Entity
@Table(name="CAS_USER")
public class PrsUser implements Serializable {
private static final long serialVersionUID = -3022044405702204502L;
@Id
@Column(name = "CAS_USER_ID")
@SequenceGenerator(name="CAS_USER_GENERATOR", sequenceName="CAS_USER_ID_SEQ", allocationSize = 1)
@GeneratedValue(strategy= GenerationType.SEQUENCE, generator="CAS_USER_GENERATOR")
private Long id;
@Column(name="EMAIL_ADDRESS")
private String emailAddress;
.....
}
==== build.gradle file ====
implementation ("org.springframework.boot:spring-boot-starter-data-jpa:2.4.5") {
exclude group: 'org.springframework.boot'
exclude module: 'spring-boot-starter-logging'
}
implementation "org.springframework.data:spring-data-jpa:2.4.8"