Problems in migrating from swagger_jaxrs_2.10 to latest swagger_jaxrs - java

I had swagger_jaxrs_2.10 (1.3.6) working for a long time, I want to benefit from the new 2.0 swagger specification.
Hence I've changed in my pom from
<dependency>
<groupId>com.wordnik</groupId>
<artifactId>swagger-jaxrs_2.10</artifactId>
<version>1.3.6</version>
</dependency>
to
<groupId>io.swagger</groupId>
<artifactId>swagger-jaxrs</artifactId>
<version>1.5.3</version>
</dependency>
When I run, I get the following error trying to access myApp/swagger.json
SEVERE: Conflicting URI templates. The URI template / for root resource class io.swagger.jaxrs.listing.ApiListingResource and the URI template / transform to the same regular expression (/.*)?
Any ideas?

In the case of swagger from the 1.5.x libraries, the swagger description will live at /swagger.json. It depends on where your app is mounted though.
The error message your describing tells me that you're mounting a root resource (/*) which is indeed going to conflict with the /swagger.json. Consider mounting your API on a path like /users or something else to avoid that conflict.

Related

How to change the Swagger UI path for a Spring Boot app using Sprinfgox?

I need to remove the "/swagger-ui" part from the Swagger UI URL. So far I have seen examples of how to add a prefix prior to the "/swagger-ui" such as "/prefix/swagger-ui" but I want to remove it completely and just have the prefix.
localhost:8080/swagger-ui -> localhost:8080/test
I have tried adding the following two to the .properties file but had no luck:
springdoc.swagger-ui.path=/test
springfox.documentation.swagger-ui.base-url=test
-spring-boot version: 2.5.6
I am using the below dependency for Springfox:
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>3.0.0</version>
</dependency>
I am wondering if there is any other way.

JSP is downloading instead of rendering

My application was first downloading the jsp file instead of rendering it on page. I was getting a 200 status code in console but 404 on the page. I looked around and found I was suppose to add the dependencies for tomcat-jasper and tomcat-embed but now am getting a class cast exception saying that jspservlet can’t be cast to javax servlet. Any help appreciated. Thanks!
Getting an ApplicationContextException:
Caused by: javax.servlet.ServletException: Class [org.apache.jasper.servlet.JspServlet] is not a Servlet
at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1054) ~[tomcat-embed-core-9.0.48.jar:9.0.48]
at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:989) ~[tomcat-embed-core-9.0.48.jar:9.0.48]
at org.springframework.boot.web.embedded.tomcat.TomcatEmbeddedContext.load(TomcatEmbeddedContext.java:82) ~[spring-boot-2.5.2.jar:2.5.2]
... 32 common frames omitted
Caused by: java.lang.ClassCastException: org.apache.jasper.servlet.JspServlet cannot be cast to javax.servlet.Servlet
at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1049) ~[tomcat-embed-core-9.0.48.jar:9.0.48]
... 34 common frames omitted
This happens when I have this in my pom:
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-jasper</artifactId>
<version>10.1.0-M2</version>
<scope>runtime</scope>
</dependency>
When this is taken out of my pom everything works fine, hits the controller and returns the ModelAndView but downloads the jsp instead of actually displaying the page.
TL;DR: Use
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
There are a couple of problems with the dependency you added:
You should use tomcat-embed-jasper instead of tomcat-jasper: it depends on tomcat-embed-core (which is already used by Spring Boot) instead of tomcat-catalina (which is not used by Spring Boot). Including the latter causes problems like in this question.
Jasper 10.1 implements JSP 3.0, which is not compatible with Servlet 4.0 provided by Tomcat 9.0 (cf. this question). Since spring-boot-parent manages these dependencies, you should omit the <version> tag and use the version chosen by Spring Boot (9.0.48 for the version you are using, but it will keep in sync, when you update Spring Boot),
If you deploy your application as WAR file in an external servlet container, you want to use the version of JSP engine provided by the servlet container, instead of your own. Therefore you should set the scope to provided.

