What is mean by <beans:beans> and <beans> - java

What is the differences between
<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"
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-3.0.xsd">
and
<beans: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"
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-3.0.xsd">
Could you please explain what is the difference between these two.

It's an XML namespace used to separate potentially conflicting element names, so there's no real difference.
XML Namespaces

They are equivalent.
You can say the full name of the element is ns : elementName
e.g.:
http://www.springframework.org/schema/beans : beans
if you say xmlns="http://www.springframework.org/schema/beans" than it means "if you see an element without a namespace prefix, assume a default namespace of "http://www.springframework.org/schema/beans"
if you say xmlns:beans="http://www.springframework.org/schema/beans" than it means "if you see an element with a beans: prefix, assume it's shorthand for "http://www.springframework.org/schema/beans"

The key to understand this is the xmlns value. In both of the cases it's:
xmlns="http://www.springframework.org/schema/beans"
This specifies the default schema for the document. This means that every tag in the XML will should be part of this schema, unless explicitly specify which other schema is it part of.
Specifying that a tag comes from another schema is usually done by <schemaName:tagName> pattern. So, for example, if the tag name is part of the schema foo, you have to use it with <foo:name>.
When picking a default schema for the document, you're allowed to skip the schema name, like in your example with <beans>. In this case, the <beans> tag must be specified in the schema, pointed with xmlns.
In the other case, you're explicitly specifying that the tag beans is part of the schema with alias beans, which result to <beans:beans>. However, if you don't have a xmlns:beans=http://www.springframework.org/schema/beans definition, you'd result with an invalid XML.
Personally, I'd prefer always explicitly provide the schema alias, though.

The first one is correct and the second one isn't. The difference comes from your "default namespace". Your default namespace is beans. If your default namespace would be something else, like context for example, then you would need to explicitly define a beans namespace (which you haven't done in your example) and use the beans:beans style.
There is a different use case for nested <beans> element where you use a new <beans> tag inside your root <beans> tag:
for the purpose of defining a subset of beans with certain default values or to be registered only when certain profile(s) are active. Any such nested element must be declared as the last element in the document.
but your examples aren't related to this.

Simply, it allows you NOT to add the namespace in front of the element you choose that belongs the default namespace.
xmlns="namespace"
From the above example if:
i)xmlns="http://www.springframework.org/schema/beans"
Then you can use element <beans> as well as <beans:beans> - explicit syntax.
ii) xmlns="http://www.springframework.org/schema/p"
Then you can use <p> as well as <xmlns:p> - explicit syntax.
NOTE: You can only set the default namespace once using xmlns!

Related

Wrong Type at Constant Pool after Hot-Swapping Code using DCEVM

