Good evening everybody,
I have a EJB class. This class has 2 attributes are EJB, with private access, and "injected" with EJB annotation #EJB. This class has no defined constructor.
I want to test this class by using Mockito.
I have 2 problems :
1) the 2 attributes are with private access
2) Even when i want to put a defined constructor with the 2 EJB attributes as parameters, it does not work in my TestNG class
In my TestNG class,
i only want instantiate my class of course,
and also her 2 EJB attributes as 2 mocks.
And i do not succeed.
Thank you very much,
Thomas
This is the class.
package fr.nomenclature.service;
#Stateless
#Local
#TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public class TraitementNomenclaturesImpl implements TraitementNomenclatures {
private static final Logger LOG = LoggerFactory.getLogger(TarificationFactureImpl.class);
#EJB(name = "AccesNomenclatures-interne-ebx")
private transient AccesNomenclatureEBX accesEbx;
#EJB(name = "AccesElementFacturation-interne-ebx")
private transient AccesElementFacturationEBX accesRefEbx;
/*
* (non-Javadoc)
*
* #see
* fr.atom.referentiel.sante.nomenclature.service.TraitementNomenclature#extraireNomenclaturesDesPrestations(java
* .util.List, java.util.Date, fr.atom.configuration.SoapContext)
*/
#Override
public ContenusNomenclatures extraireNomenclaturesDesPrestations(
final List<PrestationDeSante<? extends Identifiant>> pPrestations, final Date pDateTraitement,
final SoapContext pContext) {
.......
}
}
Related
I'm working on Business Object layer in Intershop 7 and trying to create custom business object A1PromotionBO with related business repository (extension).
I've already done Persistent Object layer (A1PromotionPO, Mgrs, EDL model, auto-generated classes, database..).
By following this Cookbook - Business Objects (https://support.intershop.com/kb/index.php/Display/27K270), i've
created package *.a1promotion.capi that contains:
- interface A1PromotionBO extends BusinessObject
- interface A1PromotionBORepository extends BusinessObjectRepository
- interface A1PromotionBORepositoryExtension extends BusinessObjectExtension<RepositoryBO>, A1PromotionBORepository
created package *.a1promotion.internal that contains:
- class ORMA1PromotionBOImpl extends AbstractExtensibleObjectBO<A1PromotionPO> implements A1PromotionBO
- class ORMA1PromotionBORepositoryImpl extends AbstractDomainRepositoryBOExtension implements A1PromotionBORepository, ObjectMapper<Object, A1PromotionBO>
- class A1PromotionBORepositoryExtensionFactory extends AbstractDomainRepositoryBOExtensionFactory
EXTENSION_ID = "A1PromotionBORepository" is defined both in interface A1PromotionBORepositoryExtension and class A1PromotionBORepositoryExtensionFactory.
And now pipelet that returns collection of A1PromotionBO fails on line when creating A1PromotionBORepository promotionBORepository:
public class GetPromotions extends Pipelet {
#Inject
private CurrentApplicationBOProvider applicationBOProvider;
/** The domain mgr. */
#Inject
private DomainMgr domainMgr;
#Override
public int execute(PipelineDictionary dict) throws PipeletExecutionException {
final ApplicationBO applicationBO = applicationBOProvider.get();
final A1PromotionBORepository promotionBORepository = applicationBO.getRepository(A1PromotionBORepositoryExtensionFactory.EXTENSION_ID);
final String promotionDomainName = dict.get("PromotionDomain");
final Domain promotionDomain = domainMgr.getDomainByName(promotionDomainName);
if (null == promotionDomain) {
throw new PipeletExecutionException("Mandatory input parameter 'ProductsDomain' not available in pipeline dictionary.");
}
final Collection<A1PromotionBO> promotions = (Collection<A1PromotionBO>)promotionBORepository.getAllPromotions();
dict.put("Promotions", promotions);
return PIPELET_NEXT;
}
}
Full stack track of exception :
Caused by: com.intershop.component.application.capi.ApplicationBOException: Can not find business object factory with extensionID A1PromotionBORepository in application ApplicationBO(Shop#A1-Site (app=a1Shop.Backoffice))
at com.intershop.component.application.internal.ApplicationBORepositoriesExtensionImpl.getRepository(ApplicationBORepositoriesExtensionImpl.java:49)
at com.intershop.component.application.internal.ApplicationBOImpl.getRepository(ApplicationBOImpl.java:222)
at hr.a1.bo.promotion.pipelet.GetPromotions.execute(GetPromotions.java:44)
at com.intershop.beehive.core.internal.pipeline.PipeletNode.executeNode(PipeletNode.java:346)
... 42 more
I've decided to use a request scoped container managed EntityManager and I've created a producer for that reason:
#RequestScoped
public class EntityManagerProducer {
#PersistenceContext(unitName = "PU", type = PersistenceContextType.TRANSACTION)
private EntityManager entityManager;
#Produces
public EntityManager getEntityManager() {
return entityManager;
}
}
I've got two EJB's that expose a remote client view:
#Remote
public interface EJB1 {
void createPerson(int id, String firstName, String lastName);
}
#Remote
public interface EJB2 {
void containsEntity(Person person);
}
#Stateless
public class EJB1Impl implements EJB1 {
#Inject
private EntityManager entityManager;
#EJB
private EJB2 ejb2;
#Override
public void createPerson(final int id, final String firstName, final String lastName) {
Person person = new Person();
person.setId(id);
person.setFirstName(firstName);
person.setLastName(lastName);
entityManager.persist(person);
System.out.println("EJB1Impl: persistence context contains entity: " + entityManager.contains(person));
ejb2.containsEntity(person);
}
}
#Stateless
public class EJB2Impl implements EJB2 {
#Inject
private EntityManager entityManager;
#Override
public void containsEntity(final Person person) {
System.out.println("EJB2Impl: PersistenceContext contains entity: " + entityManager.contains(entity));
person.setLastName("new name");
//entityManager.merge(person);
}
}
The EJB's are deployed on WildFly 10. I access them by a remote client using this tutorial. The current version throws this exception: org.jboss.weld.context.ContextNotActiveException: WELD-001303 No active contexts for scope type javax.enterprise.context.RequestScoped. If I remove the #RequestScoped annotation from the producer, I don't get an exception but the EntityManager injected into the second EJB returns false when asked if it contains the entity and if I want the changes made to the entity (the change of the last name) to have any effect, I have to call entityManager.merge(person), which apparently means that the entity is detached. I'm sure that the second EJB executes withing the same transaction because if I inject an EJBContext and call setRollbackOnly() the transaction started in EJB1 is rolled back and a new person is not inserted into the data base.
The documentation of javax.enterprise.context.RequestScoped says that the request scope is active during any remote method invocation of any EJB, so what gives? How can I share an EntityManager during a request across multiple EJB's
With following class,
#Path("/somes")
#RequestScoped
public class SomesResource {
#PersistenceContext(unitName = "some")
private EntityManager entityManager;
#Inject
private SomeService someService;
}
Where,
#Stateless
public class SomeService {
#PersistenceContext(unitName = "some")
private EntityManager entityManager;
}
Question 1: Is it O.K. to be injected with #PersistenceContext in #RequestScoped bean?
Question 2: Is entityManager in SomesResource need to be worked with an UserTransaction in any modification job?
Question 3: Are two entityManagers effectively same instance?
I have a service interface I with implementaions I1,I2,I3...I10 out of which I want to use I1-I5 to be autowired as a List<I> in controller class C. The I6-I10 should not be be autowired. How can I achieve this. Moreover the I implementations are annotated #Service beans. I do not want to move them to xml declarations.
Based on the comment by mvb13 I have tried to weave a solution for the problem....
So I write a class extending ArrayList and mark it a Component
#Component("mysublist")
public class MyList extends ArrayList implements ApplicationContextAware
{
#Value("comma.sep.eligible.beans.classnames")
private String eligibles;
private ApplicationContext appCtx;
#PostConstruct
public void init()
{
Map allBeans = appCtx.getBeansOfType(I.class);
for(Object bean:allBeans.values())
{
if(eligibles.contains(bean.getClass().getSimpleName()))
{
add(bean);
}
}
}
public void setApplicationContext(ApplicationContext appCtx)
{
this.appCtx = appCtx;
}
}
Now I can autowire the above bean in my required class definition as:
#Service
public class MyService
{
#Resource(name="mysublist")
private List<I> myReqdBeans;
......
}
*Please ignore the generics related implications in the code.
You should use #Qualifier. It defines any subset that you need.
#Autowired
#Qualifier("MySubset")
private List<I> list;
But I think you should move your bean definitions in xml to use <qualifier ... /> property. I think you haven't another option to specify qualifier.
The #Qualifier annotation should give you what you need. You need to apply it in two places:
On the #Service beans that you wish to include in the sub-list
On the #Autowired list injected into your controller
So addressing the #Service beans first:
#Service
#Qualifier("MySubList")
public class MyService implements IMyService
{
}
And then within your Controller:
#Controller
public class MyController
{
#Qualifier("MySubList")
#AutoWired
private List<IMyService> myServices;
}
This instructs Spring to #AutoWire all IMyService implementations #Qualified as "MySubList"
Now I use Jersey to create restful web service on Websphere 8.5. I also want the restful web service has the EJB 3.1's capacity.
My restful web service code as follow:
#Stateless
#Path("/tagServiceRS/{tagid}")
#Interceptors(TestTagServiceInterceptor.class)
public class TagServiceRS implements Serializable{
private static final long serialVersionUID = 5L;
private static final Logger log = LoggerFactory.getLogger(TagServiceRS.class);
#EJB
private TagTestService tagTestService;
#PersistenceContext(unitName = "tag-ejb")
private EntityManager entityManager;
#GET
#Produces("text/plain")
public String findTagById(#PathParam("tagid") String tagid) {
return "TAG";
}
/**
* #return the tagTestService
*/
public TagTestService getTagTestService() {
return tagTestService;
}
/**
* #param tagTestService the tagTestService to set
*/
public void setTagTestService(TagTestService tagTestService) {
this.tagTestService = tagTestService;
}
When I deploy the war on the Websphere 8.5. The TagServiceRS was successful deployed as a restful web service.And I test it. It's OK.But the TagServiceRS was failed deploy as a EJB session bean. The TagServiceRS's entityManager and tagTestService fields are all null.
I see the log, there is no error or warning log.
Below is my TagTestServiceBean code.
#Stateless
public class TagTestServiceBean implements TagTestService, Serializable {
private static final long serialVersionUID = 5L;
private static final Logger log = LoggerFactory.getLogger(TagTestServiceBean.class);
#Override
public Tag testFindTagById(Long id) {
log.info("testFindTagById ++++++++++++++++++++++++++++++++++++++++ invoked for id: {}", id);
return new Tag();
}
}
#Remote
public interface TagTestService extends Serializable {
/**
* #param id
* the ID from database
* #return a tag, may null
*/
Tag testFindTagById(Long id);
}
If Any Answers.Thanks a lot.
Change the annotation from #EJB to #Resource
#Resource
private TagTestService tagTestService;
The class itself need not to be annotated with #Stateless annotation.
Additionally, JAX-RS root resource and provider classes must have a JCDI specified scope. Scopes control the lifecycle of a JCDI managed bean. Root resource classes can have any valid scope such as #javax.enterprise.context.RequestScoped, which makes the JAX-RS root resource class behave the same as in a non-JCDI enabled application. The javax.ws.rs.core.Application subclasses and JAX-RS providers must have the #javax.enterprise.context.ApplicationScoped annotation.
More info here.