javax.servlet.ServletContext is being loaded from multiple dependencies in springboot application

So I have this springboot application which I'm migrating from a WAS to a springboot setup. And I have a couple of JSPs which has to be configured. To accomodate these I added the following dependencies:
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<version>9.0.22</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<scope>provided</scope>
</dependency>
The application already came with the following dependency which is being used throughout the application:
<dependency>
<groupId>com.ibm</groupId>
<artifactId>com.ibm-jaxrpc-client</artifactId>
<version>6.0</version>
</dependency>
The issue I'm facing is that both these dependencies (jaxrpc-client and tomcat-embed-jasper) have javax.servlet.ServletContext classes in them which is causing the following error:
The method's class, javax.servlet.ServletContext, is available from the following locations:
jar:file:/C:/Users/.m2/repository/com/ibm/com.ibm-jaxrpc-client/6.0/com.ibm-jaxrpc-client-6.0.jar!/javax/servlet/ServletContext.class
jar:file:/C:/Users/.m2/repository/org/apache/tomcat/embed/tomcat-embed-core/9.0.30/tomcat-embed-core-9.0.30.jar!/javax/servlet/ServletContext.class
It was loaded from the following location:
file:/C:/Users/.m2/repository/com/ibm/com.ibm-jaxrpc-client/6.0/com.ibm-jaxrpc-client-6.0.jar
Action:
Correct the classpath of your application so that it contains a single, compatible version of javax.servlet.ServletContext
I can't afford to remove any of these dependencies. jaxrpc-client is being referenced in the code already in too many places and I need tomcat-embed-jasper to render my jsp pages. I can't exclude the ServletContext class since its not a dependency(If I'm not wrong about the concept of exclusion). Please help with with a way forward with this issue.
I'm not familiar with IBM's jaxrpc client, but I assume, you have this exception in runtime, when trying to load the application.
In this case consider the following approaches:
Use another jax-rpc client library
Consider Loading the code that uses this library with the different class-loader (you'll have to create one classloader for this) to avoid the clash
Kind of paraphrasing the second option. You can "play" (override the order of loading of specific classes) with spring boot classloader as described in this article
I know, this is too general answer, but hopefully its still helpful.
The first solution is by far the easiest way I can think of.
The second solution is doable, however it pretty much depends on how exactly the code that uses the jax rpc client is loaded and used.

Spymemcached conflict with hibernate-memcached and webapp-runner

I've got a Heroku Java app that makes use of the Spymemcached library, which in my case is included by my use of the hibernate-memcached library (1.3).
I now need to make sure that all requests to my app go over HTTPS. This led me to this post, where the solution pivots on making use of the webapp-runner plugin and some config to get the right headers to my app (you provide the runner a context.xml).
My problem is that the webapp-runner plugin has a dependency (further down the dependency graph) on the Spymemcached library as well, which causes a conflict on start up. Furthermore, I can't downgrade webapp-runner to 7.0.22.1 as suggested by this post, as the support for specifying the context.xml came after the fact.
So I thought it would be a simple matter of excluding Spymemcached from my hibernate-memcached dependency so that only the webapp-runner's Spymemcached source would be included:
<dependency>
<groupId>com.googlecode</groupId>
<artifactId>hibernate-memcached</artifactId>
<version>1.3</version>
<exclusions>
<exclusion>
<artifactId>hibernate</artifactId>
<groupId>org.hibernate</groupId>
</exclusion>
<exclusion>
<groupId>spy</groupId>
<artifactId>spymemcached</artifactId>
</exclusion>
</exclusions>
</dependency>
But for some reason I still get the conflict on start up - on the factory bean that creates my memcachedClient which I specify in my application context:
<bean id="memcachedClient" class="net.spy.memcached.spring.MemcachedClientFactoryBean">...</bean>
Resulting in the infamous java.lang.NoClassDefFoundError:
Error loading class [net.spy.memcached.spring.MemcachedClientFactoryBean] for bean with name 'memcachedClient' defined in file [/home/markus/coding/reader/target/tomcat.8080/work/Tomcat/localhost/_/WEB-INF/classes/META-INF/spring/applicationContext.xml]: problem with class file or dependent class; nested exception is java.lang.NoClassDefFoundError: org/springframework/beans/factory/FactoryBean
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:328)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:106)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveManagedList(BeanDefinitionValueResolver.java:353)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:153)...
When I search for the MemcachedClientFactoryBean in my IDE I can see that it's made available by the webapp-runner and not hibernate-memcached, so the exclusion seemed to have done something right.
Am I missing something obvious here? How do I get rid of this NoClassDefFoundError?
FYI I found out that version 7.0.22 of webapp-runner does indeed have support for providing it a context.xml by running java -jar target/webapp-runner.jar --help
It differs slightly to the later versions where you specify ... --context_xml ... instead of ... --context-xml ...
Version 7.0.22 of webapp-runner doesn't have Spymemcached as a dependency, which solves the problem.

