Showing posts with label Spring. Show all posts
Showing posts with label Spring. Show all posts

Monday, August 10, 2015

cvc-elt.1: Cannot find the declaration of element 'beans'-Part2

In our previous series of the exception cvc-elt.1: Cannot find the declaration of element 'beans' We saw what is xml namespace uri and what is xml namespace prefix.And we resolve a flavor of the exception.Here in this blog we will see other favors of the same exception and measures to avoid it.Before knowing all this we should know how the application context xml document is interpreted by JAVA xml Parser and what are the different components of the application context.

Sample xml configuration:


<xml version="1.0" encoding="UTF-8"?>
      <beans xmlns="http://www.springframework.org/schema/beans"
      xmlns:context="http://www.springframework.org/schema/context"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns:task="http://www.springframework.org/schema/task"
      xsi:schemaLocation="http://www.springframework.org/schema/beans
                      http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
                      http://www.springframework.org/schema/task
                      http://www.springframework.org/schema/task/spring-task-3.1.xsd
                      http://www.springframework.org/schema/context
                      http://www.springframework.org/schema/context/spring-context-3.1.xsd ">
Have a look at xsi:schemaLocation.This is used by JAVA xml Parser to validate the xml file.Suppose we have a tag defined in application context  like "context" .For this we have to declare the context namespace.Now what Java xml parser will  here.It will read the  schemaLocation of "context" element as http://www.springframework.org/schema/context/spring-context-3.1.xsd.And try load them from internet to validate the xml file.And Spring intercepts these load requests  and try to find the same xsd version from its own classpath.
Let's do a little bit more analysis.When we build a war or jar file to deploy in production machine, a spring.schemas property  file is created inside the META-INF folder.The contents of the spring.schemas look like this.


Sample Spring.schemas:


http\://www.springframework.org/schema/context/spring-context-2.5.xsd=
org/springframework/context/config/spring-context-2.5.xsd

http\://www.springframework.org/schema/context/spring-context-3.0.xsd=
org/springframework/context/config/spring-context-3.0.xsd

http\://www.springframework.org/schema/context/spring-context-3.1.xsd=
org/springframework/context/config/spring-context-3.1.xsd

http\://www.springframework.org/schema/context/spring-context.xsd=
org/springframework/context/config/spring-context-3.1.xsd

http\://www.springframework.org/schema/jee/spring-jee-2.0.xsd=
org/springframework/ejb/config/spring-jee-2.0.xsd

http\://www.springframework.org/schema/jee/spring-jee-2.5.xsd=
org/springframework/ejb/config/spring-jee-2.5.xsd

http\://www.springframework.org/schema/jee/spring-jee-3.0.xsd=
org/springframework/ejb/config/spring-jee-3.0.xsd

http\://www.springframework.org/schema/jee/spring-jee-3.1.xsd=
org/springframework/ejb/config/spring-jee-3.1.xsd

http\://www.springframework.org/schema/jee/spring-jee.xsd=
org/springframework/ejb/config/spring-jee-3.1.xsd

http\://www.springframework.org/schema/lang/spring-lang-2.0.xsd=
org/springframework/scripting/config/spring-lang-2.0.xsd

http\://www.springframework.org/schema/lang/spring-lang-2.5.xsd=
org/springframework/scripting/config/spring-lang-2.5.xsd

http\://www.springframework.org/schema/lang/spring-lang-3.0.xsd=
org/springframework/scripting/config/spring-lang-3.0.xsd

http\://www.springframework.org/schema/lang/spring-lang-3.1.xsd=
org/springframework/scripting/config/spring-lang-3.1.xsd

http\://www.springframework.org/schema/lang/spring-lang.xsd=
org/springframework/scripting/config/spring-lang-3.1.xsd

http\://www.springframework.org/schema/task/spring-task-3.0.xsd=
org/springframework/scheduling/config/spring-task-3.0.xsd

http\://www.springframework.org/schema/task/spring-task-3.1.xsd=
org/springframework/scheduling/config/spring-task-3.1.xsd

http\://www.springframework.org/schema/task/spring-task.xsd=
org/springframework/scheduling/config/spring-task-3.1.xsd

http\://www.springframework.org/schema/cache/spring-cache-3.1.xsd=
org/springframework/cache/config/spring-cache-3.1.xsd

http\://www.springframework.org/schema/cache/spring-cache.xsd=
org/springframework/cache/config/spring-cache-3.1.xsd
When  we start our application by starting our application server (tomcat/jetty etc) or by simply running the main method,then it takes a schemaLocation value from our application context xml document and try to find the mapping for it in spring.schemas property file.If it finds one in the spring.schemas property file ,then it uses the value associated with this mapping.Usually the value is the location of the corsponding  xsd file.

