EJB 2.x transaction isolation on JBoss 4.x - ejb-2.x

We have a legacy application which is running on a JBoss 3.x instance and which can't be changed or rewritten in large. Since the following problem might occur in several locations I'll give a somewhat abstract example, so if you need more information don't hesitate to ask and I'll try to gather it.
The main problem is the following: While the application runs fine on JBoss 3.x we want to migrate it to JBoss 4.x in order to enable a slow transition to technologies like EJB 3.x or JPA. I know that JBoss 4.x has long exceeded its end of life but unfortunately there's no way around that situation (other than keep running on 3.x).
During our tests we had the situation that uncommitted data could be read by a query in the same transaction while uncommitted relations could not.
Here's some abstract code of what the system looks like:
Entity (XML is created via xdoclet which I left out for simplicity reasons. If the settings are necessary, I can add them):
public abstract class Foo extends EntityBean, ...
{
...
public abstract RelationshipLocal getRelationship( );
public abstract void setRelationship( RelationshipLocal relationshipEntity );
public StammdatenAuthProcStepPK ejbCreate( RelationshipLocal relationshipEntity, ... )
throws javax.ejb.CreateException
{
setComment( "some comment" );
}
public void ejbPostCreate( RelationshipLocal relationshipEntity, ... )
throws javax.ejb.CreateException
{
setRelationship( relationshipEntity );
}
}
DAO method:
public Long getRelationshipUid( ... )
{
Connection conn = getDataSource().getConnection();
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery( "SELECT relationshipUid FROM foo WHERE ...;" );
if( rs.next() )
{
long relationshipUid = rs.getLong( "relationshipUid" );
if( !rs.wasNull() ) //always false, i.e. relationshipUid is always null
{
return new Long (relationshipUid);
}
}
return null;
}
As far as I understand the system, we have the following sequence:
begin transaction
create entity ( ejbCreate() is called and an INSERT is issued )
update relations ( ejbPostCreate() is called and an UPDATE is issued )
select the relationship uid from the newly created entity using the DAO method above
do something with that uid (I don't know what exactly)
commit transaction
Since we get fields set in ejbCreate() it seems as if the transaction isolation level is set to read uncommitted, however I don't know where to check that in EJB 2.x.
In EJB 3.x I'd use EntityManager.refresh() for that and maybe a manual flush() first, but since EJB 2.x doesn't have an EntityManager that doesn't seem to be an option.
We tried to change container settings in standardjboss.xml, e.g. <commit-option> but without any success.
Any other ideas what we could look after or what could go wrong here?
Any global options (e.g. JBoss settings, no need to change the code, since we don't know all places) would be welcome.

We recently moved from JBOSS 4 to EAP 6. However in our JBOSS 4 configuration we have the following settings in our container configurations (standardjboss.xml):
<container-configuration>
<container-name>Standard CMP 2.x EntityBean post create</container-name>
<call-logging>false</call-logging>
<invoker-proxy-binding-name>entity-rmi-invoker</invoker-proxy-binding-name>
<sync-on-commit-only>false</sync-on-commit-only>
<insert-after-ejb-post-create>true</insert-after-ejb-post-create>
...
<container-configuration>
The changing the setting "insert-after-ejb-post-create" to true will ensure the correct database interaction so that your data will be available for a read during the same transaction.

Related

In Symfony migration class, get option that you entered in console migration command

I created custom Command where I added a new attribute.
protected function configure() : void
{
parent::configure();
$this
->setName('doctrine:migrations:generate:entitychange')
->addOption('db', null, InputOption::VALUE_REQUIRED, 'The database connection to use for this command.')
->addOption('em', null, InputOption::VALUE_REQUIRED, 'The entity manager to use for this command.')
->addOption('shard', null, InputOption::VALUE_REQUIRED, 'The shard connection to use for this command.')
->addOption('entity',null,InputOption::VALUE_OPTIONAL,
'Entity on which migration will be applied',
'User');
}
Now I want to have a value of that parameter in up() and down() functions in migrations.
For example:
public up(Schema $schema) : void
{
// How to get this
$attributOfMyInputValue = $getInputValueOfParam('entity')
if($attributOfMyInputValue === 'someValue') {
$sql = 'some query';
$this->addSql($sql);
} else {
...
}
}
I assume, that you want to write minimal code here. So the first part of the problem is, to actually make doctrine migrations commands execute&migrate with that additional parameter/option. for that you probably have to extend both and add that parameter/option (or call them via https://symfony.com/doc/current/console/calling_commands.html)
To pass it on, I would probably go the lazy route and just create a service that is dependency injected into both the command (via constructor) and the migrations (via container, by making the migration container-aware) - something similar to Request's attribute bags. On the command side, I would add the parameters/options, and obviously on the migration side, read them from the same service, which can be fetched from the container.
I believe that approach entails the least amount of code, however, it's somewhat hacky. A possibly cleaner approach would be to create a new class of migrations, where those parameters are set by the migration/execute command, which probably would mean going deep into the migrations library and duplicating some of the behaviour or somehow figure out how to hook into or override the Migration execution process (which is - as far as i can tell from a quick glance - irritating, but there's probably some object you can decorate).

How to replace EntityManager::merge in Doctrine 3?

I am working an Symfony 2.8 based web app project which currently uses Doctrine 2. The project is basically a simple ToDo list application which can be synced with a mobile app (iOS/Android).
While reading the Update notes of Doctrine 3 I discovered, that EntityManager::merge will no longer be supported.
An alternative to EntityManager#merge() is not provided by ORM 3.0,
since the merging semantics should be part of the business domain
rather than the persistence domain of an application. If your
application relies heavily on CRUD-alike interactions and/or PATCH
restful operations, you should look at alternatives such as
JMSSerializer.
I am not sure what is the best/correct way to replace EntityManager::merge?
Where do I use merge:
During the sync of the mobile apps with the web app the data is transferred as serialized JSON which is than de-serialized by JMSSerializer to an entity object. When the web app receives a ToDoEntry object this way, it can be a new ToDo-Entry (not known in the web app yet) or an updated existing entry. Either way, the received object is not managed by the EntityManager. Thus $em->persist($receivedObject) will always try to insert a new object. This will fail (due to the unique constraint of the id) if the ToDo-Entry already exists in the web app and needs to be updated.
Instead $em->merge($receivedObject) is used which automatically checks wether an insert or update is required.
Hot wo solve this?
Of course I could check for every received objects if an entity with the same ID already exists. In this case could load the existing object and update its properties manually. However this would be very cumbersome. The real project of course uses many different entities and each entity type/class would need its own handling to check which properties needs to be updated. Isn't there a better solution?
You can try to use registerManaged() method of Doctrine\ORM\UnitOfWork.
// $this->em <--- Doctrine Entity Manager
// $entity <--- detached Entity (and we know that this entity already exists in DB for example)
$id = [$entity->getId()]; //array
$data = $entity->toArray(); //array
$this->em->getUnitOfWork()->registerManaged($entity, $id, $data);
Of course, You can check the state of Your Entity using getEntityState() of Doctrine\ORM\UnitOfWork before/after perfoming needed actions.
$this->eM->getUnitOfWork()->getEntityState($entity, $assert = 3)
$assert <-- This parameter can be set to improve performance of entity state detection by potentially avoiding a database lookup if the distinction between NEW and DETACHED is either known or does not matter for the caller of the method.
While I have posted this question quite a while ago, it is still quite active. Until now my solution was to stick with Doctrine 2.9 and keep using the merge function. Now I am working on new project which should be Doctrine 3 ready and should thus not use the merge anymore.
My solution is of course specific for my special use case. However, maybe it is also useful for other:
My Solution:
As described in the question I use the merge method to sync deserialized, external entities into the web database where a version of this entity might already exist (UPDATE required) or not (INSERT required).
#Merge Annotation
In my case entities have different properties where some might be relevant for syncing and must be merged while others are only used for (web) internal housekeeping and must not be merged. To tell these properties appart, I have created a custom #Merge annotation:
use Doctrine\Common\Annotations\Annotation;
/**
* #Annotation
* #Target("PROPERTY")
*/
final class SyncMerge { }
This annotation is then be used to mark the entities properties which should be merged:
class ToDoEntry {
/*
* #Merge
*/
protected $date;
/*
* #Merge
*/
protected $title;
// only used internally, no need to merge
protected $someInternalValue;
...
}
Sync + Merge
During the sync process the annotation is used to merge the marked properties into existing entities:
public function mergeDeserialisedEntites(array $deserializedEntities, string $entityClass): void {
foreach ($deserializedEntities as $deserializedEntity) {
$classMergingInfos = $this->getMergingInfos($class);
$existingEntity = $this->entityManager->find($class, $deserializedEntity->getId());
if (null !== $existingEntity) {
// UPDATE existing entity
// ==> Apply all properties marked by the Merge annotation
foreach ($classMergingInfos as $propertyName => $reflectionProperty) {
$deserializedValue = $reflectionProperty->getValue($deserializedEntity);
$reflectionProperty->setValue($existingEntity, $deserializedEntity);
}
// Continue with existing entity to trigger update instead of insert on persist
$deserializedEntity = $existingEntity;
}
// If $existingEntity was used an UPDATE will be triggerd
// or an INSERT instead
$this->entityManager->persist($deserializedEntity);
}
$this->entityManager->flush();
}
private $mergingInfos = [];
private function getMergingInfos($class) {
if (!isset($this->mergingInfos[$class])) {
$reflectionClass = new \ReflectionClass($class);
$classProperties = $reflectionClass->getProperties();
$propertyInfos = [];
// Check which properties are marked by #Merge annotation and save information
foreach ($classProperties as $reflectionProperty) {
$annotation = $this->annotationReader->getPropertyAnnotation($reflectionProperty, Merge::class);
if ($annotation instanceof Merge) {
$reflectionProperty->setAccessible(true);
$propertyInfos[$reflectionProperty->getName()] = $reflectionProperty;
}
}
$this->mergingInfos[$class] = $propertyInfos;
}
return $this->mergingInfos[$class];
}
That's it. If new properties are added to an entity I have only to decide whether it should be merged or not and add the annotation if needed. No need to update the sync code.
Actually the code to handle this can be just a few lines. In background Doctrine will issue a query to search for your entity if not already in memory, so you can do the same by doing the query yourself with result cache enabled, and then just use PropertyAccessor to map the data.
https://symfony.com/doc/current/components/property_access.html
See this gist for a POC https://gist.github.com/stevro/99060106bbe54d64d3fbcf9a61e6a273

Proper way to test a Symfony2 Service with Doctrine

I'm struggling to find the correct way to unit test my symfony 2 services which use doctrine or other common services.
What i have done so far:
In my understanding the controller actions should:
be as short as possible
take the request
execute required methods from injected services
build a response out of this
is a service itself
To accomplish a lightweight action, i try to encapsule the logic into a separate service which gets injected into the controller.
This works nicely expect for testing everything.
Here my current code:
Controller
class SearchController
{
// search_helper, request and templating are controller-injected
protected $search_helper;
protected $request;
protected $templating;
// ...
public function searchAction()
{
$searchterm = strtolower($this->request->query->get('q'));
$result = $this->search_helper->findSamples($searchterm);
// Found a single result. Redirect to this page
if (is_string($result))
{
return new RedirectResponse($result, 301);
}
return new Response($this->templating->render('AlbiSampleBundle:Search:index.html.twig', array('results' => $result)));
}
}
SearchService
class SearchHelper
{
// doctrine, session and min_query_len are controller-injected
protected $doctrine;
protected $session;
protected $min_query_len;
// ...
public function findSamples($searchterm)
{
if (strlen($searchterm) < $this->min_query_len)
{
$msg = 'Your search must contain at least 3 characters!';
$this->session->getFlashBag()->add('error', $msg);
return false;
}
$em = $this->doctrine->getManager();
$results = $em->getRepository('AlbiSampleBundle:Sample')->findPossibleSamples($searchterm);
// Execute a more advanced search, if std. search don't delivers a result
// ...
return $results;
}
}
How can i test this code correctly?
The repository is tested with phpunit_db and a inmemory sqlite database ✓
The action can be tested through a simple functional test ✓
What's left is the logic in the search-service. e.g. the findSamples method
My first thought was to mock the dependencies (in fact that was one of the main aspects in separating the dependencies), but you not only have to mock the doctrine object, but also the entitymanager and the repository.
$em = $this->doctrine->getManager();
$results = $em->getRepository('AlbiSampleBundle:Sample')->findPossibleSamples($searchterm);
I think there must be a better solution. Not only would this mocking need many LOCs, it also doesn't feel right. The test would be unnecessarily coupled really tight to the SUT.
EDIT
Here is a sample test i came up with. Using mock objects.
The test won't work. I realized it would take much more mock-objects and i got the feeling this isn't the right way.
The test fails because SessionMock->getFlashbag doesn't return a flashbag with add method.
doctrine->getManager returns no EntityManager. The EntityManager has no getRepository method. And the repository is missing findPossibleSamples.
class SearchHelperTest extends \PHPUnit_Framework_TestCase
{
private $router;
private $session;
private $doctrine;
public function setUp()
{
parent::setUp();
// ...
}
public function testSearchReturnValue()
{
$search_service = $this->createSearchHelper();
$this->assertFalse($search_service->findSamples('s'));
}
protected function createSearchHelper()
{
return new SearchHelper($this->doctrine, $this->router, $this->session, 3);
}
protected function getDoctrineMock()
{
return $this->getMock('Doctrine\Bundle\DoctrineBundle\Registry', array('getManager'), array(), '', false);
}
protected function getSessionMock()
{
return $this->getMock('Symfony\Component\HttpFoundation\Session\Session', array('getFlashBag'), array(), '', false);
}
protected function getRouterMock()
{
return $this->getMock('Symfony\Component\Routing\Router', array('generate'), array(), '', false);
}
}
Hope the community can help me, writing well tested code :)
cheers
For your specific example I would argue that the validation of the $searchterm doesn't really belong in your service - at the very least a service should never depend on the session. There are ways you could move the session out of the service and leave the validation in but personally I would use symfony validation for this i.e. have a SampleSearchType for the form that uses itself as the data class and hang the validation off that in validation.yml (or using annotations as appropriate).
Once that validation is taken out, what's left from your question is another findX() method to be added to the repository (there's no reason why repository methods can't call and build on each other) which you already know how to test.
Having said that, I still agree that with Symfony there is a general issue of how to test services in isolation from injected services. With respect to testing in isolation from the persistence layer I've avoiding trying to do this so far. My business layer services are so tightly coupled with the persistence layer that the cost of trying to test them independently is not worthwhile (what logic there is consists mainly of making related db updates or sending emails for which symfony provides it's own decoupling mechanism). I'm not sure if this is because I'm doing it wrong or because the apps I'm working on are light on business logic!
To isolate service tests from dependencies other than persistence I've tried:
Overriding service classes with mocked versions in the configuration. Issue - you don't want to do this for functional tests which means you have to have tests scripts which update the configuration and/or change the config to run individual tests. Advantage - you can run the same test as an isolated unit test and as an integration test by flipping the config
(Warning: nasty hack!) providing a setter method to replace an injected service with a mocked version from the test program.
(Not yet tried) Directly instantiate the service being tested, passing mock dependencies in on construction.
With respect to isolating from the persistence layer the only approach that makes sense to me is to abstract it out of the service to be tested into a wrapper service which contains no additional logic. The wrapper service could then be mocked using one of the above approaches (or hopefully a better solution that someone else is going to suggest?!)
EDIT: to address the issue of complexity of mocking dependencies - very occasionally this may be unavoidable but in general this is an indication that the design needs revisiting. This is one of the strengths of TDD - it strongly encourages simplified design and decoupling of components:
No service should need to be dependent upon the session object. This is not good practice and can always be avoided. Worst case the example method could return mixed values and if the result is not an array it's assumed to be an error message, although there are better alternatives.
Sometimes dependencies are unnecessary (code more naturally belongs elsewhere) or too general (I would question the necessity of injecting high level objects like doctrine or e.g. the container into anything other than test helpers).
If there is a complex dependency to mock (such as on multiple classes from the persistence layer) abstract it out into a wrapper which is far simpler to mock than the complex dependency.

