OpenJPA persistence between OSGi bundles - java

I have two OSGi bundles deployed on Apache Karaf container. Lets say they are A and B. The A bundle is the main bundle which contains all database entities and persistence logic. The B OSGi bundle is an application which uses methods from A to store some data into database. Also bundle B has CXF web service endpoint. The persistence is handled by OpenJPA.
Method in bundle A wraps the persist method of entity manager. In bundle B there is a method which takes an object as a parameter which is defined in bundle A and has the method to persist data. When I call that method in bundle B, all is ok, the data is persisted into database as expected.
The problem is that I want to update the an entity in B bundle's CXF endpoint implementation class which is exposed as a Spring bean and has OSGi reference to an object from bundle A which contains find statement to find the entity I need to update.
The entity is returned to me correctly when I invoke find method, but when I set some new value the transaction does not get committed and the data does not appears in the database.
As I know one of OpenJPA features is that when you call persist to an object, then later you can set some new data to it and the needed transactions are made to update that entity. It does not seem to be working in my case. I have tried to annotate CXF endpoint implementation class with org.springframework.transaction.annotation.Transactional annotation. But this is not working as well.
Maybe someone know where might be the problem? Do I need to write query which updates my entity in CXF endpoint?

In this case I suggest switching from spring to blueprint. If you take a look at aries blueprint (for example) which is used by Karaf you are able to retrieve for example DAOs from Bundle A, call a "changing method" from Bundle B and it'll persisted by the Transaction Manager attached to Bundle A.

Related

Using an EJB outside container

I am currently creating a J2EE application and there is a part of it that is running outside the container, using a ServletContextListener to launch it.
However I also need to access the database from this part.
I currently have an Entity and a Stateless Session bean to fetch use the EntityManager.
I tested multiple things ( EntityManagerFactory, Initial Context, EJBContainer ) but I didn't manage to make any of them work.
How do I need to do it ?
You do not need EJB, actually you cannot create Ejbs outside the container. You need JPA, an OR-mapper and JDBC.
These normally are correctly configured in your EJB-Container. Outside the container you have to do that yourself.
You have to define your dependencies right, so that the correct JDBC-Driver is available and the OR-Mapper (probably eclipselink or hibernate?)
After that, you need define a presistence.xml to define the Entities to be used and to define how the DBMS is accessed via JDBC.
If that all is correctly configured EntityManagerFactory is the correct way to create an EntityManger for the persistence-unit defined in persistence.xml.
There are many examples available on the net. e.g.:
https://examples.javacodegeeks.com/enterprise-java/jpa/java-persistence-xml-example/
should work, if you are using eclipselink.
https://docs.jboss.org/hibernate/orm/3.6/quickstart/en-US/html/hibernate-gsg-tutorial-jpa.html
in case of Hibernate.

Call Bundle Activator Before Injecting Entity Manager

I have a persistence bundle (has a Meta-Persistence), it also has an Activator class
when deployed into karaf, the container starts processing the persistence unit &mapping files etc, before calling the start method of the Activator
My question is : is there a way to alter this behavior ? having the container call the method first ?
Edit
The reason I need the activator to be called first:
I have some mapped entities that rely on jackson which itself relies on spring, what happens is, when hibernate is loading the entities, it arrives at a home-made class that blocks while no spring context is injected into it. So the bundle is forever on a starting state
So I though a possible solution would be to make use of the Activator to inject the spring context
Thank you
The container (or more precisely Aries JPA) must start processing the persistence unit before the bundle is started.
The reason is that Aries JPA needs to do load time weaving in some cases. This kind of weaving must be done before classes to be weaved are loaded the first time by any bundle. So the only safe time to do this is directly after the bundle is resolved.

Mybatis useGeneratedKeys Fails in EJB with Proxy

I am using Mybatis 3.3.0 and EJB 3.1 running in a Wildfly 8.2.1 App server.
I modified my EJB's to have a Remote Interface and Injected the interface into all my classes that require the functionality instead of the injecting the LocalBean implementation (as it was before).
This caused all my useGeneratedKeys configurations for my mapper file Insert statements to stop working. Now my ID fields remain Null after the Inserts have run successfullly.
How is it that this caused mybatis to not be able to populate the ID's into my POJOs.
It turns out that mybatis gets confused when your EJB's are proxied and it isn't able to put the generated ID back into the POJO.
To fix it you simply have to inject the EJB Annotated with #javax.ejb.LocalBeanimplementation directly into the class you want to use it in. This is instead of injecting the Interface annotated with #javax.ejb.Remote.
Additionally I tested the same implementation using Remote EJB's and found you still won't be able to get generated Keys back from mybatis if you inject the #javax.ejb.Remote Interface type. I haven't found a solution to getting the generated ID into the POJO when using remoting.

