How to make OpenApi UI work in Payara Micro - maven

I have followed this tutorial Swagger UI on MicroProfile OpenAPI but simply adding the below to a pom.xml file of a Payara micro application does not add /openapi-ui, only /openapi works. Is there something else that is required or is it not possible with Payara Micro to have OpenApi UI.
<dependency>
<groupId>org.microprofile-ext.openapi-ext</groupId>
<artifactId>openapi-ui</artifactId>
<version>1.1.2</version>
</dependency>

My problem was the Application config class. I had to change
from:
#ApplicationPath("/api/v1")
public class JAXRSConfiguration extends Application {
public Set<Class<?>> getClasses() {
Set<Class<?>> s = new HashSet<>();
s.add(MyResource.class);
return s;
}
}
to
#ApplicationPath("/api")
public class JAXRSConfiguration extends Application {
}
Somehow overriding the getClasses() method and adding /v1 to the application path was messing with the openApi-ui configurations.

Related

Application failed to start after spring boot version upgrade from 2.1.18.RELEASE to 2.2.0.RELEASE

When we upgrade the spring-boot-starter-parent version from 2.1.8.RELEASE to 2.2.0.RELEASE, the application is not loading few beans. Due to this, application is failing. #PostConstuct is not able to add BCFIPS Provider in security provider.
#Configuration
#Slf4j
#ComponentScan(basePackages = "com.xxx.yyy.ekms.sdk")
#ConditionalOnProperty(name = "ekms.enabled", havingValue = "true")
public class EKMSClientSdkConfiguration extends ClientConfiguration
{
#PostConstruct
public void addSecurityProvider()
{
Security.addProvider(new BouncyCastleFipsProvider());
}
#Bean
public ApiClientBuilder apiClientBuilder()
{
return new DefaultApiClientBuilder();
}
}
Also, apiClientBuilder bean is not getting created.
The EKMSClientSdkConfiguration is extending ClientConfiguration, which is coming as part of another application jar. This class is not having any annotation.
public abstract class ClientConfiguration {
public ClientConfiguration()
{
}
public abstract void addSecurityProvider();
#Bean
public EKMSClient restClient() {
return new EKMSRestClientImpl(this.apiClient());
}
#Bean
public ApiClient apiClient() {
return Configuration.getDefaultApiClient();
}
}
In our case, EKMSClientSdkConfiguration bean is not getting created and the #PostConstruct is also not getting executed.
I went through the Spring Boot 2.2.RELEASE notes which is pointing to Spring Framework 5.2 upgrade guide. Here, I learned that spring boot 2.2.0 RELEASE is using Spring framework 5.2. In Spring framework 5.2, we have many changes.
It looks like this is the root cause of bean not getting loaded, but I am not sure about it.
Any help will be appreciated. Let me know if additional information is needed.
I found spring.main.lazy-initialization=true property in my application which was causing the above issue. When I removed it from the application.properties, This issue is resolved. This is the major change which was introduced in 2.2.0.RELEASE of spring boot

How to correctly handle "FeignException$ServiceUnavailableException" with fallback and without deprecated #EnableCircuitbreaker annotation

When using OpenFeign I implement fallbacks returning empty results so lists should simply appear as being empty. E.g. such as
#FeignClient(name = "objects", fallback = ObjectsClientFallback.class)
public interface ObjectsClient {
#RequestMapping("/objects/count")
Long count();
}
and
#Component
public class ObjectsClientFallback implements ObjectsClient {
#Override
public Long count() {
return 0L;
}
}
However, if the service is not started the application produces the ServiceUnavailableException when calling objectsClient.count() instead of using the fallback.
What is the correct way to use the fallback as #EnableCircuitBreaker has been deprecated recently? I do not want to add try-catch blocks if possible, especially in the context of lambdas or wrap this in service methods.
The application uses the #EnableDiscoveryClient annotation, like so
#SpringBootApplication
#EnableJpaRepositories
#EnableFeignClients
#EnableDiscoveryClient
#ServletComponentScan
public class Application {
//..
}
I've seen this question and checked the mentioned documentation, but it didn't help. Library versions are Spring-Boot 2.6.2 and Spring-Cloud 2021.0.0
Ended up using resilience4j for spring cloud.
Next to feign.circuitbreaker.enabled=true in application.properties which sets up a circuitbreaker with a default config.
One can add a custom configuration like this:
#Configuration
public class FeignConfiguration {
#Bean
public Customizer<Resilience4JCircuitBreakerFactory> circuitBreakerFactoryCustomizer() {
CircuitBreakerConfig circuitBreakerConfig =
CircuitBreakerConfig.custom()
.ignoreException(FeignException.ServiceUnavailable.class::isInstance)
.build();
return circuitBreakerFactory -> circuitBreakerFactory
.configure(builder -> builder.circuitBreakerConfig(circuitBreakerConfig),
ObjectsClient.class.getSimpleName());
}
}
Also, the resilience4j dependency needs to be in place, here a maven pom.xml is used.
<project>
<!-- .. -->
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-circuitbreaker-resilience4j</artifactId>
</dependency>
</dependencies>
That way you can replace the deprecated hystrix implementation and remove the #EnableCircuitBreaker annotation.
In case you want a more fine-grained setup, here are is a discussion how to implement fallback with resilience4j via default methods.

Spring Boot AOP in multi module project does not execute Before Advice

