У меня странная ситуация с использованием метамоделей Hibernate / JPA.Наше зрелое веб-приложение Wicket 7 работает нормально, но через некоторое время некоторые значения полей метамодели становятся равными нулю.Это всегда один и тот же преступник (в приложении несколько сотен сущностей, и он всегда один).Генератор метамодели создает это для класса ProductGroup:
@Generated(value = "org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor")
@StaticMetamodel(ProductGroup.class)
public abstract class ProductGroup_ extends com.sw.generic.data.AbstractBusinessEntity_ {
public static volatile SingularAttribute<ProductGroup, String> serviceLevelDescription;
public static volatile SingularAttribute<ProductGroup, String> supportDescription;
public static volatile SingularAttribute<ProductGroup, String> code;
public static volatile SingularAttribute<ProductGroup, Boolean> useProductSubgroupL2;
public static volatile SingularAttribute<ProductGroup, String> description;
public static volatile SingularAttribute<ProductGroup, Boolean> useSupportSubgroupL2;
public static volatile SingularAttribute<ProductGroup, String> productSubgroupLevel1Description;
public static volatile SingularAttribute<ProductGroup, String> serviceLevelGroupDescription;
public static volatile SingularAttribute<ProductGroup, String> productSubgroupLevel2Description;
public static volatile SingularAttribute<ProductGroup, String> supportSubgroupLevel1Description;
public static volatile SingularAttribute<ProductGroup, String> supportSubgroupLevel2Description;
}
Место, где мы получаем нулевые указатели, - это перечисление, которое сохраняет атрибут в виде поля:
public class DefaultProductGroupEntityDescriptionLabel extends OptionalLabel {
private static final long serialVersionUID = 1L;
public static enum ProductGroupEntityType {
SUPPORT_SERVICE( "product.group.label.support.default", ProductGroup_.supportDescription ),
SUPPORT_SUBGROUP_L1( "product.group.label.support.subgroup.l1.default", ProductGroup_.supportSubgroupLevel1Description ),
SUPPORT_SUBGROUP_L2( "product.group.label.support.subgroup.l2.default", ProductGroup_.supportSubgroupLevel2Description ),
PRODUCT_SUBGROUP_L1( "product.group.label.product.subgroup.l1.default", ProductGroup_.productSubgroupLevel1Description ),
PRODUCT_SUBGROUP_L2( "product.group.label.product.subgroup.l2.default", ProductGroup_.productSubgroupLevel2Description ),
SERVICE_LEVEL( "product.group.label.servicelevel.default", ProductGroup_.serviceLevelDescription ),
SERVICE_LEVEL_TYPE( "product.group.label.serviceleveltype.default", ProductGroup_.serviceLevelGroupDescription );
private String m_singularKey;
private String m_pluralKey;
private Attribute<ProductGroup,String> m_attribute;
private ProductGroupEntityType( String p_key, Attribute<ProductGroup,String> p_attribute ) {
this( p_key, p_key, p_attribute );
}
private ProductGroupEntityType( String p_singularKey, String p_pluralKey, Attribute<ProductGroup,String> p_attribute ) {
m_singularKey = p_singularKey;
m_pluralKey = p_pluralKey;
m_attribute = p_attribute;
}
public String getSingularKey() {
return m_singularKey;
}
public String getPluralKey() {
return m_pluralKey;
}
public Attribute<ProductGroup,String> getAttribute() {
return m_attribute;
}
public String getDescription( ProductGroup p_group ) {
try {
return BeanUtils.getSimpleProperty( p_group, getAttribute().getName() ); // <-- This is where the NPE occurs!
} catch( Exception e_e ) {
throw new IllegalStateException( name() + " has a bad property setting - cannot get Vendor property " + getAttribute().getName(), e_e );
}
}
}
protected IModel<ProductGroupEntityType> m_typeModel;
protected IModel<String> m_baseModel;
/**
* @param p_id
*/
public DefaultProductGroupEntityDescriptionLabel( String p_id, ProductGroupEntityType p_type ) {
this( p_id, Model.of( p_type ) );
}
/**
* @param p_id
*/
public DefaultProductGroupEntityDescriptionLabel( String p_id, IModel<ProductGroupEntityType> p_typeModel ) {
super( p_id );
m_typeModel = p_typeModel;
}
@Override
public void detachModels() {
super.detachModels();
m_typeModel.detach();
m_baseModel.detach();
}
protected void onInitialize() {
super.onInitialize();
m_baseModel = createBaseModel();
setDefaultModel( createDescriptionModel( m_baseModel ) );
add( new MultilineTooltipBehavior( new LoadableDetachableModel<String>() {
private static final long serialVersionUID = 1L;
@Override
protected String load() {
return getString( m_typeModel.getObject().getSingularKey() );
}
} ) );
}
@Override
protected void onDetach() {
super.onDetach();
if( m_baseModel != null ) {
m_baseModel.detach();
}
}
/**
* Creates the base model for getting the description
* @return a model for getting the description. This version gets the default description from the property settings.
*/
protected IModel<String> createBaseModel() {
return new LoadableDetachableModel<String>() {
private static final long serialVersionUID = 1L;
@Override
protected String load() {
return getString( isPlural() ? m_typeModel.getObject().getPluralKey() : m_typeModel.getObject().getSingularKey() );
}
};
}
/**
* Allows subclasses to return a modified version of the model, so the base description can be part of a more complex description.
* @param p_baseDescriptionModel
* @return the base model unchanged by default
*/
protected IModel<String> createDescriptionModel( IModel<String> p_baseDescriptionModel ) {
return p_baseDescriptionModel;
}
/**
* If true, plural versions of the key will be used.
* @return false by default.
*/
public boolean isPlural() {
return false;
}
}
Вызов ProductGroupEntityType ::getDescription вызывает ошибку, но не при первоначальном развертывании, а спустя несколько часов:
Caused by: java.lang.NullPointerException
at com.sw.system4.ui.product.group.DefaultProductGroupEntityDescriptionLabel$ProductGroupEntityType.getDescription(DefaultProductGroupEntityDescriptionLabel.java:64)
at com.sw.system4.ui.product.group.ProductGroupEntityDescriptionModel.load(ProductGroupEntityDescriptionModel.java:57)
at com.sw.system4.ui.product.group.ProductGroupEntityDescriptionModel.load(ProductGroupEntityDescriptionModel.java:17)
at org.apache.wicket.model.LoadableDetachableModel.getObject(LoadableDetachableModel.java:135)
at org.apache.wicket.model.StringResourceModel.getString(StringResourceModel.java:454)
at org.apache.wicket.model.StringResourceModel$AssignmentWrapper.load(StringResourceModel.java:271)
Этот код используется постоянно и в основном не вызывает этой проблемы.
Остановка иперезапуск сервера Tomcat, на котором он работает, заставляет его работать снова.
Я подозреваю, что если я изменю поле атрибута ProductGroupEntityType с Attribute на String, а затем передам в attribute.getName (), так что это не приведет к сохранениюСсылка, которая бы исправить вещи, но может ли кто-нибудь сказать мне, почему это происходит в первую очередь?Заранее спасибо.
Hibernate 5.1.14, Java 8