I am trying to develop a Spring "HelloWorld" project while I am runing that application it gives me this error:
INFO: Loading XML bean definitions from class path resource [Beans.xml] Exception in thread "main" java.lang.NoClassDefFoundError: org.springframework.expression.ExpressionParser
Below is my code:
package com.tutorialspoint;
public class HelloWorld {
private String message;
public void getMessage() {
System.out.println("your message : "+message);
}
public void setMessage(String message) {
this.message = message;
}
}
and
package com.tutorialspoint;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MainApp {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
HelloWorld obj = (HelloWorld) context.getBean("helloWorld ");
obj.getMessage();
// TODO Auto-generated method stub
}
}
ApplicationContext.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="helloWorld" class="com.tutorialspoint/HelloWorld">
<property name="message" value="Hello World!"/>
</bean>
</beans>
Apart from adding all the dependent jars it seems like the class defined within the bean definition is invalid
com.tutorialspoint/HelloWorld
^
make it,
<bean id="helloWorld" class="com.tutorialspoint.HelloWorld">
<property name="message" value="Hello World!"/>
</bean>
also context.getBean("helloWorld ") should be changed to context.getBean("helloWorld")
include
spring-expression-3.1.1.Release.jar
under lib folder
I mentioned 3.1.1 as example you can use latest version, if any exist.
Add the spring dependencies to you class-path
If you´re not using Maven, as M Sach says, add the "spring expression-X.Release.jar" to your "lib" folder and also DON´T forget to add it to the build path in Eclipse
This Exception related to spring-expression.jar add this.
add below dependency in your pom.xml
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>5.3.8</version>
</dependency>
Related
I have a complicated set of XSDs, so the end XSD has many <xsd:import> entries, so it requires a resource resolver to locate the referenced XSDs. The resource resolver then needs to be injected into the SchemaFactory. Simplified example:
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.ndg</groupId>
<artifactId>dummy</artifactId>
<name>NDG test project</name>
<description>NDG test project</description>
<version>0.0.1-SNAPSHOT</version>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.10.1</version>
<configuration>
<release>11</release>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
<dependencies>
<dependency>
<groupId>jakarta.xml.bind</groupId>
<artifactId>jakarta.xml.bind-api</artifactId>
<version>4.0.0</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>4.0.0</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.22</version>
</dependency>
</dependencies>
</project>
Resolver.java
import org.w3c.dom.ls.LSInput;
import org.w3c.dom.ls.LSResourceResolver;
public class Resolver implements LSResourceResolver
{
#Override
public LSInput resolveResource (String type, String namespaceURI, String publicId, String systemId, String baseURI)
{
return null;
}
}
Main.java
import javax.xml.validation.SchemaFactory;
public class Main
{
public static final void main (final String [] args)
{
Resolver resolver = new Resolver ();
SchemaFactory schemaFactory = SchemaFactory.newInstance ("http://www.w3.org/2001/XMLSchema");
schemaFactory.setResourceResolver (resolver);
System.out.println ("All ok");
}
}
This runs fine, both under JDK 11 and JDK 17. But if I try to wire the application with Spring, like so:
spring-beans.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd" >
<bean id="resolver" class="Resolver" />
<bean id="schemaFactory" class="javax.xml.validation.SchemaFactory" factory-method="newInstance">
<constructor-arg value="http://www.w3.org/2001/XMLSchema" />
<property name="resourceResolver" ref="resolver" />
</bean>
</beans>
Spring.java
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Spring
{
public static final void main (final String [] args)
{
new ClassPathXmlApplicationContext ("/spring-beans.xml");
System.out.println ("All ok");
}
}
Then on JDK 11 it outputs a warning:
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by org.springframework.beans.BeanWrapperImpl$BeanPropertyHandler (file:/W:/maven/repository/org/springframework/spring-beans/5.3.22/spring-beans-5.3.22.jar) to method com.sun.org.apache.xerces.internal.jaxp.validation.XMLSchemaFactory.setResourceResolver(org.w3c.dom.ls.LSResourceResolver)
and on JDK 17 such usage of internal types is now illegal and so it fails completely. Note SchemaFactory is an abstract class - the concrete class at runtime is com.sun.org.apache.xerces.internal.jaxp.validation.XMLSchemaFactory as per the message, so the warning/error is technically correct in that the code is indeed trying to call setResourceResolver on an internal com.sun class.
What I don't understand is:
Why does it work directly in my Main class but not from Spring? Surely they're both just calling the same setResourceResolver method.
If it is a problem with Spring, then do they not have JDK 17 support yet? I read Spring 5.3+ should be fine with JDK 17.
Is there any solution other than waiting for Spring 6? (will that even solve it?)
Given that the problem seems to be Spring invoking methods on public interfaces or abstract classes which have com.sun internal implementations, I came up with this workaround. But don't really regard this as an acceptable solution, it shouldn't be necessary to have to create a "setter class" like this, I would much rather see a way to have Spring handle this natively.
SchemaFactoryFactory.java
import javax.xml.validation.SchemaFactory;
import org.w3c.dom.ls.LSResourceResolver;
public class SchemaFactoryFactory
{
public SchemaFactory createSchemaFactory (final LSResourceResolver resourceResolver)
{
final SchemaFactory factory = SchemaFactory.newInstance ("http://www.w3.org/2001/XMLSchema");
factory.setResourceResolver (resourceResolver);
return factory;
}
}
Updated spring-beans.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd" >
<bean id="resolver" class="Resolver" />
<bean id="schemaFactoryFactory" class="SchemaFactoryFactory" />
<bean id="schemaFactory" class="javax.xml.validation.SchemaFactory" factory-bean="schemaFactoryFactory" factory-method="createSchemaFactory">
<constructor-arg ref="resolver" />
</bean>
</beans>
If I move the resource file to the resource folder, it will not be found.
However, when the resource file is placed in the main folder, it is recognized.
I did not understand why. Please help me.
Why do not they recognize it when they're in a resource folder?
main file
ApplicationContextExam01.java
package kr.or.connect.diexam01;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class ApplicationContextExam01 {
public static void main(String[] args) {
ApplicationContext ac = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
System.out.println("init!!");
UserBean userBean = (UserBean)ac.getBean("userBean");
userBean.setName("sakura");
System.out.println(userBean.getName());
}
}
resource file
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="userBean" class="kr.or.connect.diexam01.UserBean"></bean>
</beans>
Your resource file should be placed in the default package that is your "src" folder. and when starting your context you just call your file by
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
I was experimenting with AspectJ. I tried to apply aspect on String class. I created Spring configuration file as:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd ">
<!-- Enable #AspectJ annotation support -->
<aop:aspectj-autoproxy />
<!-- Employee manager -->
<bean id="employeeManager" class="com.test.advice.EmployeeManager" />
<!-- Logging Aspect -->
<bean id="loggingAspect" class="com.test.advice.LoggingAspect" />
<bean id="bean1" class="java.lang.String">
<constructor-arg value="abx" />
</bean>
</beans>
Then an Aspect class like,
package com.test.advice;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
#Aspect
public class LoggingAspect
{
#Around("execution(* java.lang.String.*(..))")
public void logAroundGetEmployee(ProceedingJoinPoint joinPoint) throws Throwable
{
System.out.println("works");
}
}
After that created a class with a main method like:
package com.test.advice;
package com.test.advice;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class AspectJAutoProxyTest
{
public static void main(String[] args)
{
ApplicationContext context = new ClassPathXmlApplicationContext("Spring-Customer.xml");
String pqr = (String) context.getBean("bean1");
pqr.trim();
}
}
On running it should output "works" to console. But it fails saying,
Exception in thread "main" java.lang.ClassCastException: com.sun.proxy.$Proxy5 cannot be cast to java.lang.String
at com.test.advice.AspectJAutoProxyTest.main(AspectJAutoProxyTest.java:13)
What is the issue? Can't we apply proxy to java.lang objects? Please help.
To use a proxy object as a replacement for the real object, the proxy object must be of a subclass of the real object. String being final, the JVM does not permit creating such a subclass.
(Note that spring has two proxy modes; one creates an actual subclass and the other just implements all public interfaces. You're probably using the latter, but if you changed to the former, you'd see an exception at proxy creation time)
This is my code. I have gotten some errors. Can anyone help me solve the problem? I get some casting errors, like cast ClassPathResource to Resource and resource object r to resource.
package firstspring;
import javax.annotation.Resource;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
public class test {
public static void main(String[] args){
Resource r =new ClassPathResource("applicationContext.xml");
BeanFactory bf=new XmlBeanFactory(r);
Student stud=(Student)bf.getBean("first");
stud.display();
}
}
This is my XML file;
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="first" class="Student">
<property name="name" value="sneha"></property>
</bean>
</beans>
You are using both the resources like javax.annotation.Resource and org.springframework.core.io.Resource, which has resulted in a conflict.
You need to use them like this
org.springframework.core.io.Resource r = new ClassPathResource("applicationContext.xml");
then program will execute.
Instead of importing
javax.annotation.Resource
use,
org.springframework.core.io.Resource
I'm writing a simple Spring 3.1 test, I'm getting an exception when adding the following line in my config:
<context:component-scan base-package="com.software.shared" />
Here's the exception:
INFO: Loading XML bean definitions from class path resource [spring-config.xml]
Exception in thread "main" java.lang.NoClassDefFoundError: org.springframework.beans.FatalBeanException
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:997)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:943)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:485)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:585)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:913)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:464)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83)
at com.software.shared.PersonBeanTest.<init>(PersonBeanTest.java:15)
at com.software.shared.PersonBeanTest.main(PersonBeanTest.java:31)
I don't get what's going on. If I remove the line, the exception dissappears, but Autowiring doesn't work.
I have all the jars in the spring 3.1 RELEASE distribution, on my class path, including org.springframework.beans-3.1.0.RELEASE.jar and I checked that it contains that file.
This is the code in the main method:
package com.software.shared;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;
#Service
public class PersonBeanTest {
public PersonBeanTest() {
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
//System.out.println("Name=" + ((PersonBean) (context.getBean("personBean"))).getName());
}
private PersonBean myBean;
public PersonBean getMyBean() {
return myBean;
}
#Autowired
public void setMyBean(PersonBean myBean) {
this.myBean = myBean;
}
public static void main(String[] args) {
PersonBeanTest test = new PersonBeanTest();
System.out.println("Name=" + test.getMyBean().getName());
}
}
Here's the Spring config:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd"
default-autowire="byName">
<!-- <context:component-scan base-package="com.software" /> -->
<!-- Register Annotation-based Post Processing Beans -->
<context:annotation-config />
<!-- Scan context package for any eligible annotation configured beans. -->
<context:component-scan base-package="com.software.shared" />
<bean id="personBean" class="com.software.shared.PersonBean">
<property name="name" value="MyName" />
</bean>
</beans>
I start the app by right clicking on this class and clicking "Run As -> Java Application".
Any ideas on why I get the exception?
you are trying to make spring scan class PersonBeanTest in package com.software.shared, but meanwhile you are creating the same application context in the constructor of PersonBeanTest, I guess this is the root cause of the exception.
try to scan some other package:
<context:component-scan base-package="some.other.package" />
and test it with the following code snippet to see if it works
public class PersonBeanTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
assertNotNull(context.getBean(PersonBean.class));
}
}
In my case, this happened because of a StackOverflowError. In some Spring catch block, the FatalBeanException subclass initialization failed again because of the current very long stack, leading to a NoClassDefFoundError
I think When your ApplicationContext loads at startup it tries to instantiate the Bean PersonBeanTest using its default constructor inside which you are creating another ApplicationContext which will again try to instantiate the same bean.This process goes on for infinite time finally throwing an Exception.
I've had the same problem under different circumstances. I'm not sure why this happens, but you should be able to find the original exception by putting a breakpoint inside AbstractAutowireCapableBeanFactory where the BeanCreationException is being thrown.
Please make sure your spring-config.xml into the classpath.