swagger.json endpoint throwing "404 Not Found" on WAS Server - websphere

I am using Jersey 2.x and integrated Swagger into my application.
API Doc for Swagger Integration with Jersey : Swagger-Core-Jersey-2.X-Project-Setup
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-jersey2-jaxrs</artifactId>
<version>1.5.0</version>
</dependency>
Running on Local Machine + Tomcat :
Swagger Endpoint running fine on my local machine if deployed on Tomcat. Please have a look on the screenshot below:
Running on WebSphere (WAS):
If I deploy the same war file on WAS, I am getting 404 Not Found error for GET swagger.json endpoint.
However other CRUD operation APIs are working perfectly fine. I also able to see LOG statement printed in Bootstrap class which means swagger intilized but endpoint is not working as expected.
Below is my Bootstrap class which I have initialized in web.xml
public class Bootstrap extends HttpServlet {
private static Logger LOGGER = LogManager.getLogger(Bootstrap.class);
#Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
System.out.println("Inside Bootstrap........");
BeanConfig beanConfig = new BeanConfig();
beanConfig.setTitle("Rest APIs Documentation");
beanConfig.setContact("you#your-company.com");
beanConfig.setVersion("1.0.0");
beanConfig.setSchemes(new String[]{"http"});
//beanConfig.setHost("localhost:9060");
//beanConfig.setBasePath("/mdm-swagger/api");
beanConfig.setResourcePackage("com.api.rs");
beanConfig.setPrettyPrint(true);
beanConfig.setScan(true);
LOGGER.info("Inside Bootstrap finish........");
}
}
I have commented host and basepath as I want to use swagger for documentation purpose not like any client.
Could you please suggest possible solution why I am getting 404 Not Found error?
Thanks a lot.

Related

springboot swagger3 "Failed to load remote configuration."

