Java tutorial
/* * Copyright (c) 2014 Alexander Gulko <kirhog at gmail dot com>. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.fastmongo.odm.dbobject.mapping.core; import com.mongodb.DBObject; import org.fastmongo.odm.document.support.LazyCollectionProxy; import org.fastmongo.odm.document.support.LazyProxy; import org.fastmongo.odm.model.TestDomainObjectsFixtures; import org.fastmongo.odm.model.TestObjectUtils; import org.fastmongo.odm.model.user.Attribute; import org.fastmongo.odm.model.user.Group; import org.fastmongo.odm.model.user.User; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.testng.AbstractTestNGSpringContextTests; import org.testng.Assert; import org.testng.annotations.Test; import java.lang.ref.Reference; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.List; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.LockSupport; import static org.fastmongo.odm.dbobject.mapping.core.ConverterHelper.getValue; import static org.fastmongo.odm.model.FixtureUtils.nextId; /** * @author Alexander Gulko */ @ContextConfiguration("classpath:common-converter-test-context.xml") public class DbObjectToDomainConverterTest extends AbstractTestNGSpringContextTests { @Autowired private DomainToDbObjectConverter toDbConverter; @Autowired private DbObjectToDomainConverter fromDbConverter; @Autowired private TestMongoTemplate mongoTemplate; @Test public void testFromDbObject() { Group expected = createGroup(); DBObject db = toDbConverter.toDbObject(expected); Assert.assertNotNull(db); Group actual = fromDbConverter.fromDbObject(db, Group.class); Assert.assertTrue(TestObjectUtils.equals(actual, expected)); } @Test public void testCyclicDependencies() { DBObject db = toDbConverter.toDbObject(createGroup()); Assert.assertNotNull(db); Group topGroup = fromDbConverter.fromDbObject(db, Group.class); User user = topGroup.getUsers().iterator().next(); Assert.assertTrue(user.getGroup() instanceof LazyProxy); Assert.assertTrue(user.getGroup() instanceof Group); // asm proxy String id = user.getGroup().getId(); // load id through loader Assert.assertEquals(id, db.get("id")); // still proxy Assert.assertTrue(user.getGroup() instanceof LazyProxy); Assert.assertTrue(user.getGroup() instanceof Group); //noinspection ResultOfMethodCallIgnored user.getGroup().toString(); // touch lazy and replace proxy Assert.assertFalse(user.getGroup() instanceof LazyProxy); Assert.assertTrue(user.getGroup() instanceof Group); Group sameGroup = user.getGroup(); Assert.assertTrue(TestObjectUtils.equals(topGroup, sameGroup)); } @Test public void testEscapeAndUnescape() { String keyWithPoint = "key.with.point"; User user = new User(); user.setAttribute(keyWithPoint, new Attribute()); DBObject db = toDbConverter.toDbObject(user); DBObject attributes = getValue(db, "attributeMap"); Assert.assertEquals(attributes.keySet().size(), 1); String escapedKey = attributes.keySet().iterator().next(); Assert.assertFalse(escapedKey.contains(".")); Assert.assertEquals(escapedKey, ConverterHelper.escape(keyWithPoint)); User actualUser = fromDbConverter.fromDbObject(db, User.class); Assert.assertEquals(actualUser.getAttributeMap().size(), 1); String unescapedKey = actualUser.getAttributeMap().keySet().iterator().next(); Assert.assertTrue(unescapedKey.contains(".")); Assert.assertEquals(unescapedKey, ConverterHelper.unescape(escapedKey)); Assert.assertEquals(unescapedKey, keyWithPoint); } @Test public void testGarbageCollectedRootObjects() { DBObject db; { Group root = TestDomainObjectsFixtures.createGroup(5, 10); db = toDbConverter.toDbObject(root); } Group root = fromDbConverter.fromDbObject(db, Group.class); Reference<Group> ref = new WeakReference<>(root); List<User> list = root.getUsers(); Assert.assertNotNull(ref.get()); //noinspection UnusedAssignment root = null; Runtime.getRuntime().gc(); int limit = 10; int wait = 0; while (ref.get() != null && wait++ < limit) { if (ref.get() == null) { break; } LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(100)); // wait a bit } Assert.assertNull(ref.get()); // touch proxy, it should not throw NPE as before Assert.assertTrue(!list.isEmpty()); } @Test public void test_collectionLoader() { Group group = new Group(nextId() + ""); group.setUsers(new ArrayList<User>()); group.getUsers().add(new User(nextId())); group.getUsers().add(new User(nextId())); group.getUsers().add(new User(nextId())); mongoTemplate.saveGroup(group); DBObject db = mongoTemplate.findById(Group.class, group.getId()); Group actual = fromDbConverter.fromDbObject(db, Group.class); Assert.assertTrue(actual.getUsers() instanceof LazyCollectionProxy); Assert.assertFalse(actual.getUsers().isEmpty()); Assert.assertTrue(actual.getUsers() instanceof LazyCollectionProxy); // still proxy Assert.assertEquals(actual.getUsers().size(), group.getUsers().size()); Assert.assertTrue(actual.getUsers() instanceof LazyCollectionProxy); // still proxy actual.getUsers().iterator(); Assert.assertFalse(actual.getUsers() instanceof LazyCollectionProxy); // not a proxy } private Group createGroup() { Group group = TestDomainObjectsFixtures.createGroup(2, 3); mongoTemplate.saveGroup(group); return group; } }