Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

spring6_springboot3_hibernate6 #1539

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
3 changes: 2 additions & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,8 @@ jobs:

- name: Build
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_USERNAME: ${{ secrets.GITHUB_USERNAME }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
cd eperusteet/eperusteet-service
mvn clean verify -B -Pit
Expand Down
2 changes: 1 addition & 1 deletion Justfile
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ sync_localisations:
# Generoi openapi-kuvauksen
gen_openapi:
@cd eperusteet/eperusteet-service/ \
&& mvn clean compile -P generate-openapi \
&& mvn verify -DskipTests -Pspringdoc -Dspring-boot.run.profiles=default,dev \
&& cp target/openapi/eperusteet.spec.json ../../generated

# Generoi julkinen openapikuvaus
Expand Down
390 changes: 279 additions & 111 deletions eperusteet/eperusteet-service/pom.xml

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,39 @@
import fi.vm.sade.eperusteet.hibernate.HibernateInterceptor;
import fi.vm.sade.eperusteet.repository.version.JpaWithVersioningRepositoryFactoryBean;
import fi.vm.sade.eperusteet.service.security.PermissionEvaluator;
import jakarta.persistence.EntityManager;
import jakarta.validation.ValidatorFactory;
import org.flywaydb.core.Flyway;
import org.hibernate.jpa.HibernateEntityManager;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.jpa.HibernatePersistenceProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.context.annotation.FilterType;
import org.springframework.context.annotation.Profile;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.support.ResourceBundleMessageSource;
import org.springframework.core.task.TaskExecutor;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.task.DelegatingSecurityContextAsyncTaskExecutor;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
import org.springframework.web.servlet.handler.HandlerMappingIntrospector;

import javax.sql.DataSource;
import java.text.MessageFormat;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

@Profile("!test")
Expand All @@ -39,7 +44,7 @@
@EnableAsync
@EnableCaching
@EnableTransactionManagement
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
@EnableMethodSecurity(securedEnabled = true)
@EnableAspectJAutoProxy // (proxyTargetClass = true)
@EnableJpaRepositories(basePackages = "fi.vm.sade.eperusteet.repository", repositoryFactoryBeanClass = JpaWithVersioningRepositoryFactoryBean.class)
@PropertySource(
Expand All @@ -52,6 +57,9 @@ public class DefaultConfigs {
@Autowired
private DataSource dataSource;

// @Autowired
// private ValidatorFactory validatorFactory;

@Bean
public TaskExecutor defaultExecutor() {
final ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
Expand All @@ -75,10 +83,10 @@ public DefaultMethodSecurityExpressionHandler expressionHandler() {
return expressionHandler;
}

@Bean
public LocalValidatorFactoryBean validator() {
return new LocalValidatorFactoryBean();
}
// @Bean
// public LocalValidatorFactoryBean validator() {
// return new LocalValidatorFactoryBean();
// }

@Bean(initMethod = "migrate")
public Flyway flyway() {
Expand All @@ -89,17 +97,27 @@ public Flyway flyway() {
.load();
}

@Bean
public HibernateInterceptor hibernateInterceptor() {
return new HibernateInterceptor();
}
// @Bean
// public HibernateInterceptor hibernateInterceptor() {
// return new HibernateInterceptor();
// }

// @Bean
// public ResourceBundleMessageSource messageSource() {
// ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
// messageSource.setDefaultEncoding("UTF-8");
// messageSource.setBasename("messages");
// return messageSource;
// }

@Bean
public ResourceBundleMessageSource messageSource() {
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
messageSource.setDefaultEncoding("UTF-8");
messageSource.setBasename("messages");
return messageSource;
public MessageSource messageSource() {
return new ResourceBundleMessageSource() {
@Override
protected MessageFormat resolveCode(String code, Locale locale) {
return null; // Disable message resolution
}
};
}

@Bean
Expand All @@ -109,21 +127,23 @@ public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
entityManagerFactory.setDataSource(dataSource);
entityManagerFactory.setPackagesToScan("fi.vm.sade.eperusteet.domain");
entityManagerFactory.setPersistenceProviderClass(HibernatePersistenceProvider.class);
entityManagerFactory.setEntityManagerInterface(HibernateEntityManager.class);
entityManagerFactory.setEntityManagerInterface(EntityManager.class);
Map<String, Object> props = new HashMap<>();
props.put("hibernate.hbm2ddl.auto", "validate");
props.put("hibernate.show_sql", false);
props.put("hibernate.dialect", "fi.vm.sade.eperusteet.utils.repository.dialect.CustomPostgreSqlDialect");
props.put("javax.persistence.sharedCache.mode", "ENABLE_SELECTIVE");
props.put("hibernate.dialect", "org.hibernate.dialect.PostgreSQLDialect");
props.put("jakarta.persistence.sharedCache.mode", "ENABLE_SELECTIVE");
props.put("org.hibernate.envers.audit_strategy", "org.hibernate.envers.strategy.internal.DefaultAuditStrategy");
props.put("javax.persistence.validation.factory", validator());
// props.put("jakarta.persistence.validation.factory", validator());
// props.put(AvailableSettings.JAKARTA_VALIDATION_FACTORY, validatorFactory);
props.put("org.hibernate.envers.revision_listener", "fi.vm.sade.eperusteet.service.impl.AuditRevisionListener");
props.put("hibernate.jdbc.batch_size", 20);
props.put("hibernate.jdbc.fetch_size", 20);
props.put("hibernate.ejb.interceptor", hibernateInterceptor());
props.put(AvailableSettings.ID_DB_STRUCTURE_NAMING_STRATEGY, "legacy");
// props.put("hibernate.ejb.interceptor", hibernateInterceptor());
props.put("hibernate.id.new_generator_mappings", false);
entityManagerFactory.setJpaPropertyMap(props);
entityManagerFactory.setMappingResources("hibernate-typedefs.hbm.xml");
// entityManagerFactory.setMappingResources("hibernate-typedefs.hbm.xml");
return entityManagerFactory;
}

Expand All @@ -132,4 +152,9 @@ public JpaTransactionManager transactionManager() {
return new JpaTransactionManager(entityManagerFactory().getObject());
}

@Bean
public HandlerMappingIntrospector mvcHandlerMappingIntrospector() {
return new HandlerMappingIntrospector();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,11 @@
import org.springframework.core.NestedRuntimeException;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.HttpStatusCode;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.lang.Nullable;
import org.springframework.transaction.TransactionSystemException;
import org.springframework.validation.BindException;
import org.springframework.web.HttpMediaTypeNotAcceptableException;
Expand All @@ -38,12 +40,12 @@
import org.springframework.web.multipart.support.MissingServletRequestPartException;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;

import javax.persistence.PersistenceException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.ValidationException;
import jakarta.persistence.PersistenceException;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.ConstraintViolationException;
import jakarta.validation.ValidationException;
import java.io.IOException;
import java.security.Principal;
import java.util.ArrayList;
Expand Down Expand Up @@ -71,8 +73,7 @@ public ResponseEntity<Object> handleTransactionExceptions(TransactionSystemExcep
}

@Override
protected ResponseEntity<Object> handleHttpMessageNotReadable(HttpMessageNotReadableException ex, HttpHeaders headers, HttpStatus status,
WebRequest request) {
protected ResponseEntity<Object> handleHttpMessageNotReadable(HttpMessageNotReadableException ex, HttpHeaders headers, HttpStatusCode status, WebRequest request) {
if (ex.getRootCause() != null && ex.getRootCause() instanceof UnrecognizedPropertyException) {
return handleExceptionInternal((UnrecognizedPropertyException) ex.getRootCause(), null, headers, status, request);
} else {
Expand Down Expand Up @@ -123,7 +124,7 @@ private void describe(Map<String, Object> map, String koodi, String selkokieline
}

@Override
protected ResponseEntity<Object> handleExceptionInternal(Exception ex, Object body, HttpHeaders headers, HttpStatus status, WebRequest request) {
protected ResponseEntity<Object> handleExceptionInternal(Exception ex, @Nullable Object body, HttpHeaders headers, HttpStatusCode status, WebRequest request) {
final Map<String, Object> map = new HashMap<>();
boolean suppresstrace = false;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import javax.persistence.EntityManagerFactory;
import jakarta.persistence.EntityManagerFactory;
import java.util.List;

@Configuration
Expand All @@ -35,7 +35,7 @@ public void configurePathMatch(PathMatchConfigurer matcher) {
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/ui/").setViewName("forward:/ui/index.html");
registry.addRedirectViewController("/ui", "/ui/");
registry.addRedirectViewController("/swagger", "/swagger/index.html");
// registry.addRedirectViewController("/swagger", "/swagger-ui/index.html");
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,58 +1,78 @@
package fi.vm.sade.eperusteet.config;

import com.fasterxml.classmate.GenericType;
import com.fasterxml.classmate.TypeResolver;
import com.fasterxml.jackson.databind.JsonNode;
import com.google.common.base.Predicate;
import com.fasterxml.jackson.databind.type.SimpleType;
import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.info.License;
import io.swagger.v3.oas.models.media.Schema;
import org.springdoc.core.customizers.OpenApiCustomiser;
import org.springdoc.core.customizers.PropertyCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.http.ResponseEntity;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.schema.AlternateTypeRules;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import org.springframework.core.ResolvableType;

import java.util.ArrayList;
import java.util.Optional;
import java.util.concurrent.Callable;

import static com.google.common.base.Predicates.not;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.Map;
import java.util.stream.Collectors;

@Configuration
@EnableSwagger2
//@EnableSwagger2
@Profile("!test")
public class SwaggerConfig {

// @Bean
// public Docket api(TypeResolver typeResolver) {
// return new Docket(DocumentationType.SWAGGER_2)
// .apiInfo(apiInfo())
// .directModelSubstitute(JsonNode.class, Object.class)
// .genericModelSubstitutes(ResponseEntity.class, Optional.class)
// .forCodeGeneration(true)
// .select()
// .apis(not(RequestHandlerSelectors.withClassAnnotation(InternalApi.class)))
// .build()
// .alternateTypeRules(
// AlternateTypeRules.newRule(
// typeResolver.resolve(new GenericType<Callable<ResponseEntity<Object>>>() {
// }),
// typeResolver.resolve(Object.class)));
// }

// private ApiInfo apiInfo() {
// return new ApiInfo(
// "ePerusteet rajapinta",
// "",
// "Spring MVC API based on the swagger 2.0 and 1.2 specification",
// null,
// null,
// "EUPL 1.1",
// "http://ec.europa.eu/idabc/eupl",
// new ArrayList<>());
// }

@Bean
public Docket api(TypeResolver typeResolver) {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.directModelSubstitute(JsonNode.class, Object.class)
.genericModelSubstitutes(ResponseEntity.class, Optional.class)
.forCodeGeneration(true)
.select()
.apis(not(RequestHandlerSelectors.withClassAnnotation(InternalApi.class)))
.build()
.alternateTypeRules(
AlternateTypeRules.newRule(
typeResolver.resolve(new GenericType<Callable<ResponseEntity<Object>>>() {
}),
typeResolver.resolve(Object.class)));
public OpenAPI springShopOpenAPI() {
return new OpenAPI()
.info(new Info()
.title("ePerusteet rajapinta")
.description("Spring MVC API based on the swagger 3.0 specification")
.version("v3.0.0")
.license(new License().name("EUPL 1.1").url("https://interoperable-europe.ec.europa.eu/licence/european-union-public-licence-version-11-or-later-eupl")));
}

private ApiInfo apiInfo() {
return new ApiInfo(
"ePerusteet rajapinta",
"",
"Spring MVC API based on the swagger 2.0 and 1.2 specification",
null,
null,
"EUPL 1.1",
"http://ec.europa.eu/idabc/eupl",
new ArrayList<>());
@Bean
public PropertyCustomizer enumPropertyCustomizer() {
return (schema, type) -> {
Type javaType = type.getType();
if (javaType instanceof SimpleType && ((SimpleType) javaType).isEnumType()) {
Class<?> enumClass = ((SimpleType)javaType).getRawClass();
schema.setEnum(Arrays.stream(enumClass.getEnumConstants())
.map(enumConstant -> ((Enum<?>) enumConstant).name())
.collect(Collectors.toList()));
}
return schema;
};
}
}
Loading
Loading