I'm doing my fist steps with Springs AOP and wanted to start with a simple logging advice. My project is a multi module maven project with the following structure:
parentProject
|__aop
|__data
|__web
The web module has a user service class in the package de.my.awsome.project.web.service with a saveNewUser Method:
#Service
public class UserService {
...
public MdUser saveNewUser(UserModel user) {
MdUser newUser = this.save(user);
createGroupMembership(user, newUser);
return newUser;
}
}
The method works as expected so don't bother with details about that.
What I've done now is to create the following class in the aop module:
#Component
#Aspect
public class LoggingAspect {
Logger logger = Logger.getLogger(getClass());
#Before("execution(public * de.my.awsome.project.web.service.UserService.saveNewUser(..))")
public void newUserLog(JoinPoint joinpoint) {
logger.info(joinpoint.getSignature() + " with user " + joinpoint.getArgs()[0]);
}
}
I added a dependency for the web module in the pom of the aop module:
<dependency>
<groupId>de.my.awsome.project</groupId>
<artifactId>web</artifactId>
<version>${project.version}</version>
</dependency>
I even wrote a ConfigurationClasse even though I thought this would not be necessary with SpringBoot:
#Configuration
#ComponentScan(basePackages="de.fraport.bvd.mobisl.aop")
public class AspectsConfig {
}
The expected result is a log-message like "saveNewUser with user xyz". But the logging method is never called. What have I missed to do?
#Configuration - Indicates that this file contains Spring Bean Configuration for an Aspect.
Replace #Component with #Configuration for LoggingAspect.
Well, the answer that #sankar posted didn't work either but I found the solution by myself.
I had to add a dependency to my aop module in the web modules pom, not vice versa. Then I added an Import of my AspectsConfig to the web modules SpringBootApplication class and it worked.
#SpringBootApplication
#Import(value= {JPAConfig.class, AspectsConfig.class})
#EnableAspectJAutoProxy
public class WebApplication {
#Autowired
private JPAConfig config;
#Autowired
private AspectsConfig aspectConfig;
public static void main(String[] args) {
SpringApplication.run(WebApplication.class, args);
}
}
The following steps work for me - see below if anyone is looking for a solution
add the aop dependency in to the main parent pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
add your Aspect implementation in he aop-sub-module
#Aspect
#Component
public class SampleAspect {
#After("execution(* de.my.awsome.project.testMethod())")
public void logAuditActivity(JoinPoint jp) {
System.out.println("TESTING ****************");
System.out.println("The method is called");
}
In your other submodule (web-submodule) add the dependancy of the aspect-submodule
<dependency>
<groupId>de.my.awsome.project</groupId>
<artifactId>aop</artifactId>
</dependency>
In your web Project include the aop package for component scan
eg. if SampleAspect is under a package de.my.awsome.project you will need to add in as follow
#ComponentScan(basePackages = {"de.my.awsome.project", "de.my.awsome.aop" }
clean build and run the app

Spring boot - executable war also deployable to app server

Let's say I have a spring boot web application - It is runnable via gradle (embedded tomcat).
But I need it also to be possible to deploy war in standard way into app server.
How the app should be configured? Standard web.xml along with xml configuration?
Currently I have something like:
#SpringBootApplication
public class MyApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
System.setProperty("spring.profiles.active", "dev");
SpringApplication.run(MyApplication.class, args);
}
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(MyApplication.class);
}
#Configuration
#ConditionalOnWebApplication
public static class WebConfiguration {
#Bean
public ServletListenerRegistrationBean<ServletContextListener> registerClientCookieConfigListener () {
ServletListenerRegistrationBean<ServletContextListener> srb =
new ServletListenerRegistrationBean<>();
srb.setListener(new MyConfigListener());
return srb;
}
#Bean
public ServletListenerRegistrationBean<HttpSessionListener> registerMySessionConfigListener () {
ServletListenerRegistrationBean<HttpSessionListener> srb =
new ServletListenerRegistrationBean<>();
srb.setListener(new MySessionConfigListener());
return srb;
}
#Bean
public FilterRegistrationBean registerLoginFilter() {
FilterRegistrationBean filter = new FilterRegistrationBean(new MyFilter());
filter.setUrlPatterns(Collections.singletonList("/*"));
return filter;
}
#Bean
public ServletRegistrationBean registerSAMLDispatcherServlet() {
ServletRegistrationBean bean = new ServletRegistrationBean(
new DispatcherServlet(), "/test/*");
bean.setLoadOnStartup(1);
return bean;
}
}
}
which is 1:1 mapping to web.xml.
Is it even possible to deploy it to app server without web.xml?
You don't need web.xml to deploy spring boot to standalone tomcat server or any other web server.
spring boot does not rely on xml configurations, it configures an equivalent to the dispatcher servlet automatically.
to deploy a spring boot app to an another server, you need to update your packaging to war in maven
<packaging>war</packaging>
and tell maven that a webserver will be available in the runtime and don't package it with scope provided
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
few documentations
https://www.baeldung.com/spring-boot-war-tomcat-deploy
https://www.mkyong.com/spring-boot/spring-boot-deploy-war-file-to-tomcat/

Spring MVC Neo4jConfiguration class not found

I am learning Spring MVC. I want to extend the Neo4jConfiguration class but it is not available. I imported the following dependency:
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-neo4j</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
and after that I have reimported the libraries from maven. As I know I should now be able to extend the Neo4jConfiguration class. What is the problem? Thank you!
Neo4jConfiguration has been dropped from Spring Data Neo4j 4.2.
You can refer to the 'Configuring a Simple Spring Application' and 'Configuring Web Applications' in the Upgrading to Spring Data Neo4j 4.2 for a quick configuration without it.
The code sample they provide for simple configuration is:
#Configuration
#EnableNeo4jRepositories(basePackages = "org.neo4j.example.repository")
#EnableTransactionManagement
public class MyNeo4jConfiguration {
#Bean
public SessionFactory sessionFactory() {
// with domain entity base package(s)
return new SessionFactory("org.neo4j.example.domain");
}
#Bean
public Neo4jTransactionManager transactionManager() {
return new Neo4jTransactionManager(sessionFactory());
}
}

Resources