Spring data jpa repository findBy returning null even if data present in DB - spring

I am using spring data JPA, facing issue as result is always coming NULL even if record present into DB.
I tried debugging spring code and checked whether statement created correctly or not. Statement is created correctly and parameter is also populated correctly.
Configuration: -
Spring-boot = 2.0.5.RELEASE
Oracle DB = Oracle Database 11g Release 11.2.0.2.0 - 64bit
POM
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<exclusions>
<exclusion>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-jdbc</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc7</artifactId>
<version>12.1.0</version>
</dependency>
</dependencies>
Entity class:
#Entity()
public class User {
#Id
#GeneratedValue(strategy=GenerationType.SEQUENCE, generator = "user_Sequence")
#SequenceGenerator(name = "user_Sequence", sequenceName = "USER_SEQ")
private Long id;
#Column(unique=true)
private String userName;
private String password;
//getter & setter
Repository class
#Repository
public interface UserRepository extends
org.springframework.data.repository.CrudRepository<User, Long>{
User findByUserName(String userName);
User save(User user);
}
Service class
#Service("loginService")
public class LoginService implements ILoginService {
#Autowired
UserRepository userRepository;
#Override
public boolean isValidUser(String userName, String password) {
User user = userRepository.findByUserName(userName);
if(user != null && user.getUserName().equals(userName) && user.equals(password)){
return true;
} else {
return false;
}
}
}
Debug Screenshot : -
Debug Screenshot parameter value is "admin" and SQL formed
SQL Formed : -
select user0_."id" as id1_2_, user0_."password" as password2_2_, user0_."user_name" as user_name3_2_ from "user" user0_ where user0_."user_name"=?
If I run same query in DB, result is : -
Result Screenshot

Since you are not using your column name as your field names it needs to know what to map to in your entity.
Change your field to either be user_name or change:
#Column(unique=true)
private String userName;
to
#Column(name="user_name", unique=true)
private String userName;
thus it will be able to know what column it references;
https://www.concretepage.com/spring-5/spring-data-crudrepository-example

use findByNameEqualsAndStatus in Repository

Below are things that work for me. I am using Oracle 19C with org.hibernate.dialect.Oracle12cDialect.
grant all on <schema>.<table> to <user>;
grant all on <schema>.<sequence> to <user>;

Related

spring-boot-starter-data-mongodb doesn't seem to include persistence-api to use #PrePersist #PreUpdate

What is the correct way to include and use JPA Entity Lifecycle Events when using spring-boot-starter-data-mongodb?
my pom.xml dependencies
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
My classpath doesn't see to have any of the following JPA annotations:
#PrePersist
#PostPersist
#PreRemove
#PostRemove
#PreUpdate
#PostUpdate
#PostLoad
Mongo has its own events documented # #Entity Callbacks.
Example:
class DefaultingEntityCallback implements BeforeSaveCallback<Person>, Ordered {
#Override
public Object onBeforeSave(Person entity, String collection) {
if(collection == "user") {
return // ...
}
return // ...
}
#Override
public int getOrder() {
return 100;
}
}
Following Functional interfaces available:
org.springframework.data.mongodb.core.mapping.event.AfterConvertCallback
org.springframework.data.mongodb.core.mapping.event.AfterSaveCallback
org.springframework.data.mongodb.core.mapping.event.BeforeConvertCallback
org.springframework.data.mongodb.core.mapping.event.BeforeSaveCallback
org.springframework.data.mongodb.core.mapping.event.ReactiveAfterConvertCallback
org.springframework.data.mongodb.core.mapping.event.ReactiveAfterSaveCallback
org.springframework.data.mongodb.core.mapping.event.ReactiveBeforeConvertCallback
org.springframework.data.mongodb.core.mapping.event.ReactiveBeforeSaveCallback

Spring boot connection with mysql workbecnch

I created a spring boot maven project using STS eclipse
In application.properties
spring.datasource.url = jdbc:mysql://localhost:3306/crud
spring.datasource.username = root
spring.datasource.password = root
spring.jpa.hibernate.ddl-auto = update
I created Player entity class, then I run the project but in my workbench there is no table created. Is that because spring boot not connect with db? Then how can I overcome this problem.
This is my pom.xml
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>javax.persistence</groupId>
<artifactId>persistence-api</artifactId>
<version>1.0.2</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
This is player Entity
#Entity
#Table(name = "PLAYER")
public class Player {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "PLAYER_ID")
private int id;
#Column(name = "PLAYER_NAME")
private String playerName;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getPlayerName() {
return playerName;
}
public void setPlayerName(String playerName) {
this.playerName = playerName;
}
}
Maybe you didn't create the Database.
You try to create the database or replace the connection string with the following:
spring.datasource.url = jdbc:mysql://localhost:3306/crud?createDatabaseIfNotExist=true
UPDATE
Please add the following dependency in your pom.xml:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
and delete the following dependency:
<dependency>
<groupId>javax.persistence</groupId>
<artifactId>persistence-api</artifactId>
<version>1.0.2</version>
</dependency>

FF4J - Spring Boot - Custom Authorization Manager

