How to launch spring boot application with cloud-bus via custom auto-configuration? - spring

Some time ago I found out that my spring-boot application had been launching slowly via #EnableAutoConfiguration. Then I decided to create custom configuration to speed up a process. I tried to #Import all needed configurations and I faced with issue of unknown beans:
Description:
Parameter 0 of method streamBusBridge in org.springframework.cloud.bus.BusStreamAutoConfiguration required a bean of type 'org.springframework.cloud.stream.function.StreamBridge' that could not be found.
Action:
Consider defining a bean of type 'org.springframework.cloud.stream.function.StreamBridge' in your configuration.
It seems that I've already used all cloud-bus configurations:
PathServiceMatcherAutoConfiguration.class,
BindingsEndpointAutoConfiguration.class,
BusAutoConfiguration.class,
BindingServiceConfiguration.class,
BindersHealthIndicatorAutoConfiguration.class,
ChannelsEndpointAutoConfiguration.class,
BusRefreshAutoConfiguration.class,
FunctionConfiguration.class,
BusStreamAutoConfiguration.class,
BusJacksonAutoConfiguration.class
What should I add to launch my application via custom auto-configuration?
Spring-boot: v2.6.6
Spring-cloud-bus: v3.1.2
Java: 17

Related

Upgrading to Springboot 3: 'org.springframework.hateoas.server.LinkRelationProvider' that could not be found

