springDM Configuration Admin bulk properties change - java

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.

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>

Context file getting over written in spring

http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
<import resource="classpath:context2.xml"/>
<import resource="classpath:context3.xml" />
Here Context1.xml is getting over written by context2.xml, context 1.xml and context2.xml are both MDB's. context3.xml is not having issues.
COntext 1 and context2 have some same Bean ID's but have different properties and references.
I found the solution . I was using same Bean ID and thought that it was a pre defined bean ID. I did not have much knowledge on spring . So i studied a bit and found out that u can give any bean ID u want for the class which you are referring to.

In Spring, How to Define Two Beans, with Same Name and Different Class

I have a java project, using Spring. I have defined three classes: BaseClass, SubClass1 and SubClass2. Two SubClassx both extend BaseClass.
Now, I need to define two beans, one is in a specific profile:
<bean id="newBean" class="SubClass1">
and
<beans profile="xxx">
<bean id="newBean" class="SubClass2">
</beans>
they are in different xml files. I use lombok to inject SubClass2 newBean in a Class:
public class WarmUpAgent extends WarmUpAgent {
#Setter(onMethod = #__(#Required))
private SubClass2 subClass2;
...
<bean id="warmUpAgent" class="WarmUpAgent">
<property name="subClass2" ref="newBean" />
</bean>
But when I run the project with profile "xxx", it throws:
IllegalStateException: Cannot convert value of type [SubClass1] to required type [SubClass2] for property 'subClass2'
It seems that fail to overwrite bean newBean with SubClass2, even though I have activated profile "xxx". Is there any way to use profile, to define two beans, with same name and different class?
Thank you very much.
========================================================================
I put
<bean id="newBean" class="SubClass1">
and
<beans profile="xxx">
<bean id="newBean" class="SubClass2">
</beans>
in one xml file, and it works. But I'd like to separate them into two xml files, according to the project organization. Any solutions to implement this?
Try restricting the first bean to the default profile
<beans profile="default">
<bean id="newBean" class="SubClass1">
</beans>
<beans profile="xxx">
<bean id="newBean" class="SubClass2">
</beans>
Try using same name instead of id.
<bean name="newBean" class="SubClass1">
<beans profile="xxx">
<bean name="newBean" class="SubClass2">
</beans>

Akka Camel and Spring

I want to combine Akka, Apache Camel, Spring and do not know the way forward for leveraging the three things in the same project.
I was successfully able to
1. write some working code with akka, akka-camel extension and camel routes(Java DSL)
2. use camel and spring (use java DSL but spring for transactions and etc..)
Now I need to combine 1 and 2. Can anyone suggest me the simplest way to achieve this?
EDIT
Some say AKKA no longer supports Spring due to conflict in object instantiation as per the link below
Why spring integration doc for akka exists only for 1.3.1 but not for next versions
Also a similar question is there without a proper solution being presented but the post is about 2 years old
akka-camel 2.2.1 route definition using Spring XML
In one blog post (which I can't get hold of the link right now) a method has been described which is in summary, the actors are defined and used Akka way and what ever the processing Akka actors does to be wired using Spring. But there wasn't any solid example.
I imagine your #2 looks like this:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ctx="http://www.springframework.org/schema/context"
xmlns:camel="http://camel.apache.org/schema/spring"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd >
<!-- Camel route configuration -->
<camelContext id = "testCamelRouteContext" xmlns="http://camel.apache.org/schema/spring">
<route id="test_data_webservice">
<from uri="jetty:http://localhost:8888/myTestService"/>
<log logName="HTTP LOG" loggingLevel="INFO" message="HTTP REQUEST: ${in.header.testdata}"/>
<process ref="myTestService"/>
</route>
</camelContext>
<context:annotation-config />
<bean class="com.package.service" id="myTestService"/>
<bean id="genericDao" class="com.dao.Impl">
<property name="dataSource" ref="datasource" />
</bean>
<bean id="testingDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
datasource stuff
</bean>
</beans>
Is it possible that you can get this camel context through Akka? Something like.
Add in your Akka config:
akka.camel.context-provider="myNewContext"
New ContextProvider class:
class myNewContext extends ContextProvider{
override def getContext(system: ExtendedActorSystem): SpringCamelHybridContext
}
I am guessing this is where the bean injection collision between Spring and Akka could occur. I have never used Akka before so my answer is trivial but I wanted to see if I could provide some help to you.
Reviving an old thread.
akka-springctx-camel library is there to make your life painless to integrate Akka, Spring, Camel, CXF etc.
Add artifact :
<dependency>
<groupId>com.github.PuspenduBanerjee</groupId>
<artifactId>akka-springctx-camel</artifactId>
<version>1.0.0</version>
</dependency>
Add Camel Context Provider in Akka config:
akka.camel.context-provider=system.SpringCamelContextProvider
Get hold of ActorSystem :
implicit val system = SpringContextActorSystemProvider.create
Create a custom RouteBuilder[other way could be Akka Consumer]
class CustomRouteBuilder(system: ActorSystem, echoActor: ActorRef)
extends RouteBuilder {
def configure {
from("direct:testEP")
.routeId("test-route")
.to(echoActor)
}
Get Camel(Spring) Context and add routes to it:
val camel = CamelExtension(system)
camel.context.addRoutes(
new CustomRouteBuilder(system, system.actorOf(Props[EchoActor])))
This test case will give you a detailed idea: https://github.com/PuspenduBanerjee/akka-springctx-camel/blob/master/src/test/scala/AkkaSpringCtxTestSpec.scala

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.

Categories

Resources