How do I test that controllers write correctly to the DB in playframework - jpa

I have a FunctionalTest that tests posting to a controller and then does asserts on the model objects to make sure the controller did it's job, like so:
#Test
public void editUser(){
Logger.debug("Edit user test");
createNewUser();
final User user = User.<User>findAll().get(0);
POST("/ManageUser/save", ImmutableMap.of(
"user.id", user.getId().toString(),
"user.username", "test",
"user.email", "test#example.com",
"user.fullName", "Test Different"
));
User.em().flush();
User.em().clear(); // this is required so that it works on the mem DB
assertEquals(1, User.findAll().size());
assertEquals("Test Different", User.<User>findAll().get(0).fullName);
final User userAfterSave = User.<User>findAll().get(0);
assertFalse("New user should not be admin.", userAfterSave.isAdmin);
}
This passes when I use the mem database
%test.db.url=jdbc:h2:mem:play;MODE=MYSQL;LOCK_MODE=0
However if I switch to mysql
%test.db=mysql://test:test#localhost/test
It fails on the second assert "Failure, expected:<Test [Differen]t> but was:<Test [Tes]t>". So when using mysql the controller doesn't persist the user properly.
What am I missing here, are there some options for transaction control that I need to change for this to work?
The controller just calls user.merge().save() to update the user, is this somehow wrong?

This is because the mem DB is not properly transactional, meaning the test thread gets new data every read. For mysql however the test thread read the user in createNewUser() meaning it's transaction had the previous version. It's not obvious but POST() starts a new thread with a separate transaction. To solve this swap out
User.em().flush();
User.em().clear();
for
JPAPlugin.closeTx(false);
JPAPlugin.startTx(false);
The later starts a new transaction.

Do your search in a separate job to be sure it correctly view the modifications (transaction isolation). Here is an example
private FeedbackType findFeedbackType(final String name) throws ExecutionException, InterruptedException {
return new Job<FeedbackType>() {
#Override
public FeedbackType doJobWithResult() throws Exception {
return FeedbackType.findByName(name);
}
}.now().get();
}
This is a private method of my Functional test and I call this method to get my object instead of directly invoking the model

Related

Apache Shiro; SecurityUtils.getSubject() for a schedule user?

