Websphere 8.5 CDI triggers Observer multiple Times - cdi

I am using Websphere 8.5 and have a problem with a simple CDI event.
The emitting EJB is stateless and emits the event once. I tested it with a breakpoint in the pojos constructor so there are no other places where this event gets fired.
I already checked my imports, but I used the correct imports. Does anyone spot my error or am I just running in another bug? The CDI implementation seems to be pretty outdated.
I tested without the TransactionAttribute and outside the debug mode too. Does not change anything.
Thanks in advance!
m
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.enterprise.event.Event;
import javax.enterprise.event.Observes;
import javax.enterprise.event.TransactionPhase;
#Stateless
public class CreateService {
// Injecting the emitter
#Inject
private Event<CreateEvent> createEmitter;
public void create(String id) {
// fire the create event
CreateEvent event = new CreateEvent(id);
createEmitter.fire(event);
}
#TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public void postCreate(#Observes(during = TransactionPhase.AFTER_SUCCESS) CreateEvent event) {
System.out.println("Received " + event.getId());
}
}
Event producer and consumer is in the same EJB.
public class CreateEvent {
private String id;
public CreateEvent() {
}
public CreateEvent(String id) {
super();
this.id = id;
}
public String id() {
return id;
}
public void setId(String id) {
this.id = id;
}
#Override
public String toString() {
return "CreateEvent ["
+ (id != null ? "id=" + id
: "") + "]";
}
}
[10/22/14 9:58:53:231 CEST] 000000a2 SystemOut O Received A622665
[10/22/14 9:58:53:231 CEST] 000000a2 SystemOut O Received A622665
[10/22/14 9:58:53:231 CEST] 000000a2 SystemOut O Received A622665
[10/22/14 9:58:53:246 CEST] 000000a2 SystemOut O Received A622665
[10/22/14 9:58:53:246 CEST] 000000a2 SystemOut O Received A622665

Related

Spring Boot - Multithreading on same Object

I work on project that manages contacts database with CRUD options
But I don't know how to handle multithreading.
I use Java 8 and spring-boot 2.0.4 RELEASE
UPDATE -> Code instead of images
This is Controller :
#RestController
#RequestMapping("/api")
#CrossOrigin(origins = "http://localhost:4200", allowedHeaders="*")
public class ContactController {
#Autowired
private ContactService contactService;
/*--- Toute la liste ---*/
#GetMapping("/contact")
public List<ContactDTO> getDestinataires() {
return contactService.getContacts();
}
/* ------------------------- CRUD ----------------------- */
// Creation contact
#PostMapping("/contact/create")
public boolean create(#Valid #RequestBody ContactDTO contact) {
return contactService.create(contact);
}
// infos d'un contact
#GetMapping("/contact/{id}")
public ContactDTO read(#PathVariable Integer id) {
return contactService.getContact(id);
}
// Maj contact
#PutMapping("/contact/update")
public boolean update(#RequestBody ContactDTO contact) {
return contactService.update(contact);
}
// Maj contact
#DeleteMapping("/contact/delete/{id}")
public boolean delete(#PathVariable Integer id) {
return contactService.delete(id);
}
}
The service (with #Service annotation) retrieves ContactDTO Object sent by the front and set Contact object. It works with CoreServices (without Spring annotations) java class.
This is it:
#Service
public class ContactService extends CoreServices{
private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(ContactService.class);
public boolean update(ContactDTO contactDTOFront) {
logger.info("ContactService - start update method");
try {
// contrĂ´le si contact existe
setContact(getContactRepo().findByIdaicontact(contactDTOFront.getIdaicontact()));
if (getContact() == null) {
return false;
}
// alimentation du bean hibernate par le bean dto.
contactDTOFront.alimBean(this);
// maj de la bdd
if (getContactRepo().save(getContact()) == null) {
return false;
}
} catch (Exception ure) {
logger.error("ContactService - Error update method: " + ExceptionUtils.getStackTrace(ure));
return false;
}
return true;
}
All Beans (DTO and entity) are managed in CoreServices Class :
public class CoreServices {
#Autowired
private ContactRepository contactRepo;
// Bean Contact
Contact contact = new Contact();
ContactDTO contactDTO = new ContactDTO();
List<ContactDTO> contactDTOList = new ArrayList<ContactDTO>();
List<Contact> contactList = new ArrayList<Contact>();
public ContactRepository getContactRepo() {
return contactRepo;
}
public Contact getContact() {
return contact;
}
public void setContact(Contact contact) {
this.contact = contact;
}
public ContactDTO getContactDTO() {
return contactDTO;
}
public void setContactDTO(ContactDTO contactDTO) {
this.contactDTO = contactDTO;
}
public List<ContactDTO> getContactDTOList() {
return contactDTOList;
}
public void setContactDTOList(List<ContactDTO> contactDTOList) {
this.contactDTOList = contactDTOList;
}
public List<Contact> getContactList() {
return contactList;
}
public void setContactList(List<Contact> contactList) {
this.contactList = contactList;
}
To set Contact bean , I use "alimBean" method defined in DTO OBject. This method is called in my service.
public void alimBean(CoreServices service) throws Exception {
logger.info("ContactDTO - start alimBean method");
service.getContact().setIdaicontact(this.getIdaicontact());
service.getContact().setIdentifiant(this.getIdentifiant());
service.getContact().setIdaisite(this.getIdaisite());
service.getContact().setIdaitype(this.getIdaitype());
service.getContact().setNom(this.getNom());
service.getContact().setPrenom(this.getPrenom());
service.getContact().setEmail(this.getEmail());
service.getContact().setComment(this.getComment());
service.getContact().setStatus(this.getStatus());
service.getContact().setLocked(this.getLocked());
service.getContact().setUserlock(this.getUserlock());
service.getContact().setCreuser(this.getCreuser());
service.getContact().setUpduser(this.getUpduser());
// Gestion des dates STRING -> DATE
logger.info("ContactDTO - end alimBean method");
}
Now, assuming two update requests are handled in same time. How does it work ?
I read some Tuto about "synchronization" but they are a little confused for me. I don't know if it's the best way and I don't want to break all the code except if it's the only solution to handle this multithreading case
What can I add to this code to be sure the second request will not set Contact object before the first request ended.
You should synchronize only update and delete actions with for example id if it's unique. You can use my library but it's in alfa version but it is tested and works good.
You must add the dependency:
<dependency>
<groupId>com.jsunsoft.util</groupId>
<artifactId>concurrent</artifactId>
<version>0.0.1-alpha2</version>
</dependency>
and write code like this
import com.jsunsoft.util.concurrent.locks.Lock;
public class ContactService extends CoreServices {
private final Lock contactLock = new StripedLock(minimumNumberOfStripes, lockTimeSec);
public boolean update(ContactDTO contactDTOFront) {
logger.info("ContactService - start update method");
try {
updateSynched(contactDTOFront);
} catch (Exception ure) {
logger.error("Co: " + ExceptionUtils.getStackTrace(ure));
return false;
}
return true;
}
//you can add the method updateSynched
private void updateSynched(ContactDTO contactDTOFront) throws Exception {
contactLock.lock(contactDTOFront.getId(), () -> {
setContact(getContactRepo().findByIdaicontact(contactDTOFront.getIdaicontact()));
if (getContact() == null) {
throw new Exception("msg");
}
// alimentation du bean hibernate par le bean dto.
contactDTOFront.alimBean(this);
// maj de la bdd
if (getContactRepo().save(getContact()) == null) {
throw new Exception("msg");
}
});
}
}
Note: In that library I used the guava striped lock if you want you can use directly the guava API.

Using Primefaces EventBus on Glassfish Embedded with JUnit

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");
}

Problems migrate from Seam3 to DeltaSpike

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})

