JPA default persistence unit - jpa

I get exception "There is no default persistence unit in this deployment." can I somehow mark unit as default?(I have only one persistence unit, so Id rather not call it by name)

No, you have to call PU's by name.

You are probably doing it through code rather than letting the container manage it. In which case you have to specify by name.
My unit test code has this code block to do this.
#Before
public void createEntityManagerFactory() throws IOException {
final Properties p = new Properties();
p.load(getClass().getResourceAsStream("/inmemory.properties"));
emf = Persistence.createEntityManagerFactory("default", p);
}
However, my application code looks like this.
/**
* Injected persistence context.
*/
#PersistenceContext
private EntityManager em;

Related

SpringbootTest + TestContainers: how do I refresh the database after tests pollute the database

I am using an abstract class like this:
#SpringBootTest(classes = MyAppApplication.class, webEnvironment = WebEnvironment.RANDOM_PORT)
#ActiveProfiles("test")
public abstract class AbstractIntegrationTest {
static {
PostgreSQLContainer postgreSQLContainer = new PostgreSQLContainer().withPassword("password")
.withUsername("postgres").withDatabaseName("MyApp");
postgreSQLContainer.start();
System.setProperty("spring.datasource.url", postgreSQLContainer.getJdbcUrl());
System.setProperty("spring.datasource.password", postgreSQLContainer.getPassword());
System.setProperty("spring.datasource.username", postgreSQLContainer.getUsername());
}
Then I have many tests that leverage that use that class like this:
public class moreTests extends AbstractIntegrationTest {
TestRestTemplate restTemplate = new TestRestTemplate("my-user", "password");
HttpHeaders headers = new HttpHeaders();
#Test
public void SimpleHealthCheck() {
HttpEntity<String> entity = new HttpEntity<String>(null, headers);
ResponseEntity<String> response = restTemplate.exchange(
createURLWithPort("/api/v1/healthcheck"),
HttpMethod.GET, entity, String.class);
assertThat(response.getStatusCode(), equalTo(HttpStatus.OK));
}
#Test
public void GetInst() {
HttpEntity<String> entity = new HttpEntity<String>(null, headers);
ResponseEntity<String> response = restTemplate.exchange(
createURLWithPort("/api/v1/institutions"),
HttpMethod.GET, entity, String.class);
assertThat(response.getStatusCode(), equalTo(HttpStatus.OK));
}
However, some of my tests will pollute the database. I'd like to control if a test runs with a fresh database or not. What's the prescribed way to do this?
After more reading about Spring boot integration testing, it appears the prescribed way is to use the "#DirtiesContext" annotation for tests that are destructive (or dirty).
EDIT: After a few months, I realized #DirtiesContext is not awesome. It basically resets the whole app which can be expensive. Also, #DirtiesContext May not reset your database in some cases depending on how your app works. I suggest having a cleanup SQL script that runs in your #BeforeAll or #AfterAll section of each test class. This cleanup SQL script needs to be carefully written.
you either use the #Before annotation to clean everything before executing your tests.
Or you clean in each test before you execute.
Each test should be independent from the other. So usually:
clear and set up expectations
run test
If test fails, your database will be in the failed state so you can check what happened.

When does a object become detached in Spring Data JPA?

I have a service that is using a Spring Data Repository to retrieve an object. The service is NOT marked as transactional, thus I assumed that any object returned from the repository would be detached since the transaction would be scoped to the repository. However, it seems as though the object is NOT detached which surprises me. Here is a code sample:
public class MyService {
#Autowired
private MyRepository repo;
#Autowired
private EntityManager entityManager;
/**
* Updates a persisted entity based on the given DTO representation.
*/
public MyObjectDto update(MyObjectDto dto) {
MyObjectJpa existing = repo.findOne(dto.getId());
entityManager.isJoinedToTransaction(); // returns false so no transaction should be active in this scope I would assume
entityManager.contains(existing); // this returns true, but I don't know why
if (existing != null) {
MyObjectJpa updated = toJpa(dto);
// calling repo.save(..) modifies the state of 'existing' object which surpised me
MyObjectDto updatedDto = toDto(repo.save(updated));
return updatedDto;
}
return null;
}
Why is the 'existing' object in my code sample still managed by the entityManager even though my service method is not marked as transactional (i.e. not using the #Transactional annotation from Spring)? Thanks.
In Spring Boot parameter spring.jpa.open-in-view is set to true by default.
I think you should turn it to false.
From java-doc:
Register OpenEntityManagerInViewInterceptor. Binds a JPA EntityManager to the thread for the entire processing of the request.

Using a Producer Method To Choose a Bean Implementation

I followed the example on here for dynamically selecting the implementation to inject during run time. I then try to implement it based on my understanding but my code always return the default implementation;
Here is my code
#Stateless
public class MemberRegistration {
#Inject
private Logger log;
#Inject
private EntityManager em;
#Inject
private Event<Member> memberEventSrc;
#Inject
#Switch
IHandler handler;
private int handlerValue;
public String testCDI(int value) {
handlerValue = value;
log.info("handling " + value);
log.info("handling " + handlerValue);
return handler.handle();
}
#Produces
#RequestScoped
#Switch
public IHandler produceHandler(#New Handler0 handler0,
#New Handler1 handler1) {
log.info("Calling producer method with handler: "+handlerValue);
switch (handlerValue) {
case 1:
log.info("returning one");
return handler1;
case 0:
log.info("returning 0");
return handler0;
default:
log.info("returning default");
return handler1;
}
}
}
When i call the method testCDI I then update the handlerValue so that my producer method can use that value. What am I missing here to ensure that the producer method is called when the right value is available?
The code is running on Wildfly 8.2.0
The instance injected isn't going to be resolved when you call the method, but at the time of injection of the bean (the stateless session bean in this case). As a result, handlerValue will be 0.
You can however use an Instance<IHandler> to defer the injection. Use an annotation literal instead of your switch to do something like
#Inject
#Any
private Instance<IHandler> handlerInst
Then in your code
IHandler handler = handlerInst.select(new SwitchLiteral(value)).get();
then do work against that guy, but in your producer you need to use the InjectionPoint class to read the Switch annotation represented by the SwitchLiteral
You are running into cycling dependency here with your simplified code. Fields injected with plain #Inject need to be resolved BEFORE MemberRegistration is created, but handler field can only be created with a producer method AFTER MemberRegistration is created (beans with producer methods are created according to same rules as other CDI beans).
There are 2 solutions:
Either you create a separate HandlerProducer class, which will contain produceHandler() method and also handlerValue field. You should mark the class as #ApplicationScoped in order to reuse the same instance all over.
Or you need not only to produce IHandler dynamically, but also use (inject it) dynamically only when really needed in the MemberRegistration - this way handler is produced not BEFORE MemberRegistration is created, but after or never if not required. You do this by injecting Instance object and then use its get() method to retrieve handler when needed. Anyway, I am not sure if CDI will create a new instance every time, or reuse existing EJB. Scopes of EJBs and plain CDI beans are completely different and in general, I would not use an EJB as a bean with producer methods. It is better to always create a separate bean for producer methods, as in solution 1.
Example for solution 2 follows:
#Inject
#Switch
Instance<IHandler> handlerInjector;
private int handlerValue;
public String testCDI(int value) {
handlerValue = value;
log.info("handling " + value);
log.info("handling " + handlerValue);
return handlerInjector.get().handle();
}

Is it possible to annotate a method with #TransactionAttribute in BMT EJB?

I came across a piece of code where the bean implementation class has #TransactionManagement(TransactionManagementType.BEAN) annotation wherein methods are annotated with CMT #TransactionAttribute. Is is valid?
Can an EJB with BMT persistence use CMT transaction annotation? What will be the behavior at runtime?
Though javadoc http://docs.oracle.com/javaee/6/api/javax/ejb/TransactionAttribute.html says that "It can only be specified if container managed transaction demarcation is used.", specifying it doesn't throw any compilation error. Does it mean that jvm simply ignores it at runtime?
#Stateless( mappedName = "Abc")
#Remote("AbcRemote.class")
#Local("AbcLocal.class")
#TransactionManagement(TransactionManagementType.BEAN)
public class AbcBean implements AbcLocal, AbcRemote{
#Resource
private UserTransaction utx;
#PersistenceUnit
private EntityManagerFactory emf;
#Override
#TransactionAttribute(TransactionAttributeType.REQUIRED)
public Abc getAlpbabets(String name) {
EntityManager em = null;
try {
em = emf.createEntityManager();
}
catch (RuntimeException re) {
throw re;
}
finally {
}
}
}
If you use CMT, then #TransactionAttribute(TransactionAttributeType.REQUIRED) would tell the container to check for an existing transaction and open one if there is none.
But if you use BMT, then it's your responsibility to do such a thing, so there's no one to observe the annotation above. Since it is still syntactically correct and the class is available, there is no need for the JVM to complain about.
Concerning ignoring annotations, there's a hint in the answer to this question.

Why transaction can't commit in a self-invoked ejb method with #REQUIRES_NEW Annotation

First I want to explain my self-invoked ejb method in this situation. I have a stateful session bean with a method which starts a new transaction (Annotated by #REQUIRES_NEW). To invoke this method inside the bean itself and make the annotation effective, I use SessionContext#getBusinessObject() to achieve the effect of #EJB (#EJB here causes stackoverflow?!). My code is shown below:
#Stateful
#Local
public class TransactionTest implements ITransactionTest {
#PersistenceContext(unitName="Table",Type=PersistenceContextType.EXTENDED)
private EntityManager manager;
#Resource
SessionContext sc;
ITransactionTest me;
#PostConstruct
public void init(){
me = this.sc.getBusinessObject(ITransactionTest.class);
}
public void generateRecord(int i) throws RuntimeException{
Record record = new Record();
record.setId(i+"");
record.status(1);
manager.persist(record);
manager.flush(); //If not flush, result is correct. Why?
me.updateRecord(i);
}
#TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public void updateRecord(int i) throws RuntimeException{
try {
Record record = manager.find(Record.class, i+"");
record.setStatus(2);
manager.flush();
} catch(Exception e) {
e.printStackTrace();
throw new RuntimeException();
}
}
}
While,generateRecord() runs properly. The console shows it executes 'insert' and 'update' HQL without any exception (I use Hibernate as JPA provider). However, the 'update' result doesn't appear in the database. Why? Does updateRecord() commit correctly?
Also, I try it in two altenative ways: First is invoking generateRecord() (it will no longer invoke updateRecord()) and updateRecord() consecutively in another bean. It can give me the right result.
The second is removing the first flush(). Then both 'insert' and 'update' HQL will be executed at the second flush(). This method can also produce right result.
My program is running under JBOSS 6.1.0-Final and database is Oracle.
Best Regards,
Kajelas