Let's analyze some rows in spring.schemas property file.

http\://www.springframework.org/schema/context/spring-context-2.5.xsd
=org/springframework/context/config/spring-context-2.5.xsd

http\://www.springframework.org/schema/context/spring-context-3.0.xsd
=org/springframework/context/config/spring-context-3.0.xsd

http\://www.springframework.org/schema/context/spring-context.xsd=
org/springframework/context/config/spring-context-3.0.xsd
Here the left side represents the schemaLocation values as declared in application context xml document.And the right side represents the excat location of the corresponding xsd file.That is if we un jar the spring-context.jar file we will see the corresponding xsd file inside  the package
org.springframework.context.config
After getting the xsd file in the classpath(inside the spring-context.jar),the xml parser validates the tags in the application context document with the corresponding xsd file.

Note:If you are curious about the extra backslash(\) before the : in 
http\://www.springframework.org/schema/context/spring-context-2.5.xsd
Then note that the ':' character is a valid delimiter in the Java properties format, and so the ':' character in the URI needs to be escaped with a backslash.

Now come back to the contents of the spring.schemas property file

http\://www.springframework.org/schema/context/spring-context-2.5.xsd
=org/springframework/context/config/spring-context-2.5.xsd

http\://www.springframework.org/schema/context/spring-context-3.0.xsd
=org/springframework/context/config/spring-context-3.0.xsd

http\://www.springframework.org/schema/context/spring-context.xsd=
org/springframework/context/config/spring-context-3.0.xsd
This means that (in xsi:schemaLocation)   of application context xml document

http://www.springframework.org/schema/context/spring-context-2.5.xsd   
will be validtaed against
org/springframework/context/config/spring-context-2.5.xsd  
in the classpath
And
http://www.springframework.org/schema/context/spring-context-3.0.xsd 
and
http://www.springframework.org/schema/context/spring-context.xsd
will be validated against org/springframework/context/config/spring-context-3.0.xsd
in the classpath

Rule Of Thumb :

Always make sure the xsd version in application context xml document matches with xsd version availble in spring.schemas property file(which is inside META-INF).If we use in application context xml document a higher version  of xsd file and our application contains a lower version of the corresponding  jar file,then mismatch will be there.

But how it resolves the same when there is internet in the machine where application is deployed?
After searching the  class path,if Java xml Parser can't find the same version of the xsd file in the classpath, then it tries to look it over internet.So we get the exception in the machine where internet connection is not there.

Issue with jar creation in Eclipse:

Recently I was creating a jar for a spring application in STS 3.6.Here my application context xml document contains the same version of the xsd file as with my jar file.I matched everything .But still I was getting the same exception cvc-elt.1: Cannot find the declaration of element 'beans'.After digging a little I came to find that,the spring.schemas property file didn't contain any schemaLocation and it's corrsponding xsd file location mapping for 'bean' element.You can see this in sample spring.schemas header.So I copy paste the mapping for the same from another file in spring.schemas property file.Then it started working.So be careful when creating a runnable jar in eclipse. 


 


Saturday, August 8, 2015

cvc-elt.1: Cannot find the declaration of element 'beans'-Part1

Generally when working with spring applications,we get the exception cvc-elt.1: Cannot find the declaration of element 'beans'.There are various reasons for this.Usually we get the exception when we run this application in a machine where internet connection is not there.Now we identify some of the cases here and find out the root cause for this.And steps to take to avoid this exception.

To know what the error exactly is we need to know some more terms and definitions.Let's starts with an sample configuration that is a part of the application context.

Sample xml configuration:


<?xml version="1.0" encoding="UTF-8"?>

&ltbeans xmlns="http://www.springframework.org/schema/beans" 

    xmlns:context="http://www.springframework.org/schema/context"

    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 

    xmlns:task="http://www.springframework.org/schema/task" 

    xsi:schemaLocation="http://www.springframework.org/schema/beans 

                    http://www.springframework.org/schema/beans/spring-beans-3.1.xsd

                    http://www.springframework.org/schema/task

                    http://www.springframework.org/schema/task/spring-task-3.1.xsd

                  http://www.springframework.org/schema/context

                  http://www.springframework.org/schema/context/spring-context-3.1.xsd ">

Xml Namespace:

We can say an XML namespace declaration is a key-value pair.The key part of  the  XML namespace is declared using the reserved XML attribute xmlns or xmlns:prefix  and the value part is a URI(Uniform Resource Identifier). Here key part is called namespace prefix and value part is called namespace URI.
Let's analyze some examples of  XML namespace.

Let's consider the second line of the above xml snippet.

 xmlns:beans="http://www.springframework.org/schema/beans"
The above line defines a XML namespace.In our example here  "bean" is the namespace prefix which is a key part and  "http://www.springframework.org/schema/beans" is the namespace URI , which is the value part.

