I'm trying to deploy a vaadin website on heroku, the website works well, but the REST api that I made with Spring JPA returns always empty list. When running on my computer it works perfectly. There is no errors in heroku's console. How should I patch that ?
The table class :
package fr.xibalba.axiumwebsite.api.tables;
import com.fasterxml.jackson.annotation.JsonBackReference;
import lombok.*;
import javax.persistence.*;
import java.util.List;
@Entity
@Table(name = "roles")
@NoArgsConstructor
@AllArgsConstructor
@Setter
@Getter
@ToString
@EqualsAndHashCode
public class Role {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", nullable = false, unique = true)
Integer id;
@Column(name = "name", nullable = false, unique = true)
String name;
@Column(name = "priority", nullable = false)
int priority;
@Column(name = "prefix")
String prefix;
@Column(name = "multiple_prefix", nullable = false)
boolean multiple_prefix;
@Column(name = "prefix_color", nullable = false)
String prefix_color;
@Column(name = "suffix")
String suffix;
@Column(name = "multiple_suffix", nullable = false)
boolean multiple_suffix;
@Column(name = "suffix_color", nullable = false)
String suffix_color;
@JsonBackReference
@ManyToMany(mappedBy = "roles")
List<Account> accounts;
}
The JPA repository :
package fr.xibalba.axiumwebsite.api.repositories;
import fr.xibalba.axiumwebsite.api.tables.Role;
import org.springframework.data.jpa.repository.JpaRepository;
public interface RoleRepository extends JpaRepository<Role, Integer> {
Role findByName(String name);
}
The REST controller :
package fr.xibalba.axiumwebsite.api.controllers;
import fr.xibalba.axiumwebsite.api.repositories.RoleRepository;
import fr.xibalba.axiumwebsite.api.tables.Role;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
@RequestMapping("/api/roles")
public class RoleController {
@Autowired
private RoleRepository roleRepository;
@RequestMapping("")
public List<Role> infos(@RequestParam(value = "name", required = false) String name, @RequestParam(value = "id", required = false) Integer id) {
System.out.println("name: " name);
if (name != null && roleRepository.findByName(name) != null) {
System.out.println("role found");
return List.of(roleRepository.findByName(name));
} else if (id != null && roleRepository.findById(id).isPresent()) {
System.out.println("role found");
return List.of(roleRepository.findById(id).get());
} else {
System.out.println("role not found");
return roleRepository.findAll();
}
}
}
My 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>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.1</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>fr.xibalba</groupId>
<artifactId>AxiumWebsite</artifactId>
<version>0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>AxiumWebsite</name>
<description>AxiumWebsite</description>
<properties>
<java.version>18</java.version>
<vaadin.version>23.1.2</vaadin.version>
</properties>
<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-data-rest</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</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>
<dependency>
<groupId>com.vaadin</groupId>
<artifactId>vaadin-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-jose</artifactId>
<version>5.6.3</version>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.vaadin</groupId>
<artifactId>vaadin-bom</artifactId>
<version>${vaadin.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
<plugin>
<groupId>com.heroku.sdk</groupId>
<artifactId>heroku-maven-plugin</artifactId>
<version>3.0.3</version>
<configuration>
<appName>axium-centrality</appName>
<processTypes>
<web>java $JAVA_OPTS -jar target/${project.artifactId}-${project.version}.jar --server.port=$PORT</web>
</processTypes>
</configuration>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>production</id>
<build>
<plugins>
<plugin>
<groupId>com.vaadin</groupId>
<artifactId>vaadin-maven-plugin</artifactId>
<version>23.0.5</version>
<executions>
<execution>
<id>frontend</id>
<phase>compile</phase>
<goals>
<goal>prepare-frontend</goal>
<goal>build-frontend</goal>
</goals>
<configuration>
<productionMode>true</productionMode>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>
Security configuration :
package fr.xibalba.axiumwebsite.security;
import com.vaadin.flow.server.auth.ViewAccessChecker;
import com.vaadin.flow.spring.VaadinConfigurationProperties;
import com.vaadin.flow.spring.security.RequestUtil;
import com.vaadin.flow.spring.security.VaadinDefaultRequestCache;
import com.vaadin.flow.spring.security.VaadinWebSecurityConfigurerAdapter;
import fr.xibalba.axiumwebsite.website.pages.login.LoginView;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import javax.sql.DataSource;
@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends VaadinWebSecurityConfigurerAdapter {
public static final String ROLE_QUERY = "SELECT accounts.username, roles.name "
" FROM accounts "
" LEFT JOIN roles "
" ON (SELECT account_id FROM accounts_roles WHERE role_id = roles.id) = accounts.id "
" WHERE accounts.username = ?;";
@Bean
public PasswordEncoder passwordEncoder() {
return NoOpPasswordEncoder.getInstance();
}
@Autowired
private DataSource dataSource;
@Autowired
private VaadinDefaultRequestCache vaadinDefaultRequestCache;
@Autowired
private RequestUtil requestUtil;
@Autowired
private ViewAccessChecker viewAccessChecker;
@Autowired
private VaadinConfigurationProperties configurationProperties;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.jdbcAuthentication()
.dataSource(dataSource)
.usersByUsernameQuery("SELECT username, password, enabled FROM accounts WHERE username = ?")
.authoritiesByUsernameQuery(ROLE_QUERY)
.passwordEncoder(passwordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
setLoginView(http, LoginView.class);
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/api/**");
super.configure(web);
}
}
Security service :
package fr.xibalba.axiumwebsite.security;
import com.vaadin.flow.component.UI;
import com.vaadin.flow.server.VaadinServletRequest;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
import org.springframework.stereotype.Component;
@Component
public class SecurityService {
private static final String LOGOUT_SUCCESS_URL = "/";
public UserDetails getAuthenticatedUser() {
SecurityContext context = SecurityContextHolder.getContext();
Object principal = context.getAuthentication().getPrincipal();
if (principal instanceof UserDetails) {
return (UserDetails) context.getAuthentication().getPrincipal();
}
return null;
}
public void logout() {
UI.getCurrent().getPage().setLocation(LOGOUT_SUCCESS_URL);
SecurityContextLogoutHandler logoutHandler = new SecurityContextLogoutHandler();
logoutHandler.logout(
VaadinServletRequest.getCurrent().getHttpServletRequest(), null,
null);
}
}
Logs : https://pastebin.com/kJ28qZWR
CodePudding user response:
Did you read the logs?
2022-08-03T17:11:42.857267 00:00 app[web.1]: name: null
2022-08-03T17:11:42.938858 00:00 app[web.1]: role not found
2022-08-03T17:11:43.003201 00:00 heroku[router]: at=info method=GET path="/api/roles/?id=0" host=axium-centrality.herokuapp.com request_id=8fcfca84-a102-4252-b4d3-f53f41574710 fwd="109.30.116.102" dyno=web.1 connect=0ms service=270m
You have no user with id=0
in your database.
CodePudding user response:
I found the problem, I configured jpa from application.properties, and appeared to be edit by the server, I put it in a configuration class and it works