I'm having an issue with JPA in multithreads application. I'm using JPA proxy authentication to access the database. Everything runs fine in session beans but when in java thread run() method, I cannot use #EJB so I use Initialcontext to look up the bean. When the program executes, I'm getting invalid username/password; logon denied.
#Stateless
public class MyDAO{
#PersistenceContext(name="myPU")
private EntityManager em;
public MyEntity getData(String id){
return em.find(MyEntity.class, id);
}
#AroundInvoke
public Object setSessionUser(InvocationContext ctx){
if(ctx.getTarget() instanceof MyDAO){
Map properties = new HasMap();
properties.put("eclipselink.oracle.proxy-type", OracleConnection.PROXYTYPE_USER_NAME);
properties.put(OracleConnection.PROXY_USER_NAME, "myusername");
properties.put("eclipselink.jdbc.exclusive-connection.mode", "Always");
properties.put("eclipselink.jdbc.exclusive-connection.is-lazy", "false");
((org.eclipse.persistence.internal.jpa.EntityManagerImpl)em.getDelegate()).setProperties(properties);
}
return ctx.proceed();
}
}
inside run();
#Override
public void run(){
...
MyDAO dao = (MyDAO) new InitialContext().lookup("java:module/...");
EntityObject obj = dao.getData("123456");
...
}
Related
I'm looking to unit test my Java EE code by using the embedded Glassfish container and JUnit. On its own this works ok, but I've discovered that when the Primefaces EventBusFactory is called it fails with a Null Pointer Exception. I'm not sure how to resolve that, or if I should be testing this in another way.
Here is my test:
public class CreateOrderBookTest {
private RequestBean requestBean;
private EJBContainer ejbContainer;
private Context ctx;
#Before
public void setUp() throws Exception {
ejbContainer = EJBContainer.createEJBContainer();
System.out.println("Opening the container" );
ctx = ejbContainer.getContext();
}
#After
public void tearDown() throws Exception {
ejbContainer.close();
System.out.println("Closing the container" );
}
#Test
public void test() throws NamingException {
RequestBean requestBean = (RequestBean) ctx.lookup("java:global/classes/RequestBean");
assertNotNull(requestBean);
requestBean.createBidOrder(50, 1.0, "CLCS", "00001");
}
}
Here is the function I'm testing in a RequestScoped Stateful bean:
public void createBidOrder(Integer amount, Double price, String memberId, String traderId)
{
BidOrder order = new BidOrder(amount,price, em.find(Member.class, memberId),
em.find(Trader.class, new Integer(traderId)));
logger.log(Level.INFO, "RequestBean.createBidOrder Created new order with bidprice {0}",
new Object[]{price});
em.persist(order);
EventBus eventBus = EventBusFactory.getDefault().eventBus();
eventBus.publish("/notify", "order");
}
I'm just testing to migrate from Seam3 to DeltaSpike, everything is ok if there is only one EntityManager in a bean, but there will be a error if add other EntityManager(other datasource):
JBAS010152: APPLICATION ERROR: transaction still active in request with status 0
the error project:
https://github.com/yuanqixun/hellodeltaspike
run this project environment:
wildfly 8.2.0.Final
H2 datasource
MySql datasource
The EntityManagerProducer code:
#ApplicationScoped
public class EntityManagerProducer {
#PersistenceUnit(unitName = "hellodeltaspike")
EntityManagerFactory emf;
#PersistenceUnit(unitName = "hellodeltaspike2")
EntityManagerFactory mysqlemf;
#Produces
#ConversationScoped
EntityManager createEntityManager(){
return this.emf.createEntityManager();
}
#Produces
#MySqlEm
#ConversationScoped
EntityManager createMysqlEntityManager(){
return this.mysqlemf.createEntityManager();
}
}
The Action code:
#ConversationScoped
#Named
public class PersonAction implements Serializable{
#Inject
EntityManager em;
#Inject
#MySqlEm
EntityManager mysqlEm;
Person person;
List<Person> personList;
#PostConstruct
void afterCreate(){
person = new Person();
personList = queryPersonList();
}
private List<Person> queryPersonList() {
String jql = "select o from Person o ";
List<Person> result = em.createQuery(jql,Person.class).getResultList();
if(result == null)
return new ArrayList<Person>();
return result;
}
#Transactional
public void btnDoSave(ActionEvent event){
try {
if(StringUtils.isEmpty(person.getUuid())){
em.persist(person);
}else{
em.merge(person);
}
em.flush();
String msg = "Saved:"+person.getName();
FacesContext.getCurrentInstance().addMessage(null,new FacesMessage(FacesMessage.SEVERITY_INFO,msg,null));
person = new Person();
personList = queryPersonList();
} catch (Exception e) {
e.printStackTrace();
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, e.getMessage(), null));
}
}
...getter and setter
}
and there will be error:
ERROR [org.jboss.as.txn] (default task-6) JBAS010152: APPLICATION ERROR: transaction still active in request with status 0
Modify the method's annotation,add the special qualifier of the right EntityManager, so the problem will be solved. But also has another problem, how to support multiple entityManager's transaction in one method?
#Transactional(qualifier = {H2Em.class})
Still learning JSF and Java and having trouble understanding how to access a session bean property.
I have a LoggedUser session bean which sets the user that is logged in(using the login method).
#ManagedBean(name="loggedUser")
#Stateless
#LocalBean
#SessionScoped
public class LoggedUser {
#EJB
UserEJB userEJB;
#PersistenceContext
private EntityManager em;
private UserEntity loggedUser;
private String loginUserName;
private String loginPassword;
public LoggedUser() {}
public UserEntity getLoggedUser() {
return loggedUser;
}
public void setLoggedUser(UserEntity loggedUser) {
this.loggedUser = loggedUser;
}
public String authenticate() {
if (loggedUser == null) {
return "login.xhtml";
} else {
return "";
}
}
public String login() {
if (userEJB.validateLogin(loginUserName, loginPassword)) {
setLoggedUser(userEJB.fetchUser(loginUserName));
return "index.xhtml";
}
return "";
}
public String getLoginUserName() {
return loginUserName;
}
public void setLoginUserName(String loginUserName) {
this.loginUserName = loginUserName;
}
public String getLoginPassword() {
return loginPassword;
}
public void setLoginPassword(String loginPassword) {
this.loginPassword = loginPassword;
}
}
I want to be able to view the logged user from other areas in the application. I think I am injecting it incorrectly because loggedUser is always null when I am in a different bean for example something like..
#Stateless
#LocalBean
public class HistoryEJB {
#PersistenceContext
EntityManager em;
#ManagedProperty(value = "#{loggedUser}")
private LoggedUser loggedUser;
public LoggedUser getLoggedUser() {
return loggedUser;
}
public void setLoggedUser(LoggedUser loggedUser) {
this.loggedUser = loggedUser;
}
public void testLoggedUser() {
loggedUser.getLoggedUser();
// Just an example but would be null here - why?
}
}
How can I access this property from other areas in my application? Thanks for any help.
You can't use #ManagedProperty in an EJB and you shouldn't inject a view component into a business-tier component, period. #ManagedProperty is strictly web-tier stuff and is able to inject only and into web-tier, JSF components.
Your EJB ought to have a method that accepts a LoggedUser. This way, you can then pass your logged-in user to the EJB (which is the proper flow of data in a web application). What you have now is just turning best practice on its head.
So
Add a provideLoggedUser(LoggedUser loggedUser) method to your EJB
Call that method on your instance of UserEJB from within your managed bean
Rule of Thumb: Your EJB should not be aware of the web application
It seems you are missing the setter and getter for loggedUser. In principe it is there but it is convention to name it as follows
setProperty
and
setProperty
for a field named property. Note the capital first letter of the field name in the setter and getter!
I'm trying to intercept the method persist and update of javax.persistence.EntityManager in a Seam 3 project.
In a previous version (Seam 2) of the micro-framework I'm trying to make, I did this using an implementation of org.hibernate.Interceptor and declaring it in the persistence.xml.
But I want something more "CDI-like" now we are in a JEE6 environment.
I want that just before entering in a EntityManager.persist call, an event #BeforeTrackablePersist is thrown. The same way, I want an event #BeforeTrackableUpdate to be thrown before entering in a EntityManager.merge call. Trackable is an interface which some of my Entitys could implement in order to be intercepted before persist or merge.
I'm using Seam 3 (3.1.0.Beta3) Extended Persistence Manager :
public class EntityManagerHandler {
#SuppressWarnings("unused")
#ExtensionManaged
#Produces
#PersistenceUnit
private EntityManagerFactory entityManagerFactory;
}
So I've made a javax.enterprise.inject.spi.Extension, and tryied many ways to do that :
public class TrackableExtension implements Extension {
#Inject #BeforeTrackablePersisted
private Event<Trackable> beforeTrackablePersistedEvent;
#Inject #BeforeTrackableMerged
private Event<Trackable> beforeTrackableMergedEvent;
#SuppressWarnings("unchecked")
public void processEntityManagerTarget(#Observes final ProcessInjectionTarget<EntityManager> event) {
final InjectionTarget<EntityManager> injectionTarget = event.getInjectionTarget();
final InjectionTarget<EntityManager> injectionTargetProxy = (InjectionTarget<EntityManager>) Proxy.newProxyInstance(event.getClass().getClassLoader(), new Class[] {InjectionTarget.class}, new InvocationHandler() {
#Override
public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
if ("produce".equals(method.getName())) {
final CreationalContext<EntityManager> ctx = (CreationalContext<EntityManager>) args[0];
final EntityManager entityManager = decorateEntityManager(injectionTarget, ctx);
return entityManager;
} else {
return method.invoke(injectionTarget, args);
}
}
});
event.setInjectionTarget(injectionTargetProxy);
}
public void processEntityManagerType(#Observes final ProcessAnnotatedType<EntityManager> event) {
final AnnotatedType<EntityManager> type = event.getAnnotatedType();
final AnnotatedTypeBuilder<EntityManager> builder = new AnnotatedTypeBuilder<EntityManager>().readFromType(type);
for (final AnnotatedMethod<? super EntityManager> method : type.getMethods()) {
final String name = method.getJavaMember().getName();
if (StringUtils.equals(name, "persist") || StringUtils.equals(name, "merge")) {
builder.addToMethod(method, TrackableInterceptorBindingLiteral.INSTANCE);
}
}
event.setAnnotatedType(builder.create());
}
public void processEntityManagerBean(#Observes final ProcessBean<EntityManager> event) {
final AnnotatedType<EntityManager> annotatedType = (AnnotatedType<EntityManager>)event.getAnnotated();
// not even called
}
public void processEntityManager(#Observes final ProcessProducer<?, EntityManager> processProducer) {
processProducer.setProducer(decorate(processProducer.getProducer()));
}
private Producer<EntityManager> decorate(final Producer<EntityManager> producer) {
return new Producer<EntityManager>() {
#Override
public EntityManager produce(final CreationalContext<EntityManager> ctx) {
return decorateEntityManager(producer, ctx);
}
#Override
public Set<InjectionPoint> getInjectionPoints() {
return producer.getInjectionPoints();
}
#Override
public void dispose(final EntityManager instance) {
producer.dispose(instance);
}
};
}
private EntityManager decorateEntityManager(final Producer<EntityManager> producer, final CreationalContext<EntityManager> ctx) {
final EntityManager entityManager = producer.produce(ctx);
return (EntityManager) Proxy.newProxyInstance(entityManager.getClass().getClassLoader(), new Class[] {EntityManager.class}, new InvocationHandler() {
#Override
public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
final String methodName = method.getName();
if (StringUtils.equals(methodName, "persist")) {
fireEventIfTrackable(beforeTrackablePersistedEvent, args[0]);
} else if (StringUtils.equals(methodName, "merge")) {
fireEventIfTrackable(beforeTrackableMergedEvent, args[0]);
}
return method.invoke(entityManager, args);
}
private void fireEventIfTrackable(final Event<Trackable> event, final Object entity) {
if (entity instanceof Trackable) {
event.fire(Reflections.<Trackable>cast(entity));
}
}
});
}
}
In all those observer methods, only the second one (processEntityManagerType(#Observes ProcessAnnotatedType<EntityManager>)) is called ! And even with that binding addition to methods persist and merge, my Interceptor is never called (I've of course enabled it with the correct lines in beans.xml, and enabled my extension with the services/javax.enterprise.inject.spi.Extension file).
Something I've thought simple with CDI seems to be actually really hard at last... or perhaps Seam 3 does something which prevent this code from executing correctly...
Does someone know how to handle that ?
I think you're making this a little harder than what it needs to be. Firstly though, JPA and CDI integration isn't very good in Java EE 6, we're very much hoping that changes in Java EE 7 and JPA 2.1.
What you'll want to do is create your own producer for the EntityManager that will delegate to an actual instance of an EntityManager, but also fire your own events when you call the methods you're interested in. Take a look at the Seam Persistence source to see one way this can be done.
As finally my little patch for Seam Persistence was applied in SEAMPERSIST-75, it will be possible in theory to do that by extending org.jboss.seam.persistence.HibernatePersistenceProvider and override the method proxyEntityManager(EntityManager).
I have a chat application that needs to store messages to DB. But connection with DB is a little bit slow, therefore it delays response to chat client.
Is it possible to persist Message entity in separate thread? What I'm actually need in: reduce delay before send-recieve message on client.
I try to do it, but it doen't work.
Dao object:
#Stateless
public class MessagesDAO {
#PersistenceContext(type= PersistenceContextType.EXTENDED)
private EntityManager entityManager;
private PersistenceThread persistenceThread = new PersistenceThread();
//another methods
public void addMessage(Message message) {
Thread thread = new Thread(persistenceThread);
persistenceThread.setMessage(message);
thread.start();
}
private class PersistenceThread implements Runnable {
private Message message;
public void setMessage(Message message) {
this.message = message;
}
public void run() {
entityManager.persist(message);
}
}
}
Interface service that calls DAO to persist new message and then return it to clients:
#Stateless
#Path("/messages")
#Produces("application/xml")
#Consumes("application/xml")
public class MessagesServiceImpl {
#EJB
private MessagesDAO messagesDAO;
#POST
#Broadcast(resumeOnBroadcast = true)
public Message postMessage(Message message) {
messagesDAO.addMessage(message);
return message;
}
#GET
#Path("/wait")
#Suspend(outputComments = false)
public Message waitForLastMessage() {
return null;
}
//another methods
}
Thanks.
Give the #Asynchronous annotation a try:
#Stateless
public class MessagesDAO {
#PersistenceContext(type = PersistenceContextType.EXTENDED)
private EntityManager entityManager;
#Asynchronous
public void addMessage(Message message) {
entityManager.persist(message);
}
}
Just bear in mind that it requires EJB 3.1.