I am upgrading my springboot app from 2.7.x to 3.0.0, I have made required changes for jakartaEE. When starting my app I am getting the below error
{"#timestamp":"2023-01-03T15:28:01.149Z","#version":"1","message":"\r\n\r\n***************************\r\nAPPLICATION
FAILED TO
START\r\n***************************\r\n\r\nDescription:\r\n\r\nParameter
1 of method collectionModelContentConverter in
org.springdoc.core.configuration.SpringDocHateoasConfiguration
required a bean of type
'org.springframework.hateoas.server.LinkRelationProvider' that could
not be found.\r\n\r\n\r\nAction:\r\n\r\nConsider defining a bean of
type 'org.springframework.hateoas.server.LinkRelationProvider' in your
configuration.\r\n","logger_name":"org.springframework.boot.diagnostics.LoggingFailureAnalysisReporter","thread_name":"main","level":"ERROR","level_value":40000}
I am using hateos lib for representation in my app, Also I am using springdoc-openapi-starter-webmvc-ui for swagger UI.
When I disable configuration for api-docs springdoc.api-docs.enabled=false the above error go away but my swagger page is also gone, which definitely means this is not the solution.
Could someone please guide me why this bean is not getting found with springboot 3 while it was all working before with springboot2.7.x and java-11.
here is my pom.xml https://gist.github.com/bruce2019/c93a16dc20f7edb7d922b1e284f39d15
Thanks in advance
You can use springdoc-openapi-starter-webmvc-ui with 2.0.2 version
Add "/v3/api-docs/**" to mvcMatchers in WebSecurityCustomizer

Spring MVC Jackson Exception on Payara 5 startup

My application is using the following:
JDK version: Open JDK jdk-11.0.11+9 Payara : 5.2021.5 Spring version: 5.2.7.RELEASE jackson version: 2.9.4.
Payara 5.2021.5 uses Jackson version 2.10.2, whereas the application uses Jackson version: 2.9.4. It looks like the method signature for some Jackson methods used by SpringMVC has changed in Jackson 2.10.2.
On Server startup, the following Exception is thrown:
Details: Location: org/springframework/http/converter/json/Jackson2ObjectMapperBuilder$XmlObjectMapperInitializer.create
(Lcom/fasterxml/jackson/core/JsonFactory;)Lcom/fasterxml/jackson/databind/ObjectMapper; #15: areturn Reason: Type 'com/fasterxml/jackson/dataformat/xml/XmlMapper' (current frame, stack[0]) is not assignable to 'com/fasterxml/jackson/databind/ObjectMapper' (from method signature)
I tried disabling class loading hierarchy locally by setting element in the glassfish-web.xml as well as globally, by setting system property fish.payara.classloading.delegate to false in domain.xml
I also tried adding the following to web.xml as suggested in documentation, as well as the init parameter to DispatcherServlet, but does not seem to help-
<context-param>
<param-name>jersey.config.jsonFeature</param-name>
<param-value>JacksonFeature</param-value>
</context-param>
tried disabling class loading hierarchy locally by setting element in the glassfish-web.xml. It looks like Payara ignores this flag and continues to load the libraries in \payara-5.2021.5\payara5\glassfish\modules, instead of loading from the application. I even tried by replacing glassfish-web.xml with payara-web.xml
The issue resolved by setting system property fish.payara.classloading.delegate to false in domain.xml.

Error finding bean when using Watson spring-boot-starter

I followed the steps in https://github.com/watson-developer-cloud/spring-boot-starter to try an call the Watson Conversation(Assistant) service in a Spring boot application, however I am getting this error:
*************************** APPLICATION FAILED TO START
Description:
Field service in application.ConverseApiBinding required a bean of
type 'com.ibm.watson.developer_cloud.conversation.v1.Conversation'
that could not be found.
Action:
Consider defining a bean of type
'com.ibm.watson.developer_cloud.conversation.v1.Conversation' in your
configuration.
Is there thing else I need to do apart from adding dependencies (I used maven) and
#Autowired
protected Conversation service;
The service url and credentials are provided in the VCAP_SERVICES environment variable.
You need to have something in your application properties file to signal that the conversation bean should be created. Normally this would be the service credentials.
In the case where the service credentials come from VCAP_SERVICES, you can simply specify
watson.conversation.enabled=true
in your application properties file. That should trigger the creation of the bean.

Websphere 8.5 with Spring-5

Is Websphere 8.5.5 compatible with Spring 5? The Validation API referenced in spring5 (validation-api 5) is resulting in MethodNotFound exception.. Any pointers/patch available to get this solved - short of upgrading to Websphere 9?
Caused by: java.lang.NoSuchMethodError:
javax/validation/Configuration.getDefaultParameterNameProvider()Ljavax/validation/ParameterNameProvider;
(loaded from
file:/opt/IBM/WebSphere/AppServer/plugins/javax.j2ee.validation.jar by
org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader#25d460de)
called from class
org.springframework.validation.beanvalidation.LocalValidatorFactoryBean
(loaded from file:../spring-context-5.0.2.RELEASE.jar by
com.ibm.ws.classloader.CompoundClassLoader#1c7dbdd9
The method javax/validation/Configuration.getDefaultParameterNameProvider was added in Bean Validation 1.1, so that indicates the Spring Validator you are using is attempting to use the Bean Validation 1.1 API. According to https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/validation/beanvalidation/LocalValidatorFactoryBean.html:
As of Spring 5.0, this class requires Bean Validation 1.1+
WebSphere 8.5.5 provides Bean Validation 1.0 and did not add support for Bean Validation 1.1 until version 9.0. So, you'll either need to use Spring 4.x or WebSphere 9.x.
The above answer is not correct. You can run Spring 5 in WebSphere 8.5. This may not be the perfect solution for your situation, but this will get you on the correct path.
1.) Provide your Bean Validation 1.1 JAR
Here is a sample of the Maven dependency.
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.1.0.Final</version>
</dependency>
2.) Add the following a deployment.xml file to the following location in your EAR file.
/myAppEAR/META-INF/ibmconfig/cells/defaultCell/applications/defaultApp/deployments/defaultApp/deployment.xml
3.) In the contents of your deployment.xml file, you must set the classloaderMode to PARENT_LAST. You must also modify this code to use the correct WAR file name.
Here is a sample...
<appdeployment:Deployment xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:appdeployment="http://www.ibm.com/websphere/appserver/schemas/5.0/appdeployment.xmi" xmi:id="Deployment_1422578178899">
<deployedObject xmi:type="appdeployment:ApplicationDeployment" xmi:id="ApplicationDeployment_1422578178899" startingWeight="10" warClassLoaderPolicy="SINGLE">
<modules xmi:type="appdeployment:WebModuleDeployment" xmi:id="WebModuleDeployment_1422578178899" startingWeight="10000" **uri="myApp.war"** **classloaderMode="PARENT_LAST"**/>
<classloader xmi:id="Classloader_1422578178899" **mode="PARENT_LAST"**/>
</classloader>
</deployedObject>
</appdeployment:Deployment>
#rob-breidecker is correct, this is possible even though WebSphere 8.5.5 provides Bean Validation 1.0. To do this, you need to change the classloader of your application.
To do that via the UI, go to Applications -> WebSphere enterprise applications -> Your Application -> Class loading and update detection and change the Class loader order to be Classes loaded with local class loader first (parent last). This "causes the class loader to attempt to load classes from its local class path before delegating the class loading to its parent.".
If you are deploying an EAR and want this change to propagate to inner applications, you can either change WAR class loader policy to Single class loader for application or change the class loader of the individual war (in the EAR click Manage Modules -> Your Module then change Class loader order).
As long as you provide a version of validation-api (I used 2.0.1.Final), you should get passed the above issue.
The following wasadmin.sh script will apply the above settings (replace app_name with the name of your application): (credit)
dep = AdminConfig.getid('/Deployment:app_name/');
depObject = AdminConfig.showAttribute(dep, 'deployedObject');
AdminConfig.modify(depObject, [['warClassLoaderPolicy', 'SINGLE']]);
classldr = AdminConfig.showAttribute(depObject, 'classloader');
AdminConfig.modify(classldr, [['mode', 'PARENT_LAST']]);
I though at some point it was impossible to do this, but finally, I found a solution, you can use spring 5.X and Boot 2.X with WebShpre 8.5 using the below Steps, just make sure that you project is compatible with:
1- Bean Validation
2- Servelt 3.1
Steps:
1- Create a custom folder on you server for example /opt/custom/lib/spring5 and upload below jars to this folder
a. jakarta.el-3.0.4.jar
b. jakarta.validation-api-2.0.2.jar
2- Create a new shared library in WebSphere as below
a. Go to environment -> shared library
b. Chose the scope to node and server
c. Click on New and fill the value with below
i. Name: spring5
ii. Class path: /opt/custom/lib/spring5
iii. Enable checkbox “use an isolated class loader for this shared library”
3- Restart the server
4- Go to Enterprise Application Click on the application (WAR/EAR)
5- Go To shared library reference add assign it to you application (WAR/EAR)
6- Go to Enterprise Application Click on the application (WAR/EAR)
7- Choose Classes loaded with local class loader first (parent last)
8- Restart the server
In case someone still needs a solution, the only way it worked for me was to change the file https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/validation/beanvalidation/LocalValidatorFactoryBean.html
from 5.x to use the logic from 4.x