Similary in line

xmlns:context="http://www.springframework.org/schema/context"

"context" is the namespace prefix which is a key part and  "http://www.springframework.org/schema/context"  is the namespace URI , which is the value part.

Similarly in line

xmlns:security="http://www.springframework.org/schema/security"

 "security" is the namespace prefix which is a key part and  "http://www.springframework.org/schema/security"   is the namespace URI , which is the value part.

Ideas behind use of xml namespace:

1.XML namespace is used to group together elements having a common idea.
2.And to distinguish between different  elements  having the same name featuring different semantics.

For example consider a student having name and roll no and some other fields and the college  having name and location and some other fields.How can we distinguish here the name element,as name is available for both the tags student and college?For example

<student>
    <name>Alok</name>
    <rollno>17</rollno>
    <college>
        <name>DKL</name>
        <location>Delhi</location>
    </college>
</student>

We can distinguish between them by creating two unique namespace declaration for each.

Here

<studentxml:student 
xmlns:studentxml="http://www.my.student.com/xml/student" 
xmlns:collegexml="http://www.my.college.com/xml/college">
    <studentxml:name>Alok </studentxml:name>
    <studentxml:rollno>17 </studentxml:rollno>
    <collegexml:college>
        <collegexml:name>DKL</collegexml:name>
        <cityxml:locatio>Delhi</collegexml:location>
        </collegexml:college>
</studentxml:student>
Now there is no ambiguity between two name elements.So in our example xmlns:beans="http://www.springframework.org/schema/beans"  the namespace prefix is beans and namespace URI is http://www.springframework.org/schema/beans.
We can think of namespace prefix  is a short name(or can say an alias) for the complete namespace uri.
Any element or attribute whose name starts with the prefix "beans:" is considered to be in the beans namespace.
Also it is possible to declare a default namespace. This default namespace is like to declare a complete namespace uri without a namespace prefix as follows.
xmlns="http://www.springframework.org/schema/beans"
you can see this line is same as the second line of  the heading sample xml configuration.
In this case, any element without a namespace prefix is considered to be in the beans namespace.

Attributes are never come under the umbrella of  the default namespace. An attribute without an explicit namespace prefix is considered not to be in any namespace.

 By the time we have got a fair understanding of namespace prefix and namespace uri.Now we proceed  to the exception of type 1.

Exception Category 1:

 If we define the namepace prefix and namespace uri in below manner like

<?xml version="1.0" encoding="UTF-8"?>
&ltbeans xmlns:beans="http://www.springframework.org/schema/beans"
   xmlns:context="http://www.springframework.org/schema/context"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:task="http://www.springframework.org/schema/task"
   xsi:schemaLocation="http://www.springframework.org/schema/beans
                   http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
                   http://www.springframework.org/schema/task
                  http://www.springframework.org/schema/task/spring-task-3.1.xsd
                 http://www.springframework.org/schema/context
                http://www.springframework.org/schema/context/spring-context-3.1.xsd ">

                   <!-- some more bean declarations goes here -->
       </beans>
We will get the below exception.

Exception in thread "main" org.springframework.beans.factory.xml.XmlBeanDefinitionStoreException: Line 11 in XML document from class path resource [META-INF/spring/app-context.xml] is invalid; nested exception is org.xml.sax.SAXParseException; lineNumber: 11; columnNumber: 78; cvc-elt.1: Cannot find the declaration of element 'beans'.
    at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:396)
    at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:334)
    at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:302)
    at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:174)
    at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:209)
    at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:180)
    at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:243)
    at org.springframework.context.support.AbstractXmlApplicationContext.loadBeanDefinitions(AbstractXmlApplicationContext.java:127)
    at org.springframework.context.support.AbstractXmlApplicationContext.loadBeanDefinitions(AbstractXmlApplicationContext.java:93)
    at org.springframework.context.support.AbstractRefreshableApplicationContext.refreshBeanFactory(AbstractRefreshableApplicationContext.java:131)
    at org.springframework.context.support.AbstractApplicationContext.obtainFreshBeanFactory(AbstractApplicationContext.java:527)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:441)
    at org.springframework.context.support.ClassPathXmlApplicationContext.(ClassPathXmlApplicationContext.java:139)
    at org.springframework.context.support.ClassPathXmlApplicationContext.(ClassPathXmlApplicationContext.java:83)
    at com.one97.EsmeSimulator.Main.MainClass.main(MainClass.java:8)
