Include resources in bnd file - osgi

I am trying to create a bundle x from lets say from 3 dependancies
a.jar has spring-context.xml
b.jar has spring-cotext.xml
c.jar has spring-beans.xml
My x bundle should import all the a,b,c jar resources and merge them into a context xml in x.jar when bundle is created. is this possible?
i have a maven project a, b,c are maven jar modules. x is a bundle project which has depencies of a,b,c.
Please can anyone help ?

I'm sure this is possible, but you might have to write the actual code to do the merge of those XML files. Combining a, b and c into a bundle x is something that the available tooling can do for you. You can take a look at Bnd or one of the tools that uses Bnd under the covers (Maven Bundle Plugin and others).

What you have suggested (combining spring contexts from multiple bundles) goes against the principles underlying OSGi. You should not have bundles that are dependent on the context of other bundles.
You should handle the dependencies by utilizing OSGi Services. Because you are using spring context files, I'm assuming that you're using Spring-DM. You can register a service in Spring DM with the following (which is usually done in a seperate osgi-context.xml file to ensure that the code base is not dependent on OSGi for testing purposes. In this example, you would have a bean with the id clinic defined in BContext.xml, and which is referenced as an OSGi service
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/osgi"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/osgi
http://www.springframework.org/schema/osgi/spring-osgi.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<service id="osgiClinic" ref="clinic" interface="org.springframework.petclinic.repository.Clinic" />
</beans:beans>
Then in the consuming bundle's osgi-context.xml, you would reference the service. In the example below, you now have a bean called clinic that utilizes the code from the first bean.
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/osgi"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/osgi
http://www.springframework.org/schema/osgi/spring-osgi.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<reference id="clinic" interface="org.springframework.petclinic.repository.Clinic"/>
</beans:beans>
This way of doing things will make sure you think about the dependencies between your bundles and only export those beans that are necessary for other bundles.

Related

Where is hided <context:annotation-config/> in spring boot?

To work via annotations in Spring need to define:
<?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
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"
xmlns:context="http://www.springframework.org/schema/context">
<context:annotation-config/>
</beans>
at
annotation-config.xml
But I created a simplest Spring boot Application (lets say I select lust Web in initialazr)
It works on annotations but there isn't any annotation-config.xml there and nor mentioning of ,
where is hidden?
You only need to add <context:annotation-config /> or <context:component-scan /> (which implies annotation driven config) when using an ApplicationContext implementation that doesn't support annotations out-of-the-box.
When only using XML based configuration you also use one of the XML enabled ApplicationContext implementations, generally that would be XmlWebApplicationContext. With these you would need to instruct the ApplicationContext to enable annotation processing.
When using Java based configuration you generally use an annotation based ApplicationContext, default would be AnnotationConfigWebApplicationContext. Due to its nature of processing Java configuration classes it has annotation processing enabled by default.
Spring Boot uses the latter (it actually uses a specialized subclass for this). Hence you don't need to explicitly enable it.

Integration of JSF 2 and Spring 4 (no Spring MVC)

I've been struggling for 2-3 weeks now with transforming my project (single module) into a multi module project where the modules are representing the layers of a multilayer architecture (i.e. persistence, business, domain...)
When the project was still a single module, everything worked together. I had my ManagedBean classes managed by JSF and enabled #Autowired for Spring with a workaround, so I could inject my Spring-managed classes into the jsf-managed beans. Now, this won't seem to work anymore, so I'm trying to clean my code up and orientate myself at some examples I've seen (one is the Maven archetype for jsf2 + spring 4 integration).
It seems, there are two ways suggested to do the Dependency Injection:
Do it per #ManagedProperty (But I don't want to do this all per JSF)
Do it per #Autowired and let Spring manage the Backing/Managed Beans (That's what I try to do)
Though many sources (even the Maven archetype, which is working) suggest to just annotate my Backing Bean class with Spring annotations (#Component, #Scope("session")), I always get the error
Caused by: javax.el.PropertyNotFoundException: Target Unreachable, identifier 'administration' resolved to null
web.xml
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath*:/WEB-INF/applicationContext.xml
</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>
org.springframework.web.context.request.RequestContextListener
</listener-class>
</listener>
applicationContext.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.0.xsd" >
<context:component-scan
base-package="my.base.projectpackage" />
<context:annotation-config />
<context:spring-configured />
<!-- import the other context files for Spring -->
<import resource="classpath*:META-INF/*-springContext.xml"/>
faces-config.xml
<faces-config xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_2.xsd"
version="2.2" metadata-complete="false">
<application>
<el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
</application>
</faces-config>
I've already tried to:
Enable Autowiring into a JSF managed bean (per [...].autowire(this) -> not working, NPE for the Service class)
Try it with #ManagedProperty on JSF annotated Service classes (not working, NPE for the Service class)
Try it with pure Spring classes (like mentioned above, not working identifier resolved to null for the managed bean)
I can compile and build the modules and the whole project without errors, and I've also not forgotten to put intermodular dependencies (like business module is depending on persistence module) into the pom.xml. Every module has packaging "jar" (except ofc the webapp module, which is war). Did I forget to mention something else?
I run the project on Tomcat 8 (though this should not be the source of the error).
Maybe someone of you has got a hint, idea or solution for me.
Thanks in advance.
Edit
I got my project to work again and split it into multiple modules. But the only way to do this was to really copy + paste (argh! really..) my classes into the Maven archetype project and add some minor, not important fixes (like cleaning out my POM files). When it worked there, I was curious, copied the project files back into my old project and tried it there again. Surprisingly, it still didn't work, even though there was no difference anymore which could have caused it not to work. So, the mystery is still unsolved, but after all, I could continue with my work.
Thank you for your help (or for trying to help me, since this was a lost cause) #Tiny.

How to add one more dtd to my Spring configration file?

I have use a .dtd to my applicationContext.xml, but now i want to use Spring's AOP based on annotation. I've been told to add a in my applicationContext.xml.
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<aop:aspectj-autoproxy />
...
But something wrong happens. It seems that the file doesn't recognize the aop node, so i think i should import one more .dtd file, and i find this:
<!DOCTYPE aspectj PUBLIC
"-//AspectJ//DTD//EN" "http://www.eclipse.org/aspectj/dtd/aspectj.dtd">
but can i use both .dtd togeter? how?
thx
You don't have to use DOCTYPE here, better declare xml namespaces like this:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop"
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
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<beans>
<aop:aspectj-autoproxy />
...
xmlns="http://www.springframework.org/schema/beans" means that beans will be root namespace (you don't have to use <beans:bean>) and aop will be accesible as desired.
The two DTDs you cite are not constructed in a way that allows them to be used together. In particular, the definition of beans in http://www.springframework.org/dtd/spring-beans.dtd is just
<!ELEMENT beans (
description?,
(import | alias | bean)*
)>
It does not provide for a child named aop:aspectj-autoproxy, and it doesn't provide any mechanism for later users like you to add new things to the content of beans.
DTDs can be built for extensibility and to support the integration of elements from multiple namespaces, though it requires a bit of forethought and planning. When extension points are not included, it's typically pretty hard or impossible to extend the DTD without just rewriting it.

Load time weaving in grails

I'm trying to use load time weaving in a Grails project in order to be able to serialize and deserialize an object and to have automatic injection of spring dependencies. After some searching I found an easy example and that seems to work as expected. But after applying the same configuration to a simple Grails project I get a lot of errors. For example:
[TomcatInstrumentableClassLoader#413a2870] error at org/springframework/web/servlet/theme/AbstractThemeResolver.java::0 class 'org.springframework.web.servlet.theme.AbstractThemeResolver' is already woven and has not been built in reweavable mode
To test this I created a new grails project and changed the applicationContext.xml:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:spring-configured />
<context:load-time-weaver aspectj-weaving="autodetect" weaver-class="org.springframework.instrument.classloading.ReflectiveLoadTimeWeaver"/>
In this file I also created a new bean:
<bean class="be.testweaving.Person" scope="prototype">
<property name="name" value="Timon"/>
</bean>
This defines a prototype for the Person class and injects the value Timon into the name property.
I package this as a war using grails war and deploy this on a tomcat server. This tomcat has the org.springframework.instrument.tomcat-3.0.5.RELEASE.jar in his lib directory and after the deployment I see a huge list of the errors I mentioned above.
Has anyone been able to configure load time weaving in Grails?
Why don't you just inject your property via metaclass?
class ExampleBootStrap {
def init = { servletContext ->
Person.metaClass.constructor = {
def person = BeanUtils.instantiateClass(Person)
person.name = "Timon"
person
}
}
}

Why does my Spring AOP aspect work in my unit test but not my webapp?

I have an aspect working correctly in my unit tests, a log message is printed from the actual method, and afterwards from the aspect applied.
When running my webapp though, I only see the result of the '#afterReturning' advice applied, my method does not execute first.
My config:
<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">
<aop:aspectj-autoproxy proxy-target-class="true" />
<bean id="loggingAspect" class="com.mypackage.MyAspect" />
</beans>
Any ideas ?
Thanks for your help.
Information you provided in not enough to analyze. So check below things in your web app,
1) Verify that the method you are expecting to be intercepted by your advice, belongs to spring bean class & not some other servlet or other class defined outside spring. If any class is not initialized through spring then aop advice can not be applied to that class.
2) Verify that above aop & advice configs are put in proper context xml for spring. Like in case of spring-mvc, you have to explicitely define the name of your application context xml. And in that application context xml only you have to write aop configurations.
3) Verify if your pointcut is appropriate to find exact class & method for advice.
See if these things are in place.

Resources