OSGi/Equinox, Declarative Service and Lazy Load

I'm attempting to use Declarative Services to create a service bundle that provides functionality to another bundle. However, I want my Service Provider bundle to not start until it is needed. Let me describe my conditions.
There are two bundles:
-com.example.serviceprovider
-com.example.serviceconsumer
The Service Provider bundle provides a services using Declarative Services as follows:
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" enabled="true" immediate="true" name="samplerunnable1">
<implementation class="com.example.serviceprovider.SampleRunnable"/>
<service>
<provide interface="java.lang.Runnable"/>
</service>
The Service Consumer references the provided services as follows:
<reference name="SampleRunnable"
interface="java.lang.Runnable"
bind="setRunnable"
unbind="unsetRunnable"
cardinality="1..n"
policy="dynamic"/>
When both of these bundles are "ACTIVE" on start up, the Service Consumer has no trouble communicating with the service declared by the Service Provider. The problem happens when I try and have the service provider start in a lazy fashion.
After the Service Provider is set to load lazy this is what I get in the OSGi console:
osgi> ss
"Framework is launched."
id State Bundle
15 STARTING com.example.serviceconsumer_1.0.0.X
16 RESOLVED com.example.serviceprovider_1.0.0.X
What I would expect to see, is that even though bundle 16 is only "RESOLVED" that it would have at least registered is service. But when I call the "bundle" command, it states "No registered services."
osgi> bundle 16
com.example.serviceprovider_1.0.0.X [17]
Id=17, Status=RESOLVED Data Root=C:\apache\apache-tomcat-.0.40\work\Catalina\localhost\examplesX\eclipse\configuration\org.eclipse.osgi\bundles\17\data
"No registered services."
No services in use.
No exported packages
Imported packages
org.osgi.framework; version="1.7.0"<org.eclipse.osgi_3.8.0.v20120529-1548 [0]>
No fragment bundles
Named class space
com.example.serivceprovider; bundle-version="1.0.0.X"[provided]
No required bundles
Maybe I've missed the fundamental concept of lazy loaded bundles and services registration. If a bundle is in a "RESOLVED" state, shouldn't it have all it's "wires" connected? (ie, has a classloader, resolved import and export dependencies and services registered.) If the Service Consumer tries to access the service shouldn't that bundle transition to the "ACTIVE" state? What piece am I missing here?
Bundles in the RESOLVED state cannot provide services, and they will be ignored by Declarative Services. You should in general start all bundles during launch time, even if you want lazy loading behaviour. The key is to make the activation of the bundles cheap (or free!), and only pay for initialization of components when they are required.
DS takes care of lazy activation by default already. There is nothing you need to enable or change for this to happen. Essentially DS publishes the service entry in the registry, but it does not actually instantiate your component (or even load its class) until some client tries to use the service.
Furthermore, because DS does not load the class until required, OSGi does not even need to create a ClassLoader for the bundle, so long as your bundle does not have a BundleActivator.
To reiterate, you should not seek to make your bundles stay in RESOLVED state. Such bundles can only export static code and resources, but they cannot "do" anything and they cannot participate in the service registry.
Declarative services were designed for this case. Starting a bundle means that's functionality should be available, it does not mean it actually uses resources. Only stop bundles when you don't want is function.
This question is a good example of trying to control too much. In a component oriented world programmers should use lazy initialisation as much as possible but they should never attempt to control the life cycle.

In Java, how to reload dynamically resources bundles in a web application?

We are using fmt:setBundle to load a resource bundle from a database (we extended the ResourceBundle class to do that).
When we modify a value in database, we have to reload the web server to display the new value on the web app.
Is there any simple way to use the new value without restarting the web server ?
(We do not want to always look up the value from database but we would like to invalidate the cache, for example by calling a special 'admin' URL)
EDIT : We are using JDK 1.4, so I would prefer a solution on that version. :)
If you're using JDK 1.6 you can use the callback methods getTimeToLive() and needsReload() in ResourceBundle.Control to control if the bundle cache needs to be loaded with new values from the database.
As others have pointed out in the comments, you might want to look into Spring - particularly the ReloadableResourceBundleMessageSource.
First you can create a class which extends from ReloadableResourceBundleMessageSource to expose its inner class protected method called getProperties. This method return a concurrent map from PropertiesHolder object. Second you should configure a bean of that extended class in you web configuration class. Now you able to use messageSource in your service or business layer. Here is the reference link Configure reloadable message source bundle

Categories