Caused by: org.xml.sax.SAXParseException; lineNumber: 11; columnNumber: 78; cvc-elt.1: Cannot find the declaration of element 'beans'.
    at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(Unknown Source)
    at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.error(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.handleStartElement(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.startElement(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.scanStartElement(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl$NSContentDriver.scanRootElementHook(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$PrologDriver.next(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown Source)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown Source)
    at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(Unknown Source)
    at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(Unknown Source)
    at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(Unknown Source)
    at org.springframework.beans.factory.xml.DefaultDocumentLoader.loadDocument(DefaultDocumentLoader.java:75)
    at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:388)
    ... 14 more

Solution to the Exception Category 1:

Notice here in line no 2 of the namespace declaration, we declare the namespace prefix like
beans xmlns:beans="http://www.springframework.org/schema/beans"
Here we have bounded the relevant namespace uri to a prefix.But we are using the beans tag like.
  </beans>.Here we are using an unprefixed name for the beans element.

This problem has two solutions

solution:1 

Since the uri here is prefixed with namespace prefix bean,so we need to prefix the beans element as 
</beans:beans>.And also we need to do this for all the child elements of bean elements.

solution:2 

As  discussed above , we can declare the beans element as default namespace without any namespace prefix as follows
 beans xmlns="http://www.springframework.org/schema/beans" 
Then no need to add the prefix for beans element and for all it's child elements.

If you find it useful, please follow  the part 2 of the series  to find solutions for this kind of exceptions

Saturday, April 11, 2015

ThreadPoolTaskExecutor and HTTPConnectionManager

I was working on a project where it is a requirement to read some tasks from queue and process them.Let's say the queue name is fileSendQueue.There are multiple threads to get the tasks from the the queue   and process the tasks.Here ThreadPoolTaskExecutor of spring comes into picture.I have 10 threads in the thread  pool.Each thread takes a task from the queue process the task.After the completion of the task,the thread is returned to the pool.My Thread pool configuration is like  below

              <bean id="fileSenderTaskExecutor"
        class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
        <property name="corePoolSize" value="10" />
        <property name="maxPoolSize" value="10" />
        <property name="threadGroup" value="fileSenderThreadGroup" />

       </bean >
               
               
               
       




Here core pool size is 10 , max pool size is 10.
The job of each thread is to send a file to a remote server by httpclient.That is it  was a multipart post request.Soon after  deploying the application it is noticed that the task queue (fileSendQueue) is empty.
It looks like all the tasks in the queue are completed successfully.So far so good , so happy now, pretty cool.As expected my thread pool is working properly and it is emptying the queue and processing the tasks. And also successfully completing the task.But Soon after packing my bag for a short leave , I got a call , that the remote servers on the other sides are waiting for the files from this server.Ohh what happened, here my 
fileSendQueue size is 0.It indicates the tasks are processed from the queue.So the queue is empty now.But after logging a little more and analyzing I found the tasks are removed from the queue but it is not processed, it is stuck some where in between.Where did it  stuck?And from logging a little more it is clear that the active thread count is equal to the core pool size that is 10.Actually it is in the ThreadPoolTaskExecutor queue.
Just it removed from one queue and entered in another queue.But Why the tasks are in ThreadPoolTaskExecutor's queue?Since the number of active threads are equal to the core pool size.So the
ThreadPoolTaskExecutor queueed the tasks in its own queue.It is according to the documentation of  ThreadPoolTaskExecutor.But at first it seems ThreadPoolTaskExecutor is not working properly and it is not releasing the threads to the pool after the completion of tasks.So the active thread count is 10.But my assumption  was wrong.

The Bottleneck is not thread pool.It is with HTTPConnectionManager.The httpclient is taking too much time to send a file to remote server.So the next doubt is on HTTPConnectionManager.Perhaps it is not getting time out for bad connection as given in configurations of manager.The SOTimeout is defined as 30 seconds.That is the inactive time between two consecutive packet receive.Perhaps it is not obeying the configuration.And there is some issue with HTTPConnection manager.

After analyzing  a little more  I found  Http Manager is working expected.So what is happening here.Puzzled,confused?Actually the issue is with the file size and bidirectional connectivity.Assume That I have 100 tasks in the queue initially and more tasks are coming at run time.But the file need to send to remote server is of size like 150 MB or more and it is trying to send the file to remote server but taking too much time.Sometimes a thread is blocked for 1 hour or  more  to send a file.But  due to connectivity problem , some times at the end we are getting socket time out exception.

 java.net.SocketTimeoutException: Read timed out

So in this case thread was blocked for more than 1 hour and in the end did not do  anything useful as exception occurs at last moment due to connectivity issue.And it was the issue with all the tasks.The files size was so huge and connectivity was not smooth.

Solution to this problem: Make the file size small enough to send it in case bad connectivity.And make the task of the thread asynchronous.So that the thread from ThreadPoolTAskExecutor will not block till the completion of the task.It will not create load on the system as sooner or later the asynchronous task will complete and the threads will be released.