OSGI DS: properties -> ParseException - java

I use apache felix and I have the following annotation for my DS
#Component(immediate = false,properties = {"name:String=stub"})
Maven generates the following xml
<component ...>
<implementation ..../>
<service>
....
</service>
<properties enty="name:String=stub"/>
</component>
However, when I start this bundle I get the following:
ERROR: com.temp.biz (55): General problem with descriptor entry '/OSGI-INF/com.temp.MyClass.xml'
org.apache.felix.scr.impl.parser.ParseException: Exception during parsing
at org.apache.felix.scr.impl.metadata.XmlHandler.startElement(XmlHandler.java:364)
at org.apache.felix.scr.impl.parser.KXml2SAXParser.parseXML(KXml2SAXParser.java:82)
at org.apache.felix.scr.impl.BundleComponentActivator.loadDescriptor(BundleComponentActivator.java:245)
at org.apache.felix.scr.impl.BundleComponentActivator.initialize(BundleComponentActivator.java:158)
at org.apache.felix.scr.impl.BundleComponentActivator.<init>(BundleComponentActivator.java:120)
at org.apache.felix.scr.impl.Activator.loadComponents(Activator.java:258)
at org.apache.felix.scr.impl.Activator.access$000(Activator.java:45)
at org.apache.felix.scr.impl.Activator$ScrExtension.start(Activator.java:185)
at org.apache.felix.utils.extender.AbstractExtender.createExtension(AbstractExtender.java:259)
at org.apache.felix.utils.extender.AbstractExtender.modifiedBundle(AbstractExtender.java:232)
at org.osgi.util.tracker.BundleTracker$Tracked.customizerModified(BundleTracker.java:479)
at org.osgi.util.tracker.BundleTracker$Tracked.customizerModified(BundleTracker.java:414)
at org.osgi.util.tracker.AbstractTracked.track(AbstractTracked.java:232)
at org.osgi.util.tracker.BundleTracker$Tracked.bundleChanged(BundleTracker.java:443)
at org.apache.felix.framework.util.EventDispatcher.invokeBundleListenerCallback(EventDispatcher.java:913)
How to fix it? The problem disappears as soos as I remove properties from #Component.

For the OSGi DS #Component annotation, you want to use property:
#Component(immediate = false, property = {"name:String=stub"})
For the Felix SCR annotations, refer to the documentation.

Related

junit test for stateless ejb + jpa