Spring on WebSphere 8: Quartz job with web service call throws JAXBException "<class> is not known to this context"

I'm facing a JAXBException " is not known to this context" when calling a web service from within a job controlled by Quartz on Spring:
javax.xml.ws.WebServiceException: javax.xml.bind.JAXBException: com.xxxx.yyyy.zzzz.ImageMetaData is not known to this context
at org.apache.axis2.jaxws.ExceptionFactory.createWebServiceException(ExceptionFactory.java:175)
at org.apache.axis2.jaxws.ExceptionFactory.makeWebServiceException(ExceptionFactory.java:70)
at org.apache.axis2.jaxws.ExceptionFactory.makeWebServiceException(ExceptionFactory.java:128)
at org.apache.axis2.jaxws.marshaller.impl.alt.DocLitWrappedMinimalMethodMarshaller.demarshalResponse(DocLitWrappedMinimalMethodMarshaller.java:624)
at org.apache.axis2.jaxws.client.proxy.JAXWSProxyHandler.createResponse(JAXWSProxyHandler.java:593)
at org.apache.axis2.jaxws.client.proxy.JAXWSProxyHandler.invokeSEIMethod(JAXWSProxyHandler.java:432)
at org.apache.axis2.jaxws.client.proxy.JAXWSProxyHandler.invoke(JAXWSProxyHandler.java:213)
at com.sun.proxy.$Proxy299.findAllImageMetaData(Unknown Source)
I'm having a Spring 3.2.4 Java EE application with JSF running on IBM WebSphere v8.
When calling a specific web service from the JSF part of the application (i.e. from an action or a service), everything's ok.
The exception occurs only when the call is done from within a Quartz/Spring triggered job.
Executing exacty the same job code from the action does not result in an exception.
I tried a lot of different things like using a corresponding #XmlSeeAlso annotation in the JAXB generated classes but even using the annotation in the webservice interface itself does not solve the issue.
I also updated the Spring and Quartz libraries to more recent versions but this didn't help.
Anyone any idea?
I've finally solved the issue.
After much analysis I encountered the following issue in the Spring framework:
https://jira.spring.io/i#browse/SPR-11125
When a job is triggered via Spring/Quartz on WebSphere, the wrong ContextClassLoader is set.
This may cause many different problems - among them is the JAXBException as described.
The Spring bug is still open - so as a workaround I had to overwrite the context class loader of the current thread by the correct one:
ClassLoader cl = invoiceService.getClass().getClassLoader();
Thread.currentThread().setContextClassLoader(cl);
The correct class loader can be simply retrieved by a class that has been loaded by the container. Using this class loader as the context class loader for the current thread solved my issue.

Resources