Кулак это не тот объект, но это неправильная ссылка, поскольку я поставил диагноз проблемы.GWT RequestFactory вызывающий сеттер на неправильном объекте
У меня есть редактор, где я редактирую объект, который содержит другой редактор списка из большего количества компонентов.
У меня есть TagCollectionProxy, и он содержит список объектов TagProxy. Проблема возникает, когда я сохраняю TagCollectionProxy со связанными объектами List. Мой локатор объектов ищет объект в базе данных и устанавливает значение, но тогда у меня нет ссылки на этот объект. Это новое, и я не уверен, почему это происходит сейчас.
Это сообщение отладки, когда я вызываю сохранение объекта. Я поместил сообщение в класс Tag на setValue, и вы можете видеть, что я устанавливаю правильное значение для объекта домена. Идентификатор совпадает. Проблема возникает в следующем сообщении для моего сохранения (TagCollection) в моем классе dao. Я повторяю сущности и печатаю значение, но значение не изменилось для этого объекта.
2014-08-29T15:34:15.912-0500|INFO: Setting value Tag2asdfasdfasdfasdf for id 294 Reference [email protected]
2014-08-29T15:34:15.944-0500|INFO: Tag name => asdfasdf Tag value => Tag2 id => 294 ref => [email protected]
2014-08-29T15:34:15.944-0500|INFO: Id of tag is 294
Заранее благодарим за любую помощь, я теряю волосы на минуту.
Это моя деятельность, которая сохраняет объект. Обратите внимание, что я сохраняю TagCollectionProxy, который содержит список тегов.
public class TagCollectionEditActivity extends AbstractActivity<TagCollectionEditView> implements
TagCollectionEditView.Presenter {
private Receiver<Long> saveReceiver = new Receiver<Long>() {
@Override
public void onSuccess(Long response) {
logger.info("saved tagCollection with id of " + response);
clientFactory.getPlaceController().goTo(new TagCollectionsPlace());
}
public void onConstraintViolation(Set<ConstraintViolation<?>> violations) {
for (ConstraintViolation<?> violation : violations) {
logger.warning(violation.getMessage());
}
getDisplay().getEditorDriver().setConstraintViolations(violations);
}
public void onFailure(ServerFailure failure) {
logger.log(Level.SEVERE, "Failed to save tag collection " + failure.getMessage());
getDisplay().showError(failure);
}
};
private static final Logger logger = Logger.getLogger(TagCollectionEditActivity.class.getName());
private IClientFactory clientFactory;
private TagCollectionDaoRequest editContext = null;
public TagCollectionEditActivity(IClientFactory clientFactory) {
super(new TagCollectionEditView(clientFactory.getResources(), clientFactory.getEventBus()));
this.clientFactory = clientFactory;
}
@Override
protected void bindToView() {
getDisplay().setPresenter(this);
final TagCollectionEditPlace place = (TagCollectionEditPlace) getPlace();
Long tagCollectionId = place.getTagCollectionId();
if (tagCollectionId == null) {
createTagCollection();
} else {
findCollection(tagCollectionId);
}
}
private void findCollection(Long tagCollectionId) {
clientFactory.tagCollectionRequest().find(tagCollectionId).with(getEntityProperties())
.fire(new Receiver<TagCollectionProxy>() {
@Override
public void onSuccess(TagCollectionProxy tagCollection) {
editContext = clientFactory.tagCollectionRequest();
editContext.save(tagCollection).with(getDisplay().getEditorDriver().getPaths()).to(saveReceiver);
getDisplay().getEditorDriver().edit(tagCollection, editContext);
GWT.log("Context is " + editContext.hashCode());
}
});
}
private void createTagCollection() {
editContext = clientFactory.tagCollectionRequest();
TagCollectionProxy tagCollection = editContext.create(TagCollectionProxy.class);
editContext.save(tagCollection).with(getDisplay().getEditorDriver().getPaths()).to(saveReceiver);
tagCollection.setTags(new ArrayList<TagProxy>());
getDisplay().getEditorDriver().edit(tagCollection, editContext);
}
@Override
public void onSave() {
RequestContext context = getDisplay().getEditorDriver().flush();
context.fire();
}
public String[] getEntityProperties() {
return new String[] { "tags", "deviceFamily" };
}
@Override
public void onCancel() {
clientFactory.getPlaceController().goTo(new TagCollectionsPlace());
}
}
Вот мой тег коллекция прокси, где я определяю мой DomainEntityLocator
@ProxyFor(value = TagCollection.class, locator = DomainEntityLocator.class)
public interface TagCollectionProxy extends DomainEntityProxy {
public List<TagProxy> getTags();
public void setTags(List<TagProxy> tags);
public DeviceFamilyProxy getDeviceFamily();
public void setDeviceFamily(DeviceFamilyProxy deviceFamily);
}
Вот мой локатор, который использует базу данных для поиска объектов с помощью JPA EntityManager.
public class DomainEntityLocator extends Locator<DomainEntity, Long> {
private static EntityManager em = null;
static {
Context initCtx;
try {
initCtx = new InitialContext();
// perform JNDI lookup to obtain container-managed entity manager
em = (javax.persistence.EntityManager) initCtx.lookup("java:comp/env/persistence/DomainEntityManager");
} catch (NamingException e) {
throw new RuntimeException("Unable to get the domain entity manager");
}
}
public DomainEntityLocator() {
}
@Override
public DomainEntity create(Class<? extends DomainEntity> clazz) {
try {
return clazz.newInstance();
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
@Override
public DomainEntity find(Class<? extends DomainEntity> clazz, Long id) {
return em.find(clazz, id);
}
@Override
public Class<DomainEntity> getDomainType() {
return DomainEntity.class;
}
@Override
public Long getId(DomainEntity domainObject) {
return domainObject.getId();
}
@Override
public Class<Long> getIdType() {
return Long.class;
}
@Override
public Object getVersion(DomainEntity domainObject) {
return 0;
}
}
Update
После некоторого исследования, я понял, что JPA на стороне сервера был виноват в моей проблеме. Я пришел к выводу, что DomainEntityLocator извлекает объект, но не переносит его в транзакцию. Таким образом метод DomainEntityLocator # find() будет извлекать объект, и ServiceLayer будет изменять значение для объекта. Проблема заключается в том, что метод find не заключен в транзакцию, и поскольку управляющий объект, который я получаю, не управляется, диспетчер сущности не очищает изменения. Поэтому я не вижу обновлений значения.
по теме Вопрос # 2
Есть общий шаблон для добавления управления транзакциями в Entity локатор, так что он будет сохраняться объектом после того, как запрос на завод вызывает сеттер. Я использовал это с помощью простого фильтра сервлетов, но для проекта, над которым я работаю, требуется java ee для поддержания такой функциональности. Я не могу сделать DomainEntityLocator фасоном без статусов из-за того, как ServiceLayer будет искать его. Было бы лучше расширить RequestFactoryServlet и обернуть doPost в tranasction? Это кажется самой логичной идеей. Какие-либо предложения?
Еще раз спасибо Томас
Томас, благодарю вас за помощь. Я пришел к тому же выводу, что и после небольшой отладки. Моя первоначальная путаница, связанная с Chrome, не печатает всего сообщения сообщения в панели предварительного просмотра (отладочные инструменты). Мне нужно было копаться в панели заголовка, чтобы увидеть все исходящее сообщение. Я обновил вопрос с незначительным обновлением. Если вы знаете хорошее решение для упаковки Locator в транзакции, если это даже хорошая идея, пожалуйста, дайте мне знать. –
Обертка всего запроса/ответа в транзакции вызывает проблемы: семантика RF изменится, если вы это сделаете. Вам нужен шаблон «open session in view» (один «EntityManager» для каждого запроса/ответа), а затем охватите ваши транзакции к вашим методам обслуживания. –