Entity Framework reverting changes

I am develloping a web form that has a wizard with 4 steps:
On each step I'me creating new entities generated from a database.
The problem is that being a wizzard, the user can change the properties of the controls that will originate the values to be stored.
So I need to release the created entity objects or return that entity values to the original rows stored on the database.
How can I do this.
Should'n it work if I set each created entity object to null?
By the way this is how I'm doing it:
entities = new Entities();
...
Client client = new Client();
client.name = tbxName.text
...
entities.SaveChanges();
entities.Connection.Close();
So If this code is executed on the 2nd wizard part of a wizard of 3 parts and I go back and fowrward through this set more the once the client creating runs more than once, so there's my problem.
So how can I unCreate it :-P
Thannks!!!
If you are building wizard you must manage it as single operation. It means that you have to store built entity graph in the session and save it only if whole wizard is completed and confirmed. Your step logic also must check if related data are already present in the entity graph and use them instead of creating new one.
If your using Entity Framework, why not implement the Unit Of Work pattern? Each part of your wizard builds the UoW and the "final step" commits the unit of work.
There was an article called "The Unit Of Work Pattern And Persistence Ignorance" in MSDN magazine a few years ago that explains the concept.
This is the way I do it:
1- Create a place where you can manage your Session variables :
public class SessionObjects { }
2- I save my ObjectContext in the Session so I create a property to manage it in the mentioned class :
public static ObjectContextEntities ObjectContextEntities
{
get
{
return (ObjectContextEntities)HttpContext.Current.Session["ObjectContextEntities"];
}
set
{
HttpContext.Current.Session["ObjectContextEntities"] = value;
}
}
3- Initialize the ObjectContext on the wizard's start and dispose it on its end:
void StartWizard()
{
SessionObject.ObjectContextEntities = new ObjectContextEntities();
}
void StartWizard()
{
SessionObject.ObjectContextEntities = new ObjectContextEntities();
}
void EndWizard()
{
((ObjectContextEntities)SessionObject.ObjectContextEntities).Dispose();
}
4- To save wizard result to the database you can call:
void SaveWizard()
{
((ObjectContextEntities)SessionObject.ObjectContextEntities).SaveAllChanges();
}
5- To reset wizard simply call EndWizard then StartWizard .
I guess you know how to manage your ObjectEntity objects and in the ObjectContext so you can continue from here by your self ..