I am trying to create a standalone feature flag server (centrally managed feature flag micro-service) backed by spring boot starters provided by FF4J. I was able to get it up and running with the web-console and REST API as well. I am now trying to just add the support of custom authorization manager as provided in the wiki, but based on the sample provided there, I am unclear as to how the authorization manager would be aware of the user context when it gets accessed from a different microservice which is implementing the feature. Below I have provided all the relevant code snippets. If you notice in CustomAuthorizationManager class, I have a currentUserThreadLocal variable, not sure how or who is going to set that at run time for FF4J to verify the user's role. Any help on this is really appreciated, as I having issues understanding how this works.
Also note, there is a toJson method in authorization manager that needs to be overridden, not sure what needs to go over there, any help with that is also appreciated.
Custom Authorization Manager
public class CustomAuthorizationManager implements AuthorizationsManager {
private static final Logger LOG = LoggerFactory.getLogger(FeatureFlagServerFeignTimeoutProperties.class);
private ThreadLocal<String> currentUserThreadLocal = new ThreadLocal<String>();
private List<UserRoleBean> userRoles;
#Autowired
private SecurityServiceFeignClient securityServiceFeignClient;
#PostConstruct
public void init() {
try {
userRoles = securityServiceFeignClient.fetchAllUserRoles();
} catch (Exception ex) {
LOG.error("Error while loading user roles", ex);
userRoles = new ArrayList<>();
}
}
#Override
public String getCurrentUserName() {
return currentUserThreadLocal.get();
}
#Override
public Set<String> getCurrentUserPermissions() {
String currentUser = getCurrentUserName();
Set<String> roles = new HashSet<>();
if (userRoles.size() != 0) {
roles = userRoles.stream().filter(userRole -> userRole.getUserLogin().equals(currentUser))
.map(userRole -> userRole.getRoleName()).collect(Collectors.toSet());
} else {
LOG.warn(
"No user roles available, check startup logs to check possible errors during loading of user roles, returning empty");
}
return roles;
}
#Override
public Set<String> listAllPermissions() {
Set<String> roles = new HashSet<>();
if (userRoles.size() != 0) {
roles = userRoles.stream().map(userRole -> userRole.getRoleName()).collect(Collectors.toSet());
} else {
LOG.warn(
"No user roles available, check startup logs to check possible errors during loading of user roles, returning empty");
}
return roles;
}
#Override
public String toJson() {
return null;
}
}
FF4J config
#Configuration
#ConditionalOnClass({ ConsoleServlet.class, FF4jDispatcherServlet.class })
public class Ff4jConfig extends SpringBootServletInitializer {
#Autowired
private DataSource dataSource;
#Bean
public ServletRegistrationBean<FF4jDispatcherServlet> ff4jDispatcherServletRegistrationBean(
FF4jDispatcherServlet ff4jDispatcherServlet) {
ServletRegistrationBean<FF4jDispatcherServlet> bean = new ServletRegistrationBean<FF4jDispatcherServlet>(
ff4jDispatcherServlet, "/feature-web-console/*");
bean.setName("ff4j-console");
bean.setLoadOnStartup(1);
return bean;
}
#Bean
#ConditionalOnMissingBean
public FF4jDispatcherServlet getFF4jDispatcherServlet() {
FF4jDispatcherServlet ff4jConsoleServlet = new FF4jDispatcherServlet();
ff4jConsoleServlet.setFf4j(getFF4j());
return ff4jConsoleServlet;
}
#Bean
public FF4j getFF4j() {
FF4j ff4j = new FF4j();
ff4j.setFeatureStore(new FeatureStoreSpringJdbc(dataSource));
ff4j.setPropertiesStore(new PropertyStoreSpringJdbc(dataSource));
ff4j.setEventRepository(new EventRepositorySpringJdbc(dataSource));
// Set authorization
CustomAuthorizationManager custAuthorizationManager = new CustomAuthorizationManager();
ff4j.setAuthorizationsManager(custAuthorizationManager);
// Enable audit mode
ff4j.audit(true);
return ff4j;
}
}
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>feature-flag-server</artifactId>
<version>1.0.0-SNAPSHOT</version>
<name>feature-flag-server</name>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.1.RELEASE</version>
</parent>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Hoxton.RC2</spring-cloud.version>
<ff4j.version>1.8.2</ff4j.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
<exclusions>
<!-- resolve swagger dependency issue - start -->
<exclusion>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</exclusion>
<!-- resolve swagger dependency issue - end -->
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- FF4J dependencies - start -->
<dependency>
<groupId>org.ff4j</groupId>
<artifactId>ff4j-spring-boot-starter</artifactId>
<version>${ff4j.version}</version>
</dependency>
<dependency>
<groupId>org.ff4j</groupId>
<artifactId>ff4j-store-springjdbc</artifactId>
<version>${ff4j.version}</version>
</dependency>
<dependency>
<groupId>org.ff4j</groupId>
<artifactId>ff4j-web</artifactId>
<version>${ff4j.version}</version>
</dependency>
<!-- FF4J dependencies - end -->
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Full disclosure I am the maintainer of the framework.
The documentation is not good on this part, improvements are in progress. But here is some explanation for a working project.
When using AuthorizationManager:
AuthorizationManager principle should be used only if you already enabled authentication in your application (LOGIN FORM, ROLES...). If not you can think about FlipStrategy to create your own predicates.
FF4j will rely on existing security frameworks to retrieve context of logged user, this is called the principal. As such this is unlikely for you to create your own custom implementation of AuthorizationManager except you are building your own authentication mechanism.
What to do:
You will use well known framework such as Spring Security of Apache Shiro to secure your applications and simply tell ff4j to rely on it.
How to do:
Here is working example using SPRING SECURITY:
https://github.com/ff4j/ff4j-samples/tree/master/spring-boot-2x/ff4j-sample-security-spring
Here is working example using APACHE SHIRO:
https://github.com/ff4j/ff4j-samples/tree/master/spring-boot-2x/ff4j-sample-security-shiro

