I need the ability to reliably get client IP address in CXF JAX-WS and so I added the following code to my web service:
Message message = PhaseInterceptorChain.getCurrentMessage();
HttpServletRequest request = (HttpServletRequest)message.get(AbstractHTTPDestination.HTTP_REQUEST);
request.getRemoteAddr();
In order for the build to complete successfully, I had to add the following imports:
import javax.servlet.http.HttpServletRequest;
import org.apache.cxf.message.Message;
import org.apache.cxf.phase.PhaseInterceptorChain;
import org.apache.cxf.transport.http.AbstractHTTPDestination;
And add the following dependencies to my pom.xml:
<dependency> <!-- PhaseInterceptorChain & Message -->
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-api</artifactId>
<version>2.4.0</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http</artifactId>
<version>2.2.3</version>
</dependency>
<dependency> <!-- HttpServletRequest -->
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<!-- scope>provided</scope -->
</dependency>
But when I try to deploy the resulting successful(!) build, Tomcat (7.0.42) throws an exception and refuses to load the war file:
org.springframework.beans.factory.BeanDefinitionStoreException:
Unexpected exception parsing XML document from class path resource [beans.xml];
nested exception is org.springframework.beans.FatalBeanException:
Invalid NamespaceHandler class [org.apache.cxf.jaxws.spring.NamespaceHandler] for namespace [http://cxf.apache.org/jaxws]:
problem with handler class file or dependent class;
nested exception is java.lang.NoClassDefFoundError: org/apache/cxf/endpoint/AbstractEndpointFactory
...
Caused by: org.springframework.beans.FatalBeanException:
Invalid NamespaceHandler class [org.apache.cxf.jaxws.spring.NamespaceHandler]
for namespace [http://cxf.apache.org/jaxws]:
problem with handler class file or dependent class;
nested exception is java.lang.NoClassDefFoundError: org/apache/cxf/endpoint/AbstractEndpointFactory
...
Caused by: java.lang.ClassNotFoundException: org.apache.cxf.endpoint.AbstractEndpointFactory
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1714)
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1559)
Apparently, something is missing from my pom.xml that provides the necessary module at runtime. What am I missing?
Mystery solved. For the benefit of all I am providing the root cause of the problem and the solution:
The problem was in this line:
<version>2.4.0</version>
That is, cxf-api artifact's version did not match the CXF version throughout the project (and the pom.xml).
All I had to do to solve the problem was to change that line to:
<version>${cxf.version}</version>
Where cxf.version was defined earlier as 2.7.1.
Conclusion: CXF dependencies/packages/plugins versions must match throughout the pom.xml (or else you will get some "red herrings").
Related
After migrating application to Spring Boot 3 and Java 17 I tried to deploy it to Tomcat 10.1.x.
The deployment failed with exception:
Caused by: org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'mailSender' defined in class path
resource [org/springframework/boot/autoconfig
ure/mail/MailSenderPropertiesConfiguration.class]: Failed to
instantiate [org.springframework.mail.javamail.JavaMailSenderImpl]:
Factory method 'mailSender' threw exception with message: arraycopy:
element type mismatch: can not cast one of the elements of
java.lang.Object[] to the type of the destination array,
jakarta.activation.MimeTypeRegistry
The issue turned out to be caused by CXF library having dependency on:
com.sun.activation:jakarta.activation.
The solution is to exclude it from cxf:
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxws</artifactId>
<exclusions>
<exclusion>
<groupId>com.sun.activation</groupId>
<artifactId>jakarta.activation</artifactId>
</exclusion>
</exclusions>
</dependency>
Instead include directly the jakarta.activation-api as below:
<dependency>
<groupId>jakarta.activation</groupId>
<artifactId>jakarta.activation-api</artifactId>
<version>2.1.1</version>
</dependency>
There might be other libraries with the same dependency in the application.
For above the approach with deploying application to webapps-javaee folder and allowing Tomcat to perform migration doesn't work.
I tried to setup a new Spring Boot 2.4.3 project and I want to include Liquibase as well as Spring Data JPA.
To achieve this I use the following dependencies in my POM:
<dependency>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-core</artifactId>
<version>${liquibase.version}</version>
</dependency>
or...
<dependency>
<groupId>org.liquibase.ext</groupId>
<artifactId>liquibase-hibernate5</artifactId>
<version>${liquibase.version}</version>
</dependency>
...respectively and
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
with
<kotlin.version>1.4.31</kotlin.version>
<liquibase.version>4.3.1</liquibase.version>
<hibernate.version>5.4.29.Final</hibernate.version>
Yet, in the beginning, I don't have any DB setup so far and in application.yaml you can find:
server:
port: 8080
spring:
liquibase:
change-log: classpath:db/changelog/db.changelog.yml
wherbey db.changelog.yml is empty.
A Maven install using the spring-boot-starter-data-jpa dependency results in:
java.lang.IllegalStateException: Failed to load ApplicationContext
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'liquibase' defined in class path resource [org/springframework/boot/autoconfigure/liquibase/LiquibaseAutoConfiguration$LiquibaseConfiguration.class]: Invocation of init method failed; nested exception is
liquibase.exception.ChangeLogParseException: Empty file classpath:db/changelog/db.changelog.yml
Caused by: liquibase.exception.ChangeLogParseException: Empty file classpath:db/changelog/db.changelog.yml
while when commenting out this dependency the build succeeds.
I found out that the empty db.changelog.yml file must contain at least:
databaseChangeLog:
- changeset:
although on https://docs.liquibase.com/concepts/basic/changelog.html an example is given that an empty changelog.yaml file needs to look like:
databaseChangeLog:
, but this results in a BeanCreationException:
Caused by: liquibase.exception.ChangeLogParseException: Could not find databaseChangeLog node
I am adding SSO code in the webpage using SAML. And for this process I added the following code for Maven.
<!-- Spring Framework Security -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>5.1.2.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-config -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>5.1.2.RELEASE</version>
</dependency>
<!-- Spring Security SAML -->
<dependency>
<groupId>org.springframework.security.extensions</groupId>
<artifactId>spring-security-saml2-core</artifactId>
<version>1.0.2.RELEASE</version>
</dependency>
And I added the following code in the application context xml.
<!-- Initialization of OpenSAML library -->
<bean class="org.springframework.security.saml.SAMLBootstrap" />
But I get the following error
org.springframework.beans.factory.BeanCreationException: Error
creating bean with name
'org.springframework.security.saml.SAMLBootstrap#0' defined in class
path resource [conf/spring/root-context.xml]: Instantiation of bean
failed; nested exception is
org.springframework.beans.BeanInstantiationException: Failed to
instantiate [org.springframework.security.saml.SAMLBootstrap]: No
default constructor found; nested exception is
java.lang.NoClassDefFoundError:
org/springframework/beans/factory/access/BootstrapException
It appears certain jars are missing. How do I add this jar?
Thanks
Jae Kim
Bottom line is: update to 1.0.3.RELEASE solves the problem.
Explanation: class SAMLBootstrap throws (line 45) BootstrapException, which exists in spring-4 (spring-beans-4.2.4.RELEASE) but not in spring-5.
In spring-security-saml2-core-1.0.3.RELEASE the dependency in class BootstrapException is removed.
According to this issue https://github.com/spring-projects/spring-security-saml/issues/211
You just have to update saml library to the latest version
1.0.4.RELEASE
Problem
I build an application using a Neo4j database. I like to test some custom Cypher queries using Spring Boot's #DataNeo4jTest annotation (see also Spring Boot Test - Neo4j), but I run in either one of the following problems:
The test tries to connect to a Neo4j instance using the BOLT driver.
The test fails to load the embedded driver.
Details
My dependencies are managed with Maven following the Spring Data Neo4j Reference Documentation. Section 10.3.1 of the SDN documentation explains:
By default, SDN will use the BOLT driver to connect to Neo4j and you don’t need to declare it as a separate dependency in your pom. If you want to use the embedded or HTTP drivers in your production application, you must add the following dependencies as well. (This dependency on the embedded driver is not required if you only want to use the embedded driver for testing. See the section on Testing below for more information).
Therefore, the relevant parts of my pom.xml are:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi=...>
...
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.0.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
...
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-neo4j</artifactId>
</dependency>
<dependency>
<groupId>org.neo4j.test</groupId>
<artifactId>neo4j-harness</artifactId>
<version>3.3.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
...
</project>
My main/resources/application.yml is:
spring:
data:
neo4j:
uri: bolt://localhost
username: <username>
password: <password>
My test/resources/application.yml is:
spring.data.neo4j.uri: file:///neo4j.db
Without the test/resources/application.yml I get the following exception, which I assume is caused by using the BOLT driver:
org.springframework.transaction.CannotCreateTransactionException: Could not open Neo4j Session for transaction;
nested exception is org.neo4j.driver.v1.exceptions.AuthenticationException: The client is unauthorized due to authentication failure.
With the test/resources/application.yml I get the following exception:
java.lang.IllegalStateException: Failed to load ApplicationContext
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'neo4jAuditionBeanFactoryPostProcessor': Unsatisfied dependency expressed through constructor parameter 0;
nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory' defined in class path resource [org/springframework/boot/autoconfigure/data/neo4j/Neo4jDataAutoConfiguration.class]: Bean instantiation via factory method failed;
nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.neo4j.ogm.session.SessionFactory]: Factory method 'sessionFactory' threw exception;
nested exception is org.neo4j.ogm.exception.core.ConfigurationException: Could not load driver class org.neo4j.ogm.drivers.embedded.driver.EmbeddedDriver
Questions
Are there any dependencies missing?
Is the configuration wrong?
Does anyone have a link to a working example using the Spring Boot annotation #DataNeo4jTest?
Any suggestion is welcome.
I have found a solution to my problem. It seems as if the BOLT driver is used as default for testing as well - which is confusing given the Spring Data Neo4j (SDN) documentation. Finally, the pom.xml of the GitHub project movies-java-spring-data-neo4j helped me. I added the following test dependency to my pom.xml:
<dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j-ogm-embedded-driver</artifactId>
<version>${neo4j-ogm.version}</version>
<scope>test</scope>
</dependency>
I kept the test/resources/application.yml but removed the line:
spring.data.neo4j.uri: file:///neo4j.db
Now, the test context starts with the embedded driver, and creates a temporary database file like file:/C:/Users/Me/AppData/Local/Temp/neo4j.db6943517458205762238/, which is awesome. I can get a clean database instance for every test method.
I hope this answer will help others, who have the same problem. I'm happy to provide more details if necessary.
#DataNeo4JTest works great with Spring Boot 2.x.
Example Test:
#RunWith(SpringRunner.class)
#DataNeo4jTest
public class WidgetRepositoryTest {
#Autowired
private WidgetRepository repository;
private Widget widget;
#Before
public void setUp() {
widget = WidgetTestData.builder().build();
}
#Test
public void itShouldSaveAndRetrieve() {
final Widget saved = repository.save(widget);
assertThat(saved.getId()).isNotNull();
assertThat(saved.getName()).isEqualTo(widget.getName());
final Optional<Widget> found = repository.findById(saved.getId());
assertThat(found).hasValueSatisfying(w-> {
assertThat(w.getId()).isEqualTo(saved.getId());
assertThat(w.getName()).isEqualTo(saved.getName());
});
}
}
The Neo4J-related dependencies in my Maven POM:
<dependency>
<groupId>org.neo4j.test</groupId>
<artifactId>neo4j-harness</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j-ogm-embedded-driver</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-neo4j</artifactId>
</dependency>
I am implemented LDAP authentication in my Spring Boot Application. The dependencies added are as follows:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-ldap</artifactId>
</dependency>
<dependency>
<groupId>org.apache.directory.server</groupId>
<artifactId>apacheds-all</artifactId>
</dependency>
However I am still getting following ClassNotFoundException:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'springSecurityFilterChain'
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [javax.servlet.Filter]
Caused by: java.lang.NoClassDefFoundError: org/apache/directory/server/core/DirectoryService
Caused by: java.lang.ClassNotFoundException: org.apache.directory.server.core.DirectoryService
My maven dependency tree clearly shows apacheds-all is added successfully.
Why am I still getting this error?
Spring Security doesn't support Apache DS 2.0. Instead, you need to use 1.5.5. Also, note that later 1.5.x versions are not supported due to breaking API changes.