How to thread-safely share an attribute between the beforePhase() and the afterPhase() methods of a PhaseListener?

I need to share an attribute between the beforePhase() and the afterPhase() methods of my PhaseListener, for a same JSF request.
Is the following snippet thread-safe?
public class MyPhaseListener implements PhaseListener {
private MyObject o = null;
#Override
public void beforePhase(PhaseEvent event) {
if (condition) {
o = new MyObject();
}
}
#Override
public void afterPhase(PhaseEvent event) {
if (o != null) {
o.process();
o = null;
}
}
#Override
public PhaseId getPhaseId() {
return PhaseId.RESTORE_VIEW;
}
}
If not, what are other solutions?
This is definitely not threadsafe. There's only one phase listener instance applicationwide which is shared across multiple requests. Basically, a phase listener is like an #ApplicationScoped managed bean.
Just set it as a context attribute.
public class MyPhaseListener implements PhaseListener {
#Override
public void beforePhase(PhaseEvent event) {
if (condition) {
event.getFacesContext().setAttribute("o", new MyObject());
}
}
#Override
public void afterPhase(PhaseEvent event) {
MyObject o = (MyObject) event.getFacesContext().getAttribute("o");
if (o != null) {
o.process();
}
}
#Override
public PhaseId getPhaseId() {
return PhaseId.RESTORE_VIEW;
}
}
You could use ThreadLocal for this, but it tends to have issues in environments having different classloaders, to name it: memory leak. Be sure to check for that in the given environment...
Also, you should make it sure that if the processing can be interrupted (e.g. exception...) between the beforePhase() and afterPhase() methods, the ThreadLocal should be handled appropriately...
This is what it would look like:
public class MyPhaseListener implements PhaseListener {
//if null is a valid value, no initial setting is needed
private ThreadLocal<Object> myStateObject = new ThreadLocal<Object> ();
#Override
public void beforePhase(PhaseEvent event) {
//might be needed, to guarrantee no residue from an aborted processing is in there
myState.set(null);
if (condition) {
myState.set(<Object representing the state>);
}
}
#Override
public void afterPhase(PhaseEvent event) {
try {
Object stateObject = myState.get();
if (stateObejct!=null) {
//do what you have to
}
} finally {
//to be sure
myState.remove();
}
}
}
In this article the author uses ThreadLocal too...
Also, this article is also a great eye-opener, explaining why not to share mutable instance-level information:
One thing to remember though, is that PhaseListener instances are application-wide Singletons that are referenced by the JSF Lifecycle, which itself is an application-wide Singleton.
EDIT just saw Boolean got updated to Object, adjusted example

How to persist Entity in separate thread with JPA on J2EE App server?

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.

Resources