#DeleteMapping not recognized

I am new with spring boot, is very simple my question but I canĀ“t find where is the problem.
I have a basic #GetMapping and #DeleteMapping
#RestController
public class MyController
{
private MyServiceImpl myService;
#Autowired
public MyController(MyServiceImpl myService)
{
this.myService = myService;
}
#GetMapping("/test")
public List<Scan> getTestData(#RequestParam(value = "test_id", required = true) String test_id) {
return myService.findByTestId( test_id );
}
#DeleteMapping("/test")
public int deleteData(#RequestParam(value = "test_id", required = true) String test_id){
return myService.deleteTest( test_id );
}
#DeleteMapping("/test2")
public String deleteArticle() {
return "Test";
}
}
I am testing with Postman, the Get request is working, but the delete request is not. Even when I debug the spring boot application. The GetMapping is called, whereas the delete is not "reacting" /called
Maybe is not enough information, but I even tested #DeleteMapping("/test2") is not doing anything, I mean, I get no response, and in Postman it stays "loading..."
Any suggestions?
My complete POM
http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
<parent>
<groupId>com.ttt.pdt</groupId>
<artifactId>pdt-base</artifactId>
<version>2.0-SNAPSHOT</version>
</parent>
<artifactId>pdt-service</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.4.0</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.4.0</version>
</dependency>
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
The parent (pdt-base) has
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.3.RELEASE</version>
</parent>
MyServiceImpl
#Service
public class MyServiceImpl
{
private ScnDao scnDao;
#Autowired
public ScanServiceImpl(ScnDao scnDao){
this.scnDao = scnDao;
}
public int deleteTest( String test_id )
{
return scnDao.deleteTest( test_id );
}
}
public interface ScanDao
{
int deleteTest( String test_id )
}
#Repository
public class ScnPostgres implements ScnDao
{
private JdbcTemplate jdbcTemplate;
#Autowired
public ScnPostgres( JdbcTemplate jdbcTemplate )
{
this.jdbcTemplate = jdbcTemplate;
}
public int deleteTest( String test_id )
{
String SQL = "DELETE FROM scn WHERE test_id = ?";
return jdbcTemplate.update( SQL, new String[] { test_id } );
}
}
As in SPR comments described SPR-16874:
it does not support DELETE currently. It would be a trivial change to
make. There is suggested a workaround:
#DeleteMapping(value = "/greeting")
public Greeting handle(#RequestBody MultiValueMap<String, String> params) {
return new Greeting(counter.incrementAndGet(),
String.format(template, params));
}
As you can see the issue has been opened in the spring boot tracker.

Spring Bean Validation with Hibernate: validation not happening on update

I have a class defined as follows:
import org.hibernate.validator.constraints.NotBlank;
public class Game {
#GeneratedValue(strategy = GenerationType.AUTO)
#Id
#Column(name = "id")
Long id;
#NotBlank
#Column(name = "title")
String title;
...
However, when I execute the following test, no validation exception is thrown:
#Test(expected = ConstraintViolationException.class)
public void thatExistingGameGivenBlankTitleCannotBeSaved(){
Game game = new Game("SimCity 2000");
gameDAO.save(game);
game.setTitle(" "); //game.setTitle(null) doesn't work either
gameDAO.save(game);
}
How can I make the validator trigger when saving an already persisted object? Preferably through Java configuration.
My validation dependencies:
<!-- validation -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.1.0.Final</version>
</dependency>
<dependency>
<groupId>javax.el</groupId>
<artifactId>javax.el-api</artifactId>
<version>2.2.4</version>
</dependency>
<dependency>
<groupId>org.glassfish.web</groupId>
<artifactId>javax.el</artifactId>
<version>2.2.4</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator-cdi</artifactId>
<version>5.1.0.Final</version>
</dependency>
Your JPA implementation has to integrate bean validation. If you're using Hibernate this will happen automatically by putting the validation provider in the class path. If not read 10.1.3. JPA. Given your tags I assume you're using JPA/Hibernate and it should work.
I don't know what gameDAO.save() is calling on your JPA implementation. Hibernate's integration is event based. If your save() is none of these events there will be no validation by default:
PreInsertEvent
PreUpdateEvent
PreDeleteEvent

Resources