Hey everyone!
For context I am working on a simple spring project in intelliJ to configure it with HotswapAgent using DCEVM [8u181 build 2 ] along with the compatible JDK [ 8u181 ] on the Payara 5.0 Application Server.
Please bear with me in the next few snippets of code and my plausible explanation of what's happening and this is not a question regarding Spring MVC syntax or it's working.
This is the sample code I am testing on Hotswapping [ Not the Inbuilt on JVM but using DCEVM ] and HotswapAgent[1.3.0]
HelloWorldController.java
#Controller
public class HelloWorldController {
#Autowired HelloService helloService;
#RequestMapping("/hello")
public String hello(
#RequestParam(value = "name", required = false, defaultValue = "World") String name,
Model model) {
model.addAttribute("name", name);
System.out.println( helloService.sayHello() );
return "helloworld";
}
I don't want to include the code for helloService as it might bloat this post.
HelloService.sayHello() just churns out the quintessential Hello World in the console
As you can see above that auto-wiring has been turned on and it does the proper function(said above).
After this I comment out the Autowired Annotation and the function call, and this gives me an error which is :
org.springframework.web.util.NestedServletException: Handler dispatch failed; nested exception is java.lang.annotation.AnnotationFormatError: java.lang.IllegalArgumentException: Wrong type at constant pool index
Focus on :
java.lang.IllegalArgumentException: Wrong type at constant pool index
I debugged the application and found out that the IllegalArgumentException was raised when AnnotationParser was parsing the annotations of the Spring Controller class from the Constant Pool and the members(of one of the annotation which is 'type' of the annotation) was not correct when it was taken from the Constant Pool of the Class.
So from my knowledge the hotdeploying is not being done correct ( even though HotswapAgent says it has reloaded the class on the Payara Server) or there is something wrong with the JVM communication or the JDK, and I say this because when I do the opposite that is comment out autowiring then hot deploy and then run, so then I get a null pointer exception.
Note: just for added information
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.NullPointerException
If anyone needs more information or code or logs on this then I'd be more than happy to clarify. Thank you for your time everyone.
The retention policy of the Autowire is #Retention(RetentionPolicy.RUNTIME).
According to the JVM specification , the annotation should be available in binary form. (Reference : https://docs.oracle.com/javase/specs/jls/se8/html/jls-9.html#jls-9.6.4.2)
My assumption is java keeps the reference in the constant pool of all the classes with RUNTIME annotation. When you hotswap it, the class is hot swapped but constant pool is not refrenshed to reflect the class swap.
There is an similar open issue with hotswapagent : https://github.com/HotswapProjects/HotswapAgent/issues/256
Well this was weird to solve but it's not related to JDK version or DCEVM, but to the dispatcher servlet of Spring.
My Dispatcher Servlet was missing:
<annotation-driven />
Which is why it couldn't register the controller class and caused unwanted behavior. Also missing was the added XML Schemas.
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"
Just for completion purposes or if would be of help to anyone, I'll post the complete dispatcher servlet configuration.
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<annotation-driven />
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
<context:component-scan base-package="com.test" />
</beans:beans>

dependency-check in Spring3.x

Spring2.5 had a feature called dependency-check which can be given for a bean tag and default-dependency-check which can be given at the parent level <beans> tag.
Eg: <bean id="soandSo" class="..." dependecy-check=""/>
<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-2.5.xsd"
default-dependency-check="all">
however in Spring3.x these attributes are deprecated, is there any alternate way of setting dependency-check apart from using #Required attribute and any equivalent to default-dependency-check in Spring3.x??
This feature is no loger supported since Spring 3.x. You can achieve similar result by telling Spring to respect #Required and #Autowired annotations. It can be done using any of the following configuration options within XML context file:
<context:annotation-config/>
<context:component-scan base-package="*"/>
You can skip those options by registering appropriate BeanPostProcessors such as AutowiredAnnotationBeanPostProcessor and RequiredAnnotationBeanPostProcessor.
I think no, because In Spring 2.5 annotations were fully embraced and as the framework evolves through these types of changes, its evident that annotations will continue to be a strong driver in keeping the framework as clear and straightforward as possible.
Spring team now encourages developers to use the following alternatives going forward (with Spring 3 and beyond).
Use constructors (constructor injection instead of setter injection)
exclusively to ensure the right properties are set. Create setters
with a dedicated init method implemented.
Create setters with #Required annotation when the property is required.
Use #Autowired-driven injection which also implies a required property by
default.

Spring : order of <map> tag

I need to Inject a Map to a bean property and when map entries are traversed it should return them in insertion order. In Java, this is similar to the LinkedHashMap. But as I can't find anything in spring documentation related to the ordering of tag, I'm not sure whether I can use to use it in this scenario.
Can someone please let me know the whether I can use for this purpose.
Many thanks
Use this construct:
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
...
<util:map id="mymap" map-class="java.util.LinkedHashMap">
<entry key="a" value="b" />
<entry key="c" value="d" />
</util:map>
...
</beans>
to declare the map with ordered keys. You can then use this map using <ref id="mymap" /> or you can use this construct directly while declaring the value of Map property.
The default is LinkedHashMap - MapFactoryBean is used to create instances of Map. According to docs:
Simple factory for shared Map instances. Allows for central setup of
Maps via the "map" element in XML bean definitions.
and its setTargetMapClass method:
Set the class to use for the target Map. Can be populated with a fully
qualified class name when defined in a Spring application context.
Default is a linked HashMap, keeping the registration order.
See Also: LinkedHashMap
so no need to use <util:map> here.

springDM Configuration Admin bulk properties change

So, I have springDM managed properties
<beans:beans xmlns="http://www.springframework.org/schema/osgi-compendium"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:osgix="http://www.springframework.org/schema/osgi-compendium"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/osgi-compendium
http://www.springframework.org/schema/osgi-compendium/spring-osgi-compendium.xsd">
<beans:bean id="configurationBean" class="com.eugene.PropertiesBean">
<osgix:managed-properties persistent-id="MyPid" update-strategy="container-managed"/>
<beans:property name="host" value="localhost"></beans:property>
<beans:property name="port" value="5698"></beans:property>
</beans:bean>
</beans:beans>
Now, here is what I do. Deploy the bundle to Virgo, everything works great, the default properties (because the MyPid.properties is not deployed) get injected into the bean.
Deploy MyPid.properties where BOTH host and port are changed, they are both re-injected also.
That's great. But here is the thing, can I have one single method that would tell me that the bean has changed? The properties have been re-injected? Something like : afterPropertiesSet or init in XML config? Because right now having an afterPropertiesSet or init works only the first time the properties get injected, not the second, third and so on... Which is somehow logic.
I do not know (googleed it) if spring DM offers such a thing.
Thx! Eugene.
This is a known issue actually. We had to switch to bean-managed updates.

How to inject FactoryBean instead of object it produces?

Let's say I have following Spring config (version of Spring is 3.0.3):
<?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="theFactoryBean" class="wax.MyFactoryBean"/>
<bean id="factoryBeanUser" class="wax.FactoryBeanUser">
<!-- what should be placed here?-->
</bean>
</beans>
I have instance of FactoryBean implementation and some other instance. I need Spring to inject to other instance FactoryBean, not the object it produces.
There are two possible ways to solve it.
First one, obvious and malfunctional:
<bean id="factoryBeanUser" class="wax.FactoryBeanUser">
<property name="myFactoryBean" ref="&theFactoryBean"/>
</bean>
With this config Spring throws following exception on start:
[skipped irrelevant part]
Caused by: org.xml.sax.SAXParseException: The reference to entity "theFactoryBean" must end with the ';' delimiter.
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:195)
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.fatalError(ErrorHandlerWrapper.java:174)
at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:388)
at com.sun.org.apache.xerces.internal.impl.XMLScanner.reportFatalError(XMLScanner.java:1414)
I found this solution Spring: Getting FactoryBean object instead of FactoryBean.getObject(), this question is maked as answered and four people voted for it. So I assume that this solution might work, but currently there is something wrong in my code.
Second one, working but awkward:
public class FactoryBeanUser implements ApplicationContextAware{
private MyFactoryBean myFactoryBean;
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
myFactoryBean = (MyFactoryBean)applicationContext.getBean("&theFactoryBean");
}
}
My question is it possible to make first approach functional or I should stick with a second way?
It seems the XML parser interprets the ampersand (&) as a start of an XML-entity. You can try using ref="&theFactoryBean".
The spring docs is not clear whether this syntax is allowed in an xml file, or only with programatic lookup. But then the xml configuration is used by the app context, so I assume the & should work (although it seems it has not been the best choice for a special symbol)
Here's why I'd suggest another thing - if you really need the factory bean rather than its product, create another bean, that does not implement FactoryBean, define a method createObject() or something like that, and use it in all factories that need it.
A sidenote - better reference the xsd with the version included:
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd

Categories

Resources