Spring Boot 2.6.3 with Springdoc.
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>
<version>1.6.5</version>
</dependency>
In applicaton.yaml, when I set the path as /v3/api-docs or remove it, that means use the default path "/v3/api-docs".
The Swagger UI page shows up correctly with the APIs
http://localhost:8080/swagger-ui/index.html
But I want to overite the path as below
api-docs.path: /bus/v3/api-docs
then Swagger UI displays the "Failed to load remote configuration" error:
Make sure to add "/v3/api-docs/**" in configure method.
#Configuration
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/swagger-ui/**", "
/v3/api-docs/**");
}
}
If you are using Spring Security in your app, you must include the URL in the configs.
Add the code below please to your project.
#Configuration
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/swagger-ui/**", "/bus/v3/api-docs/**");
}
}
I had the same problem, If you are behind a reverse proxy, the fix was to add the following property in application.yml
server:
forward-headers-strategy: framework
this is needed due to the following
Swagger relies on internal routing to make requests from the clients perspective. Putting the service behind a reverse-proxy without providing the X-Forwarded headers will result in the user not being able to use the documentation as intended
source -> https://medium.com/swlh/swagger-spring-boot-2-with-a-reverse-proxy-in-docker-8a8795aa3da4
Perform "Empty cache and hard refresh" in your browser.
I think I have solved the problem (thanks to #Ivan Zaitsev), just wanted to add more clarification to the answer.
I too have changed the api-docs.path property and I had the same problem. When I inspect the requests on swagger UI page, swagger-config request returns 404 since it was still trying to get the config from the old URL.
Even though I have changed api-docs.path property, here is the request URL that tries to retrieve swagger-config.
http://localhost:8080/api/v3/api-docs/swagger-config
It turned out to be a problem related to openapi-ui, because I was able to solve it when I cleared the browser cache and cookies. It is better do to the tests with incognito browser since it does not hold any data on the session.
If you are using SpringBoot v3, you must use springdoc-openapi v2:
https://springdoc.org/v2/
With gradle, for example:
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.0.2'

I am not able to connect to Google Cloud Memory Store from Spring Boot

I am developing a module with spring boot in my backend where i need to use Redis through GCP Memory Store. I have been searching in forum and even the "oficial documentation" about memory store but i cannot understand how to connect to memory store with my spring boot app.
I found a google code lab but they use a Compute Engine VM to install spring boot and then save and retrieve information from memory store. So i tried to do it like that in my local spring boot but it didnt work because throws an error saying:
Unable to connect to Redis; nested exception is io.lettuce.core.RedisConnectionException: Unable to connect to 10.1.3.4
the codelab i mentioned earlier says that you only have to add this line to your application.properties:
spring.redis.host=10.1.3.4
as well as the annotation #EnableCaching in the main class and #Cachable annotation in the controller method where you try to do something with redis.
the method looks like this:
#RequestMapping("/hello/{name}")
#Cacheable("hello")
public String hello(#PathVariable String name) throws InterruptedException {
Thread.sleep(5000);
return "Hello " + name;
}
i dont know what else to do. Notice that i am new on this topic of redis and memory store.
Anyone can give me some guidance on this please?
thanks in advance
codelab url: https://codelabs.developers.google.com/codelabs/cloud-spring-cache-memorystore#0
See this documentation on how to setup Memorystore Redis instance.
Included in the documentation is how you can connect and test your Memorystore instance from different computing environments.
There's also a step by step guide on how SpringBoot can use Redis to cache with annonations.
Add the Spring Data Redis starter in your pom.xml if you're using Maven for your project setup.
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
Add this configuration in your application.properties file:
spring.redis.host=<MEMORYSTORE_REDIS_IP>
# Configure default TTL, e.g., 10 minutes
spring.cache.redis.time-to-live=600000
Turn on caching capability explicitly with the #EnableCaching annotation:
#SpringBootApplication
#EnableCaching
class DemoApplication {
...
}
Once you configured the Spring Boot with Redis and enabled caching, you can use the #Cacheable annotation to cache return values.
#Service
class OrderService {
private final OrderRepository orderRepository;
public OrderService(OrderRepository orderRepository) {
this.orderRepository = orderRepository;
}
#Cacheable("order")
public Order getOrder(Long id) {
orderRepository.findById(id);
}
}

Spring Boot App as .war is running, but endpoint is not working

I built a Spring Boot Rest API and want it to run in a Tomcat container on a Linux server.
I have a server on digitalocean running on Ubuntu 20.4
I installed tomcat as described in this article and it is running
I build a very small Spring Boot Application with only one endpoint, which I want to build and deploy on the tomcat server. You can see the build.gradle file here in my github repository: spring-boot-example
Here are some Code Snippets:
#RestController
public class ExampleController {
#GetMapping(value = "/hello-world")
public ResponseEntity<String> helloWorld() {
return ResponseEntity.ok("Hello world");
}
}
#SpringBootApplication
public class ExampleApplication extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(ExampleApplication.class);
}
public static void main(String[] args) {
SpringApplication.run(ExampleApplication.class);
}
}
This is basically the whole app
Steps taken:
building the war file with './gradlew war' or './gradlew bootWar' locally on my machine (I tried both, i don't know if it makes any difference, but I had the issue with both of them)
Opening the tomcat manager remotely on http://'host':8080/manager/html
Deploying the .war file manually and waiting until it's deployed:
As you can see, it is up and running:
Now I open the following URL: http://host:8080/spring-boot-example/hello-world, where I expect to see the message Hello world, as defined in the Controller
But all I can see is this
Did I miss something? It says at the end or is not willing to disclose that one exists, do I have to do something with that endpoint to make it available to the public? Or did I upload the app incorrectly?

Unable to access spring-docs-open-ui swagger documentation

I am a spring newbie trying to configure swagger documentation for my spring boot application. I configured my application based on the documentation provided here
I am able to access the documentation page locally from this URL
http://localhost:8080/doc.html
However, when I deploy my application on Docker I keep getting a 404 status.
https://www.mywebsite.com/context_path/doc.html
My application.properties file looks like this -
springdoc.api-docs.path=/doc
springdoc.swagger-ui.path=/doc.html
I have also added a HomeController which redirects to the documentation page
#Controller
public class HomeController {
private static final Logger LOGGER = LoggerFactory.getLogger(HomeController.class);
#RequestMapping(value = "/")
public void redirect(HttpServletResponse response) throws IOException {
response.sendRedirect("/doc.html");
}
}
FYI, I am using Amazon Cognito. I have read and tried several examples that I found online but I cannot make this work. Can someone help me?
You are using only #Controller annotation;
If you are using REST APIs, you should use #RestController.
If you need to use #Controller, you should add #ResponseBody
If you don't want change your #Controller, you add:
static {
SpringDocUtils.getConfig().addRestControllers(HelloController.class);
}
More information are available on the documentation of F.A.Q:
https://springdoc.org/faq.html#my-rest-controller-using-controller-annotation-is-ignored

Spring Boot CSRF

Tried to implement CSRF protection on the latest Spring Boot.
All the examples on internet are based on user login and authentication, which I do not need.
My site does not have any sections requiring authentication.
I would like
1) Rest requests come from within site. No direct request from outside with wget to be allowed.
2) All pages (routes) must be requested from the index page (/)
Included the security dependency in pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
-- Defined users in application.properties (even though, I do not need)
-- App creates _csrf.token .
-- Created class extending WebSecurityConfigurerAdapter with "configure" method overriding.
Tried all suggested filters in "configure". It did not work and finally left it blank.
The problem is that Wget can get api pages directly.
How to prevent it?
I've quickly put together a POC of this configuration:
#Configuration
#EnableWebSecurity
#SpringBootApplication
public class StackoverflowQ40929943Application extends WebSecurityConfigurerAdapter{
public static void main(String[] args) {
SpringApplication.run(StackoverflowQ40929943Application.class, args);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/**").permitAll();
}
}
The gist of it is Spring Boot + Security will secure all endpoints automatically. Here we explicitly allow requests to all endpoints. But, Spring Boot + Security automatically configures CSRF out of the box which we've left enabled. Thus you get the best of both worlds.
NOTE: You'll probably need to refine this configuration further to meet your needs.
Full Example on GitHub

Resources