I would like to write a junit test for my stateless ejb + jpa demo code. I think it is actually not a junit test, it is an integration test.
I have a stateless ejb with an injected EntityManager and PostgreSQL database server is used. I use CDI (Spring is not used in my project) and EclipseLink with a persistent.xml file. My application will be executed on GlassFish server.
I would like to write a test which checks the full logic: calls a method on my example stateless ejb and persist data into a in-memory database. I want to start the in-memory database with my tests and stop it when my test class was executed.
ejb class:
#Stateless
public class PropertyServiceImpl implements PropertyService {
#PersistenceContext(name = "anything-jndi-em")
private EntityManager em;
public String getStringValue(final String key) {
Property property = em.createNamedQuery("Property.findByKey", Property.class)
.setParameter("key", key)
.getSingleResult();
return property.getValue();
}
}
enitity class:
#Entity
#Table(name = "APPLICATION_SETTING")
#NamedQueries({
#NamedQuery(name = "Property.findByKey", query = "select a from Property a where a.key = :key and a.status = 1")
})
public class Property
{
#Id
#SequenceGenerator(name = "APPLICATION_SETTING_SEQ", sequenceName = "APPLICATION_SETTING_SEQ", allocationSize = 1)
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "APPLICATION_SETTING_SEQ")
#Column(name = "ID", unique = true, nullable = false)
private Long id;
#Column(name = "KEY", length = 200, nullable = false)
private String key;
...
}
If I am correct I need to follow the next steps:
create a new persistent.xml file with the proper jdbc connection parameters which will connect to the in-memory dadabase and put it under the /test/Resources/META-INF folder
add some pom dependencies for in-memory database (ex.: hsqldb) and embedded ejb container
create a simple PropertyServiceImplTest.java class
configure somehow that the /test/Resources/META-INF/persistent.xml file will be user by my test class
initialize the embedded ejb container and start the in-memory database
execute my juni test method:
#Test
public void testGetStringValue() {
PropertyService service = new PropertyServiceImpl();
assertNotNull(service.getStringValue("abc"));
}
Could you please help my to write a proper test java class for this scenario?
I highly recommend Arquillian. I use it with gradle on Wildfly 8, 9 and 10. Once setup properly, which can be a bit arduous, it works wonders.
You need only annotate your JUnit test like so:
#RunWith(Arquillian.class)
public class MRSInjectionServiceTests extends ...
And then provide a deployment archive which I do via JBoss ShrinkWrap:
#Deployment
public static WebArchive createDeployment() {
return ShrinkWrap.create(ZipImporter.class, "MRSInjectionServiceTests.war").importFrom(new File(ROOT_WAR_DEPLOYMENT_LOCATION)).as(WebArchive.class);
}
Then you can run these integration tests from maven or gradle. Arquillian will run your App server container (Wildfly, GLassfish, etcetera) based upon your configuration and will run the JUnit tests as a system test with your entire system running.
It is very nice. Well worth the effort.
In your actual test case boot up the javax.ejb.embeddable.EJBContainer. After that use its javax.naming.Context to lookup your stateless bean. The you can use your bean like you are used to and assert its behavior. Keep in mind that an embeddable container impl only has to support a subset (ejb lite) of functionality compared to a full blown ejb container. Here you find a pretty neat example.
Code snippet:
JBContainer ejbContainer = EJBContainer.createEJBContainer();
Context ctx = ejbContainer.getContext();
PropertyService service = (PropertyService) ctx.lookup("java:global/classes/PropertyServiceImpl");
assertNotNull(service.getStringValue("abc"));
I want to share with you my solution. According to your help I had a look at the Arquillian documentation and finally I was able to create a proper integration test.
My test uses GlassFish embedded EE container with HSQL in-memory database.
test java class:
#RunWith(Arquillian.class)
public class PropertyServiceImplTest {
#EJB
private PropertyService propertyService;
#Deployment
public static JavaArchive createTestArchive() {
return ShrinkWrap.create(JavaArchive.class, "test.jar").
.addPackage(Property.class.getPackage())
.addPackage(PropertyService.class.getPackage())
//.addPackage(PropertyServiceImpl.class.getPackage())
addAsResource("META-INF/persistence.xml");
}
#Test
public void testGetStringValue() {
assertNotNull(propertyService);
Property property = new Property();
property.setKey("aaa");
property.setValue("5");
propertyService.setStringValue(property);
assertEquals(propertyService.getStringValue("aaa"), "5");
}
}
persistence.xml
Valid values for target-database: eclipselink doc
<persistence-unit name="example" transaction-type="JTA">
<jta-data-source>jdbc/my-ds</jta-data-source>
<class>a.b.domain.Property</class>
<properties>
<property name="eclipselink.target-database" value="HSQL"/>
<property name="eclipselink.ddl-generation" value="drop-and-create-tables"/>
<property name="eclipselink.logging.level" value="ALL"/>
</properties>
</persistence-unit>
arquillian.xml
How to eliminate the crazy "Potential problem found" warning message? DatatypeFactory properties has to be set.
WARNING: Potential problem found: The configured data type factory
'class org.dbunit.dataset.datatype.DefaultDataTypeFactory' might cause problems with the current database
'HSQL Database Engine' (e.g. some datatypes may not be supported properly). In rare cases you might see this
message because the list of supported database products is incomplete (list=[derby]). If so please request a
java-class update via the forums.If you are using your own IDataTypeFactory extending DefaultDataTypeFactory,
ensure that you override getValidDbProducts() to specify the supported database products.
DBUnit specific settings: jboss documentation
DataType factories: dbunit documentation
<engine>
<property name="deploymentExportPath">target/arquillian</property>
</engine>
<container default="true" qualifier="glassfish">
<configuration>
<property name="resourcesXml">myproject/src/test/resources/glassfish-resources.xml</property>
</configuration>
</container>
<extension qualifier="persistence">
<property name="defaultDataSource">jdbc/my-ds</property>
</extension>
<extension qualifier="persistence-dbunit">
<property name="datatypeFactory">org.dbunit.ext.hsqldb.HsqldbDataTypeFactory</property>
</extension>
glassfish-resources.xml
<resources>
<jdbc-connection-pool name="jdbc/my-pool"
res-type="javax.sql.DataSource"
datasource-classname="org.hsqldb.jdbc.JDBCDataSource">
<property name="PortNumber" value="9001" />
<property name="serverName" value="localhost" />
<property name="URL" value="jdbc:hsqldb:mem:arquillian" />
<property name="user" value="sa" />
<property name="password" value="" />
</jdbc-connection-pool>
<jdbc-resource jndi-name="jdbc/my-ds" pool-name="jdbc/my-pool" />
</resources>
Project structure:
src/test/java/a.b.PropertyServiceImplTest.java
src/test/resources/META-INF/persistence.xml
src/test/resources/arquillian.xml
src/test/resources/glassfish-resources.xml
I am so disappointed after I spent 3-4 days with arquillian.
I read documentation about this testing framework and I have created a nice environment with it. There were created beautiful xml files with placeholders for prod and test environments and pom files are done. Everything works fine with my simple ejb and entity java classes.
Today I have been started working on my real java 8 application. After a while something had happened because my tests have failed. When I removed lambda expression from my code then my tests worked fine again.
So when I use lambda expression then the injected ejb is always null:
#EJB
private ConfigurationService configurationService;
The last release of GlassFish Managed 3.1 Container is 1.0.0.CR4, release date: 2013-04-29. It is quite old :(
Arquillian GlassFish module is totally useless :(
I had that problem too, but you can fix it using Payara's embedded server.
<dependency>
<groupId>fish.payara.extras</groupId>
<artifactId>payara-embedded-all</artifactId>
<version>4.1.1.162</version>
<scope>test</scope>
</dependency>

Is it possible to control set-jaxb-validation-event-handler programmatically?

In a CXF SOAP webservice, I'm using the following annotations to disable the xsd validation:
#EndpointProperties({
#EndpointProperty(key = "set-jaxb-validation-event-handler", value = "false")
})
I would like the validation to controlled at runtime (enable/disable it, based on the value of a setting retrieved from a database). My question is: is it possible to disable/enable this handler at runtime? Maybe by writing a custom event handler and not using this property at all?
Thanks.
Edit: an option would be not to disable the validation with set-jaxb-validation-handler, and rather subclass ValidationEventHandler. As explained here, I would then check the database setting in handleEvent and return according to its value.
But there are still a few downsides with this approach: first, this webservice is configured with annotations, and I can't seem to find a way to apply a ValidationEventHandler with annotations (same question as: How to set custom ValidationEventHandler on JAXB unmarshaller when using annotations).
Secondly, it means that the validation will be performed even if I don't need it; I would then lose any performance benefit.
It doesn't in fact exactly suit my needs, so I'm still open to any suggestion.
Yes, it is possible.
MyService service = new MyService();
MyServiceInterface port = service.getMyServicePort();
BindingProvider bindingProvider = (BindingProvider) port;
bindingProvider.getRequestContext().put(
"set-jaxb-validation-event-handler", Boolean.FALSE);
I finally found a working solution.
As I'm running CXF on JBoss EAP 6.0, I added the following configuration to the webservices subsytem in standalone.xml:
<subsystem xmlns="urn:jboss:domain:webservices:1.2">
<!-- ... -->
<endpoint-config name="myconfig">
<property name="set-jaxb-validation-event-handler" value="false"/>
</endpoint-config>
<!-- ...-->
</subsystem>
And the following annotation to the SEI implementation:
#org.jboss.ws.api.annotation.EndpointConfig(configName = "myconfig")
This is the related Maven dependency:
<dependency>
<groupId>org.jboss.ws</groupId>
<artifactId>jbossws-api</artifactId>
<version>1.0.1.Final</version>
<scope>provided</scope>
</dependency>
We still need a restart of the server if we want to change the property value, but it's a lesser evil.
For the people trying to configure that on the bus level, the following worked for me:
<cxf:bus id="soapClientCxfBus" bus="soapClientCxfBus" >
<cxf:properties>
<entry key="set-jaxb-validation-event-handler" value="false" />
</cxf:properties>
</cxf:bus>