ASP.Net Entity Framework Repository & Linq

My scenario:
This is an ASP.NET 4.0 web app programmed via C#
I implement a repository pattern. My repositorys all share the same ObjectContext, which is stored in httpContext.Items. Each repository creates a new ObjectSet of type E. Heres some code from my repository:
public class Repository<E> : IRepository<E>, IDisposable
where E : class
{
private DataModelContainer _context = ContextHelper<DataModelContainer>.GetCurrentContext();
private IObjectSet<E> _objectSet;
private IObjectSet<E> objectSet
{
get
{
if (_objectSet == null)
{
_objectSet = this._context.CreateObjectSet<E>();
}
return _objectSet;
}
}
public IQueryable<E> GetQuery()
{
return objectSet;
}
Lets say I have 2 repositorys, 1 for states and 1 for countrys and want to create a linq query against both. Note that I use POCO classes with the entity framework. State and Country are 2 of these POCO classes.
Repository stateRepo = new Repository<State>();
Repository countryRepo = new Repository<Country>();
IEnumerable<State> states = (from s in _stateRepo.GetQuery()
join c in _countryRepo.GetQuery() on s.countryID equals c.countryID
select s).ToList();
Debug.WriteLine(states.First().Country.country)
essentially, I want to retrieve the state and the related country entity. The query only returns the state data... and I get a null argument exception on the Debug.WriteLine
LazyLoading is disabled in my .edmx... thats the way I want it.
You're doing a join without retrieving anything from it. There are multiple solutions to your problem:
Use Include to load the dependent entities: from s in ((ObjectSet<State>) _stateRepo.GetQuery).Include("Country"). The problem with this approach is that you should expose the ObjectSet directly rather than as a IQueryable if you want to avoid casting.
Use context.LoadProperty(states.First(), s => s.Country) to explicitly load the Country from the database for a given state.
Select both entities in the query: from s in ... join c ... select new { s, c }. You won't be able to access directly the state's Country property but you have it in the anonymous type.
Enable lazy loading.
Your repository implementation is very similar to mine, especially the way you are storing the ObjectContext. It works fine for me, so I don't think it's a conceptual problem.
Try using a static objectcontext (no wrapper) just to see if that fixes the problem. Perhaps there is a bug in your ContextHelper which causes your context to get disposed and recreated.

Resources