I am beginner with JAX-RS webservice and its testcase.
My TestController class is as follows:
public class LotTypeMangementServiceTest {
private final String LOT_NAME = "lotName";
#Inject
private LotTypeManagementService lotTypeService;
#Test
private LotType testCreate() {
LotType newLotType = new LotType();
newLotType.setName(LOT_NAME);
//save
lotTypeService.createOrUpdate(newLotType);
Assert.assertNotNull(newLotType.getId());
return newLotType;
}
}
My LotTypeManagementService as follows:
#Stateless
public class LotTypeManagementService {
#PersistenceContext(unitName="primary")
private EntityManager em;
public void createOrUpdate(LotType lotType) {
if (lotType.getId() == null) { // Save New Label Type
em.persist(lotType);
} else { // Update Label Type
em.merge(lotType);
}
}
}
Now as you can see, LotTypeManagementService has EntityManager dependency.
In testclass, I've injected LotTypeManagementService. However, its dependency is not getting injected and hence I em object is NULL.
My persistence.xml file is as below:
<persistence version="2.0"
xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="primary">
<jta-data-source>java:jboss/datasources/lottype</jta-data-source>
<properties>
<property name="hibernate.hbm2ddl.auto" value="update" />
<property name="hibernate.show_sql" value="true" />
</properties>
</persistence-unit>
</persistence>
My RestController is as below:
#RequestScoped
public class LotTypeResourceRESTService {
#Inject
private LotTypeManagementService lotTypeService;
}
I am using wildfly-9.0.1 server, java8, JAX-RS webservice, hibernate, jpa-2.1 and jUnit.
I found some solution on Stack Overflow like
Use #Inject or #Ejb
some change on persistance.xml <provider>org.hibernate.ejb.HibernatePersistence</provider>
em = (EntityManager) new nitialContext().lookup("java:/primary");
Like create dynamically container.
How can I do this correctly?
Related
I have a project by name Utility and it has a class by name Util as below:
public class Util {
public static String verify() {
CloseableHttpClient httpClient = HttpClientBuilder.create().build();
HttpGet getRequest = new HttpGet("Endpoint");
HttpResponse response = httpClient.execute(getRequest);
// Parsing the response as String
String resp = .......
return resp;
}
}
I have another project by name Consumer and it has a class by name Service as below:
public class Service {
public String verify() {
String resp = Util.verify();
return resp;
}
}
I have added Utility as a dependency for Consumer as:
<dependency>
<groupId>com.my.company</groupId>
<artifactId>utility</artifactId>
<version>0.0.1</version>
<scope>provided</scope>
</dependency>
I have a unit test case for the Service class where I am mocking the Util class with PowerMockito as:
#RunWith(PowerMockRunner.class)
#PrepareForTest({ Util.class })
public class ServiceTest {
Service service = new Service();
#Before
public void setUp() throws Exception {
PowerMockito.mockStatic(Util.class);
PowerMockito.when(Util.verify()).thenReturn("mockedResponse");
}
#Test
public void testVerify() {
String resp = service.verify();
assertEquals(resp, "mockedResponse");
}
}
This test throws NotFoundException for ProtocolSocketFactory. Does anyone know why I see this exception? I am trying to mock the Util class, but PowerMockito tries to initialize the class before mocking it. If I add HttpClient as a dependency in pom.xml for project Consumer, then the error goes away and the mocking is successful.
The Powermockito version I am using is 1.6.2
java.lang.IllegalStateException: Failed to transform class with name com.my.company.Util. Reason: cannot find org.apache.commons.httpclient.protocol.ProtocolSocketFactory
at org.powermock.core.classloader.MockClassLoader.loadMockClass(MockClassLoader.java:266)
at org.powermock.core.classloader.MockClassLoader.loadModifiedClass(MockClassLoader.java:180)
at org.powermock.core.classloader.DeferSupportingClassLoader.loadClass(DeferSupportingClassLoader.java:68)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:348)
at sun.reflect.generics.factory.CoreReflectionFactory.makeNamedType(CoreReflectionFactory.java:114)
Caused by: javassist.CannotCompileException: cannot find org.apache.commons.httpclient.protocol.ProtocolSocketFactory
at javassist.expr.NewExpr.replace(NewExpr.java:215)
at org.powermock.core.transformers.impl.MainMockTransformer$PowerMockExpressionEditor.edit(MainMockTransformer.java:418)
at javassist.expr.ExprEditor.loopBody(ExprEditor.java:212)
at javassist.expr.ExprEditor.doit(ExprEditor.java:91)
at javassist.CtClassType.instrument(CtClassType.java:1431)
at org.powermock.core.transformers.impl.MainMockTransformer.transform(MainMockTransformer.java:74)
at org.powermock.core.classloader.MockClassLoader.loadMockClass(MockClassLoader.java:251)
... 55 more
Caused by: javassist.NotFoundException: org.apache.commons.httpclient.protocol.ProtocolSocketFactory
at javassist.ClassPool.get(ClassPool.java:450)
at javassist.bytecode.Descriptor.toCtClass(Descriptor.java:592)
at javassist.bytecode.Descriptor.getParameterTypes(Descriptor.java:439)
at javassist.expr.NewExpr.replace(NewExpr.java:188)
... 61 more
I am trying to create a unit test that uses EclipseLink via JPA and I noticed that I needed to inject a DAO into a listener. The code itself works as expected inside a container, but I am having trouble making a unit test for it.
The listener looks like this.
#ApplicationScoped
public class ParticipantListener {
#Inject
private ParticipantDAO dao;
#PrePersist
#PreUpdate
void ensureNoDuplicateSin(final Participant e) throws DuplicateSinException {
final Participant bySin = dao.getBySinAndNotSelf(e.getSin(), e);
if (bySin != null && bySin.getId() != e.getId()) {
throw new DuplicateSinException();
}
}
}
When I run in a unit test dao is not injected.
My test is initialized as follows:
weld = new Weld();
final WeldContainer container = weld.initialize();
vf = Validation.buildDefaultValidatorFactory();
final Map<String, String> props = new HashMap<>();
props.put("javax.persistence.provider", "org.eclipse.persistence.jpa.PersistenceProvider");
emf = Persistence.createEntityManagerFactory("test-pu", props);
em = emf.createEntityManager();
which obviously should not work because there's no relationship between the em/emf and the container
I needed to set the javax.persistence.bean.manager to point to Weld's bean manager. In addition I found that I also
weld = new Weld();
final WeldContainer container = weld.initialize();
final JpaProvider jpaProvider = container.select(JpaProvider.class).get();
final Map<String, Object> props = new HashMap<>();
props.put("javax.persistence.provider", "org.eclipse.persistence.jpa.PersistenceProvider");
props.put("javax.persistence.bean.manager", container.getBeanManager());
emf = Persistence.createEntityManagerFactory("test-pu", props);
em = emf.createEntityManager();
jpaProvider.setEntityManager(em);
In addition I had to change the DAO to not use #PersistenceContext and use #Inject for the entity manager and create a JpaProvider class. During the test it will set the entity manager from the container instance.
#ApplicationScoped
public class JpaProvider {
private EntityManager em;
#Produces
public EntityManager getEntityManager() {
return em;
}
#PersistenceContext
public void setEntityManager(final EntityManager em) {
this.em = em;
}
}
Your solution sounds unwieldy and as far as I understand you needed to change the code under test (which is not-a-good-thing-to-do (TM)).
Rather have a look into arquillian (http://arquillian.org/) and the use with mockito.
Here's a little bit of boilerplate code showing how I usually do this:
#RunWith(Arquillian.class)
public class TestParticipantListener {
// Collection of producer methods and/or static producer fields
// that mock the injected dependencies for the class under test
public static class LocalMocks {
#Produces ParticipantDAO getParticipantDAO() {
ParticipantDAO participantDAO = Mockito.mock(...);
return participantDAO
}
}
#Deployment
public static WebArchive createDeployment() {
PomEquippedResolveStage pom = Maven.resolver().loadPomFromFile("pom.xml");
BeansDescriptor beansXml = Descriptors.create(BeansDescriptor.class)
.addDefaultNamespaces().getOrCreateAlternatives()
.up();
WebArchive jar = ShrinkWrap.create(WebArchive.class)
.addAsLibraries(pom.resolve("org.mockito:mockito-core").withTransitivity().asFile())
.addClass(ParticipantListener.class)
.addClass(ParticipantDAO.class)
.addClass(TestParticipantListener.LocalMocks.class)
// ... other dependencies
.addAsWebInfResource(new StringAsset(beansXml.exportAsString()), "beans.xml");
return jar;
}
#Inject ParticipantListener participantListenerUnderTest;
#Test
public void test() {
... whatever your test is, using the injected instance
}
}
I get the following error when my Webservice is invoked:
org.apache.openjpa.persistence.ArgumentException: A JDBC Driver or DataSource class name must be specified in the ConnectionDriverName property.
The Webservice class is bascially trying to use JPA to insert data, and based on the above error message it seems the EntityManager cant access the datasource entry as shown below:
<persistence-unit name="TEST_P" transaction-type="RESOURCE_LOCAL">
<provider>
com.ibm.websphere.persistence.PersistenceProviderImpl
</provider>
<non-jta-data-source>java:comp/env/jdbc/DATA</non-jta-data-source>
<class>jpa.WSTGHandler</class>
<properties>
</properties>
</persistence-unit>
I have also defined the datasource entry in the web.xml as shown below:
<resource-ref>
<res-ref-name>java:comp/env/jdbc/DATA</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
<res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>
Embedding the JPA code in In Servlet suceesfully locates the datasource. how can I get the Webservice to work the same way ?
PS: I am using Websphere 7, JPA version 1.2, and JAX-WS
As requested, the follwing class is invoked int he Webservice method i.e beginTransaction()
public class EntityManagerHelper {
private static final EntityManagerFactory emf;
private static final ThreadLocal<EntityManager> threadLocal;
private static final Logger logger;
static {
emf = Persistence.createEntityManagerFactory("TEST_P");
threadLocal = new ThreadLocal<EntityManager>();
logger = Logger.getLogger("TEST_P");
logger.setLevel(Level.FINE);
}
public static EntityManager getEntityManager() {
EntityManager manager = threadLocal.get();
if (manager == null || !manager.isOpen()) {
manager = emf.createEntityManager();
threadLocal.set(manager);
}
return manager;
}
public static void closeEntityManager() {
EntityManager em = threadLocal.get();
threadLocal.set(null);
if (em != null) em.close();
}
public static void beginTransaction() {
getEntityManager().getTransaction().begin();
}
public static void commit() {
getEntityManager().getTransaction().commit();
}
public static void rollback() {
getEntityManager().getTransaction().rollback();
}
public static Query createQuery(String query) {
return getEntityManager().createQuery(query);
}
public static void log(String info, Level level, Throwable ex) {
logger.log(level, info, ex);
}
}
Issue resolved. it was just a typo in the res-ref-name :)
I am working on a plugin for Mura CMS adding in my own beans, and just started getting an error that one doesn't exist. One of my beans has setters and getters for email, name, amount, etc. as well as some beans (ie. configBean, priceBean, teamBean).
When I try to load up the bean (called donationBean) I get an error that no bean exists with the ID email. Email is not supposed to be based off a bean. I haven't added any code besides the getter/setter for email and the error doesn't arise from any other properties. Here is the getter/setter section of the donation bean:
public numeric function getAmount(){ return Variables.data['amount']; }
public void function setAmount(numeric amount){ Variables.data['amount'] = Arguments.amount; }
public any function getConfigBean(){ return Variables.configBean; }
public void function setConfigBean(any configBean){ Variables.configBean = Arguments.configBean; }
public string function getEmail(){ return Variables.data['email']; }
public void function setEmail(string email){ Variables.data['email'] = Arguments.email; }
public string function getId(){ return Variables.data['id']; }
public void function setId(string id){ Variables.data['id'] = Arguments.id; }
public string function getName(){ return Variables.data['name']; }
public void function setName(string name){ Variables.data['name'] = Arguments.name; }
public boolean function getPaid(){ return Variables.data['paid']; }
public void function setPaid(boolean paid){ Variables.data['paid'] = Arguments.paid; }
public any function getPriceBean(){ return Variables.priceBean; }
public void function setPriceBean(any priceBean){ Variables.priceBean = Arguments.priceBean; }
public numeric function getTeamId(){ return Variables.data['teamid']; }
public void function setTeamId(numeric teamid){ Variables.data['teamid'] = Arguments.teamid; }
And here's my config.xml
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans default-autowire="byName">
<bean id="registrationBean" class="[plugin]lib.registration" />
<bean id="priceBean" class="[plugin]lib.price" />
<bean id="donationBean" class="[plugin]lib.donation" />
</beans>
And finally my code to load up the bean (from within the bean itself):
public any function createForTeamPayment(priceid, teamid, name, email){
var price = getPriceBean().loadBy({priceid=Arguments.priceid});
setAmount(price.getAmount());
setTeamId(Arguments.teamid);
setName(Arguments.name);
setEmail(Arguments.email);
save();
}
I found that if I changed the email property to another name, in my case donorEmail, then everything started to work. I have no idea why, as there is no bean with ID email and it wasn't being called as a bean.
Most likely a namespace collision ... EmailID is in the mura namespace ...
You might try setting a local scope for the vars ...
Checkout ~ requirements\mura\bean\beanFactory.cfc ...
<cfset variables.transientAlias["email"]="emailBean"/>
And too ~ requirements\mura\email\emailBean.cfc
<cfcomponent extends="mura.bean.bean" output="false">
<cfproperty name="emailID" type="string" default="" required="true" />
I've used this technique before and specifying all the configuration explicitly. The log indicates it's creating the datasource and loading the scripts:
o.s.j.d.e.EmbeddedDatabaseFactory - Starting embedded database: url='jdbc:h2:mem:balancer;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=false', username='sa'
o.s.j.d.i.ScriptUtils - Executing SQL script from class path resource [db/migration/V1_0001__create_queue_server_table.sql]
o.s.j.d.i.ScriptUtils - Executed SQL script from class path resource [db/migration/V1_0001__create_queue_server_table.sql] in 20 ms.
o.s.j.d.i.ScriptUtils - Executing SQL script from class path resource [db/migration/V1_0002__queue_server_entries.sql]
o.s.j.d.i.ScriptUtils - Executed SQL script from class path resource [db/migration/V1_0002__queue_server_entries.sql] in 8 ms.
o.s.o.j.LocalContainerEntityManagerFactoryBean - Building JPA container EntityManagerFactory for persistence unit 'default'
I am able to invoke the REST webservice and the call goes through to the Repository but nothing is returned. The application works fine when connecting to mysql and returns data that was loaded. I cannot see what is missing WRT configuration:
Testcase:
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = {QueueServiceApplication.class, TestConfig.class})
#WebAppConfiguration
#ActiveProfiles({"test"})
public class QueueServiceApplicationTests {
private static final int EXPECTED_SERVER_COUNT = 10;
#Autowired
private WebApplicationContext webCtx;
private MockMvc mvc;
#Before
public void init() {
mvc = MockMvcBuilders.webAppContextSetup(webCtx).build();
}
#Test
public void successListAll() throws Exception {
mvc.perform(get("/listall")).andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$", hasSize(EXPECTED_SERVER_COUNT)));
}
}
Test configuration object for embedded datasource:
#Configuration
#Profile("test")
public class TestConfig {
#Bean
public DataSource dataSource() {
return new EmbeddedDatabaseBuilder()
.addScript("classpath:/db/migration/V1_0001__create_queue_server_table.sql")
.addScript("classpath:/db/migration/V1_0002__queue_server_entries.sql")
.setType(EmbeddedDatabaseType.H2)
.setName("vitel-balancer")
.setScriptEncoding("UTF8")
.build();
}
}
Launcher:
#SpringBootApplication
public class QueueServiceApplication {
public static void main(String[] args) {
SpringApplication.run(QueueServiceApplication.class, args);
}
}
I'm using spring-boot 1.3.2, java 8 update 72
I have been able to address this by changing my TestConfig class
#Configuration
#Profile("test")
public class TestConfig {
#Bean
public DataSource dataSource() {
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.H2)
.build();
}
#Bean
public ResourceDatabasePopulator populator() {
ResourceDatabasePopulator pop = new ResourceDatabasePopulator();
pop.addScript(new ClassPathResource("db/migration/V1_0001__create_queue_server_table.sql"));
pop.addScript(new ClassPathResource("db/migration/V1_0002__queue_server_entries.sql"));
pop.setContinueOnError(true);
return pop;
}
#Bean
public DataSourceInitializer dbInit(DataSource ds, ResourceDatabasePopulator populator) {
DataSourceInitializer init = new DataSourceInitializer();
init.setDataSource(ds);
init.setDatabasePopulator(populator);
init.setEnabled(true);
return init;
}
}
I'm not sure why this is different that using the EmbeddedDatabaseBuilder and adding the scripts to it. Would be greatful if there is an explaination