Spring 4 / Groovy DSL - autowiring

How do I enable autowiring when using the Groovy DSL in Spring 4?
if my config.groovy file currently looks like this:
beans {
mongoClient(com.mongodb.MongoClient)
hello(org.abiri.HelloImpl) {
mongoClient = mongoClient
}
}
Previously in XML configuration, we could have done this:
<bean id="hello" class="org.abiri.HelloImpl" autowire="byType" />
And we could even enable that for the whole file:
<beans default-autowire="byType" />
What is the equivalent of those XML snippets in the new Groovy DSL, i.e what do I need to do in order for the mongoClient to be autowired to hello ?
You need to use
hello(org.abiri.HelloImpl) { bean ->
bean.autowire = "byType"
}
The configuration closure is passed a parameter that you can use to configure things that would be attributes on the bean element in an XML configuration. In addition to autowire this includes scope, initMethod and destroyMethod.

Spring #Value annotations don't work, returning null

I have the following class:
#Component
public class MyClass {
#Value("${main.url}") private String mainUrl;
the following XML context:
<context:annotation-config/>
<context:component-scan base-package="mypackage"/>
<context:property-placeholder file-encoding="UTF-8" location="classpath:/app.properties" ignore-unresolvable="true"/>
and prop file:
main.url=veryniceurl.com
Injection doesn't work, it is always null.
I read a lot of similar examples and I thought that everything is ok but it isn't. Can anyone tell me if I forgot about something? I'm working with Mule ESB.
#Value doesn't seem to work with Mule. Instead you need to wire it up through the Mule XML, where I assume you are loading your component as a Spring Bean:
<spring:bean id="MyClass" class="com.example.MyClass">
<spring:property name="mainUrl" value="${main.url}"/>
</spring:bean>
Give an id to your properties and use this syntax :
#Value("#{jetProperties['jetBean.name']}")
<!-- define the properties file to use -->
<util:properties id="jetProperties" location="classpath:/jet.properties" />
From http://chrislovecnm.com/2010/03/08/spring-3-java-based-configuration-with-value/
Did you add the context placeholder in the dispatcher-servlet.xml ? As per here, Spring #Value annotation in #Controller class not evaluating to value inside properties file they seem to have solved it by adding it there instead of the application context

Configurable values to MDB annotations

I'm trying to use this method for receiving mail in our EJB3 app. In short, that means creating an MDB with the following annotations:
#MessageDriven(activationConfig = { #ActivationConfigProperty(propertyName = "mailServer", propertyValue = "imap.company.com"),
#ActivationConfigProperty(propertyName = "mailFolder", propertyValue = "INBOX"),
#ActivationConfigProperty(propertyName = "storeProtocol", propertyValue = "imap"),
#ActivationConfigProperty(propertyName = "debug", propertyValue = "false"),
#ActivationConfigProperty(propertyName = "userName", propertyValue = "username"),
#ActivationConfigProperty(propertyName = "password", propertyValue = "pass") })
#ResourceAdapter("mail-ra.rar")
#Name("mailMessageBean")
public class MailMessageBean implements MailListener {
public void onMessage(final Message msg) {
...snip...
}
}
I have this working, but the situation is less than ideal: The hostname, username and password are hardcoded. Short of using ant and build.properties to replace those values before compilation, I don't know how to externalize them.
It would be ideal to use an MBean, but I have no idea how to get the values from the MBean to the MDB configuration.
How should I do this?
You can externalise the annotations into the ejb-jar.xml that you deploy in the META-INF of your jar file as follows:
<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar version="3.0">
<enterprise-beans>
<message-driven>
<ejb-name>YourMDB</ejb-name>
<ejb-class>MailMessageBean</ejb-class>
<activation-config>
<activation-config-property>
<activation-config-property-name>username</activation-config-property-name>
<activation-config-property-value>${mdb.user.name}</activation-config-property-value>
</activation-config-property>
...
...
</activation-config>
</message-driven>
</enterprise-beans>
Then you can set the mdb.user.name value as a system property as part of the command line to your application server using -Dmdb.user.name=theUserName and it will magically get picked up by the mdb.
Hope that helps.
As of JBoss AS 5.1 at least, you can use AOP to configure the #ActivationConfigProperties. I discovered this by looking at the examples that jboss provides here. This is useful if you do not want your username and passwords available to the entire container in a systems property, or if you are like me and never, I repeat NEVER, want to deploy an artifact with a username/password in it. Any how, here is the jist...
Annotate the mdb like this...
...
#MessageDriven
#AspectDomain("TestMDBean")
public class TestMDBean implements MessageListener {
...
Then add a ${whatever}-aop.xml to the deploy dir with internals like below. I left the original comments in there in case Jaikiran does make the changes mentioned...
Note: the annotation must be on one
line only.
<?xml version="1.0" encoding="UTF-8"?>
<aop xmlns="urn:jboss:aop-beans:1.0">
<!-- TODO: Jaikiran - These interceptor declarations need not be here since they
are already declared through the ejb3-interceptors-aop.xml. Duplicating them leads to
deployment errors. However, if this custom-ejb3-interceptors-aop.xml needs to be
independent, then we must find a better way of declaring these. Right now, commenting these
out, can be looked at later. -->
<!--
<interceptor class="org.jboss.ejb3.AllowedOperationsInterceptor" scope="PER_VM"/>
<interceptor class="org.jboss.ejb3.entity.TransactionScopedEntityManagerInterceptor" scope="PER_VM"/>
<interceptor factory="org.jboss.ejb3.security.RunAsSecurityInterceptorFactory" scope="PER_CLASS"/>
<interceptor class="org.jboss.ejb3.stateless.StatelessInstanceInterceptor" scope="PER_VM"/>
<interceptor factory="org.jboss.ejb3.interceptor.EJB3InterceptorsFactory" scope="PER_CLASS_JOINPOINT"/>
<interceptor factory="org.jboss.aspects.tx.TxInterceptorFactory" scope="PER_CLASS_JOINPOINT"/>
-->
<domain name="TestMDBean" extends="Message Driven Bean" inheritBindings="true">
<annotation expr="!class(#org.jboss.ejb3.annotation.DefaultActivationSpecs)">
#org.jboss.ejb3.annotation.DefaultActivationSpecs (value={#javax.ejb.ActivationConfigProperty(propertyName="destinationType", propertyValue="javax.jms.Queue"), #javax.ejb.ActivationConfigProperty(propertyName="destination", propertyValue="queue/MyQueue"), #javax.ejb.ActivationConfigProperty(propertyName="user", propertyValue="testusr"), #javax.ejb.ActivationConfigProperty(propertyName="password", propertyValue="testpwd")})
</annotation>
</domain>
</aop>

Categories