I want to implement the following scenario:
I have a EJB scheduler, which should run every 1 minute.
My issue is the following:
I need a login for the user, who execute the schedule. This should be a system user. There will be no login via GUI.
How can I login this user and execute further task?
Currently I´m trying in my class:
#Singleton
#LocalBean
#Startup
public class Scheduler {
public void startSchedule() {
Subject currentUserShiro = SecurityUtils..getSubject();
UsernamePasswordToken token = new UsernamePasswordToken("test#domain.com", "test1234");
currentUserShiro.login(token);
In one of my function, I check e.g. for the permission:
SecurityUtils.getSubject().isPermitted("billingInvoice:create")
I´m getting currently the following issue:
No SecurityManager accessible to the calling code, either bound to the org.apache.shiro.util.ThreadContext or as a vm static singleton. This is an invalid application configuration.
Any idea?
Code update:
private void addScheduleToList(ScheduleExecution scheduleExecution) throws UnknownHostException {
synchronized (this) {
Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro-web.ini");
SecurityManager securityManager = factory.getInstance();
SecurityUtils.setSecurityManager(securityManager);
Subject subject = new Subject.Builder().buildSubject();
Runnable myRunnable = null;
subject.execute(myRunnable = new Runnable() {
#Override
public void run() {
// Add tasks
executeAction(scheduleExecution);
}
});
//////
schedulingService.addTaskToExecutor(taskId, myRunnable, 0);
}
}
I´m gettig now not anymore the issue message which I got initialy, but it seems I´m getting PermissionException, because the user has not the permission? If I check the Subject object, this object is not authenticated. This Subject object needs full permission. How can I do this?
SecurityUtils.getSubject().isPermitted("billingInvoice:create") == false
You have a couple of options.
Move your permission checking to your web-based methods, this moves the permission checkout outside of your scheduled task.
(this isn't always possible and since you are asking the question, I'm assuming you want the 2nd option)
You need to execute your task in the context of a user. Create a new Subject using a SubjectBuilder and then call the execute with a runnable from your task.
See https://shiro.apache.org/subject.html specifically the "Thread Association" section.

Persist object without try-catch block in method

I'm currently working on a project and I want to see what damage it can do if I don't embrace my code with try-catch block when persisting object into database. Here is my code down below that i use as test.
public class NewEventServiceBean implements NewEventService {
#PersistenceContext(name = "example")
EntityManager manager;
#Resource
private UserTransaction userTransaction;
#Override
public void createNewEvent(String title, String content) throws Exception
{
userTransaction.begin();
Event event = new Event();
Content cont = new Content();
cont.setContent(content);
event.setTitle(title);
event.setCont(cont);
manager.persist(event);
manager.persist(cont);
userTransaction.commit();
}
In the database i have this Event table that has a foreign key to Content table.
And my question is if It's possible that Event object is persisted in to the database even if I cause something wrong when persisting the content class. Or what is the disadvantages of not embracing the code with try catch and rollback?
I've tried to cause an error when persisting the content object, but the Event is not persisted into the datbase even if everything is correct in that class.

Detecting when the database session gets refreshed on a Spring Boot 2 application

I'm trying to execute the following SQL statement every time the Database Session gets refreshed. I have a Spring Boot 2.0.1.RELEASE with JPA application and a PostgreSQL Database.
select set_config('SOME KEY', 'SOME VALUE', false);
As the PostgreSQL documentation states the is_local parameter is used to indicate that this configuration value will apply just for the current transaction -if true- or will be attached to the session (as I require) -if false-
The problem is that I'm not aware when Hibernate/Hikari are refreshing the db session, so, in practice, the application start failing when it has a couple of minutes running, as you can imagine...
My approach -that is not working yet- is to implement a EmptyInterceptor, for that I have added a DatabaseCustomizer class to inject my hibernate.session_factory.interceptor properly in a way that Spring can fill out all my #Autowires
DatabaseInterceptor.class
#Component
public class DatabaseInterceptor extends EmptyInterceptor {
#Autowired
private ApplicationContext context;
#Override
public void afterTransactionBegin(Transaction tx) {
PersistenceService pc = context.getBean(PersistenceService.class);
try {
pc.addPostgresConfig("SOME KEY", "SOME VALUE");
System.out.println("Config added...");
} catch (Exception e) {
e.printStackTrace();
}
}
}
DatabaseCustomizer.class
#Component
public class DatabaseCustomizer implements HibernatePropertiesCustomizer {
#Autowired
private DatabaseInterceptor databaseInterceptor;
#Override
public void customize(Map<String, Object> hibernateProperties) {
hibernateProperties.put("hibernate.session_factory.interceptor", databaseInterceptor);
}
}
Obviously, there is a problem with this approach because when I #Override the afterTransactionBegin method to start another transaction I get an Infinite loop.
I tried to look something inside that Transaction tx that could help to be sure that this transaction is not being generated by my own addPostgresConfig but there is not much on it.
Is there something else I could try to achieve this?
Thanks in advance,

How to get outArgument WorkflowApplication when wf wait for response(bookmark OR idle) and not complete

Accessing Out Arguments with WorkflowApplication when wf wait for response(bookmark OR idle) and not complete
I also used Tracking to retrieve the values, but instead of saving it to a database I come up with the following solution.
Make a Trackingparticipant and collect the data from an activity.
You can fine tune the tracking participant profile with a spefic tracking query.
I have added a public property Output to set the value of the data from the record.
public class CustomTrackingParticipant : TrackingParticipant
{
//TODO: Fine tune the profile with the correct query.
public IDictionary<String, object> Outputs { get; set; }
protected override void Track(TrackingRecord record, TimeSpan timeout)
{
if (record != null)
{
if (record is CustomTrackingRecord)
{
var customTrackingRecord = record as CustomTrackingRecord;
Outputs = customTrackingRecord.Data;
}
}
}
}
In your custom activity you can set the values you want to expose for tracking with a CustomTrackingRecord.
Here is a sample to give you an idea.
protected override void Execute(NativeActivityContext context)
{
var customRecord = new CustomTrackingRecord("QuestionActivityRecord");
customRecord.Data.Add("Question", Question.Get(context));
customRecord.Data.Add("Answers", Answers.Get(context).ToList());
context.Track(customRecord);
//This will create a bookmark with the display name and the workflow will go idle.
context.CreateBookmark(DisplayName, Callback, BookmarkOptions.None);
}
On the WorklfowApplication instance you can add the Tracking participant to the extensions.
workflowApplication.Extensions.Add(new CustomTrackingParticipant());
On the persistable idle event from the workflowApplication instance I subscribed with the following method.
In the method I get the tracking participant from the extensions.
Because we have set the outputs in the public property we can access them and set them in a member outside the workflow. See the following example.
private PersistableIdleAction PersistableIdle(WorkflowApplicationIdleEventArgs
workflowApplicationIdleEventArgs)
{
var ex = workflowApplicationIdleEventArgs.GetInstanceExtensions<CustomTrackingParticipant>();
Outputs = ex.First().Outputs;
return PersistableIdleAction.Unload;
}
I hope this example helped.
Even simpler: Use another workflow activity to store the value you are looking for somewhere (database, file, ...) before starting to wait for a response!
You could use Tracking.
required steps would be:
define a tracking profile which queries ActivityStates with the state closed
Implement an TrackingParticipant to save the OutArgument in process memory, a database or a file on disk
hook everything together
The link cotains all the information you will need to do this.

Is this safe? - NUnit base class opens and rollsback a TransactionScope

I was thinking it would be nice to create a base class for NUnit test fixtures that opens a TransactionScope during the SetUp phase, then rolls back the transaction during tear down.
Something like this:
public abstract class TestFixtureBase
{
private TransactionScope _transaction;
[TestFixtureSetUp]
public void TestFixtureSetup()
{
_transaction = new TransactionScope();
}
[TestFixtureTearDown]
public void TestFixtureTearDown()
{
if (_transaction != null)
{
_transaction.Dispose();
}
}
}
Do you think this is a good idea?
Obviously the database is just a test database, not a live database, but it would still be annoying if it filled up with junk data from the unit tests.
What do other people do when running unit tests that involve a lot of data access?
You want to be careful here. TransactionScope is going to promote the transaction to a distributed transaction if you open up more than one connection to the database. I find that it is easier just to write some simple SQL that clears out the tables of interest to my test class before I start running the test.
EDIT: Normally I would call any test that touches the database an integration test since it involves another system. Typically, I will mock out the database when unit testing my code.
[TestSetup]
public void Setup()
{
foreach (string table in new string[] { "table1", "table2" })
{
ClearTable( table );
}
}
private void ClearTable( string table )
{
...standard stuff to set up connection...
SqlCommand command = connection.CreateCommand() );
command.CommandText = "delete from " + table;
command.ExecuteNonQuery();
... stuff to clean up connection...
}
I've used XtUnit
It automatically rolls back at the end of a unit test. You can simply add a [Rollback] attribute to the test. It's an extension to NUnit or MbUnit