WebSphere MQ Configuration issues

getting below error after i configure MQ connection factory.
java.lang.ClassCastException: com.ibm.ejs.jms.JMSQueueConnectionFactoryHandle incompatible with com.ibm.mq.jms.MQQueueConnectionFactory
my code snippet where the exception is pointing to :
String queueConnectionJndi = props.getProperty(queueConnection + MQ_CONN);
queueConnectionFactory = MQQueueConnectionFactory)initialContext.lookup(queueConnectionJndi);
I am not able to find out the root cause of this.
can any body please help me on this, Thanks in advance.
There is no way to be sure without more context, but it looks like this method call:
initialContext.lookup(queueConnectionJndi);
is returning an object of type com.ibm.ejs.jms.JMSQueueConnectionFactoryHandle which cannot be cast to com.ibm.mq.jms.MQQueueConnectionFactory.
Can you provide more context?
This Post on old nabble sounds like a similar issue and may help you out.
Specifically the final response talks about removing any jms.jar file(s) that may be in your deployed WAR. Check your WEB-INF/lib. Certain jars are provided by the Websphre container and shouldn't be including them in your WAR.
This Post on the spring fourm also indicates issues of this nature caused by jars included in the classpath that shouldn't be there
Remove any of the following if you find them...
naming.jar
providerutil.jar
jndi.jar
jms.jar
mq.jar
websphere.jar
Can you rewrite your code to use JMS standard (ConnectionFactory or QueueConnectionFactory)instead of a Websphere MQ specific implementation class? That way you won't be tying your app to Websphere MQ and porting it to an alternative MQ implementation would be easier...
i.e.
import javax.jms.QueueConnectionFactory;
...
queueConnectionFactory = (QueueConnectionFactory)initialContext.lookup(jndiName);
the MQ jars which WAS is using and my application using are different so this problem occured. when i corrected the classpath it is resolved. sorry for the trouble, thanks for the help.
I went through a lot of trial and error to find the answer (the answer to my question at least). I hope this solution will solve your issues too. As mentioned from another post excluding the jms library works. But how do you exclude the jms library and still be able to compile the code? That was something no one seems to have mentioned. The solution to that is to make the scope for the jms library to "provided" (if you are using Maven or Gradle).
As mentioned somewhere:
"Provided means that you need the JAR for compiling, but at run time there is already a JAR provided by the environment so you don't need it packaged with your app. For a web app, this means that the JAR file will not be placed into the WEB-INF/lib directory."
So in your pom.xml add/update these:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
<version>4.3.4.RELEASE</version>
<exclusions>
<exclusion>
<groupId>javax.jms</groupId>
<artifactId>javax.jms-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>javax.jms</groupId>
<artifactId>jms</artifactId>
<version>1.1</version>
<scope>provided</scope>
</dependency>
Hopefully this can be helpful to those who have been frustrated by the lack of answers from the Internet.
Remove all the ibm libraries. They are useless. Once you deploy onto Websphere, it will use its libraries anyways.

Categories