2011-05-13 4 views
5

유효한 @Embeddable 클래스가 무엇인지 설명하는 JPA 사양에는 무엇이 있습니까? 나는 보았지만 아무것도 찾을 수 없습니다.@Embeddable 클래스를 비공개로 설정할 수 있습니까?

최대 절전 모드 (3.6.4.Final) 및 스프링 (3.0.5)에서 EclipseLink (2.3.0-M7 - 전체 빌드 문자열 2.3.0.v20110429-r9282)를 사용하고 문서화 된대로 내 응용 프로그램을 설정했습니다 EclipseLink/Examples/MOXy/Spring/JAXBAnnotations에 있습니다. 다른 모든 것은 현재 작동하고 있으며 몇 달 동안 지속되었습니다. @Embeddable 클래스를 추가하고 NPE를 받기 시작했습니다.

다음은 EclipseLink 라이브러리 및 구성을 제거하고 (최대 절전 모드의 구현으로 되돌려 놓았 기 때문에) EclipseLink의 버그 일 경우 누군가가 이것을 재현하는 데 사용할 수있는 몇 가지 예제 코드입니다. 그러면 더 이상 NPE를 얻지 못합니다.

테스트 클래스 Broken.java

package x.y.z.model; 

import javax.persistence.*; 
import javax.xml.bind.annotation.*; 
import java.io.Serializable; 

@Entity 
public class Broken { 
    @EmbeddedId 
    private Pk pk = new Pk(); 

    @Embeddable 
    private static class Pk implements Serializable { 
     @ManyToOne 
     private String foo; 

     public String getFoo() { 
      return this.foo; 
     } 
     public void setFoo(String foo) { 
      this.foo = foo; 
     } 
    } 
} 

내가 가진 스프링 빈 설정은 다음과 같습니다

<bean id="jaxbMarshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller"> 
    <property name="contextPath" value="x.y.z.model"/> 
</bean> 
<bean id="xmlHelper" class="x.y.xml.XMLHelper"> 
    <property name="marshaller" ref="jaxbMarshaller"/> 
</bean> 

마지막으로 내가 추가 한 다음 (XMLHelper 클래스에 대한 위의 링크 참조) ~ jaxb.index :

봄 응용 프로그램을 시작할 때
Broken 

, 나는 다음과 같은 예외를 얻을 :

ERROR org.springframework.test.context.TestContextManager 324 - Caught exception while allowing TestExecutionListener [org.springframewor[email protected]9b601d] to prepare test instance [[email protected]] 
java.lang.IllegalStateException: Failed to load ApplicationContext 
    at org.springframework.test.context.TestContext.getApplicationContext(TestContext.java:308) 
    at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:109) 
    at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:75) 
    at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:321) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:220) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:301) 
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:303) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:240) 
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49) 
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193) 
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52) 
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191) 
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42) 
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184) 
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28) 
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) 
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) 
    at org.junit.runners.ParentRunner.run(ParentRunner.java:236) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:180) 
    at org.apache.maven.surefire.junit4.JUnit4TestSet.execute(JUnit4TestSet.java:35) 
    at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:115) 
    at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:97) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
    at java.lang.reflect.Method.invoke(Method.java:597) 
    at org.apache.maven.surefire.booter.ProviderFactory$ClassLoaderProxy.invoke(ProviderFactory.java:103) 
    at $Proxy0.invoke(Unknown Source) 
    at org.apache.maven.surefire.booter.SurefireStarter.invokeProvider(SurefireStarter.java:150) 
    at org.apache.maven.surefire.booter.SurefireStarter.runSuitesInProcess(SurefireStarter.java:91) 
    at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:69) 
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jaxbMarshaller' defined in class path resource [applicationContext.xml]: Invocation of init method failed; nested exception is org.springframework.oxm.UncategorizedMappingException: Unknown JAXB exception; nested exception is 
javax.xml.bind.JAXBException 
- with linked exception: 
[java.lang.NullPointerException] 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1420) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456) 
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:291) 
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:288) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:190) 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:580) 
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:895) 
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:425) 
    at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:84) 
    at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:1) 
    at org.springframework.test.context.TestContext.loadApplicationContext(TestContext.java:280) 
    at org.springframework.test.context.TestContext.getApplicationContext(TestContext.java:304) 
    ... 31 more 
Caused by: org.springframework.oxm.UncategorizedMappingException: Unknown JAXB exception; nested exception is javax.xml.bind.JAXBException 
- with linked exception: 
[java.lang.NullPointerException] 
    at org.springframework.oxm.jaxb.Jaxb2Marshaller.convertJaxbException(Jaxb2Marshaller.java:668) 
    at org.springframework.oxm.jaxb.Jaxb2Marshaller.getJaxbContext(Jaxb2Marshaller.java:335) 
    at org.springframework.oxm.jaxb.Jaxb2Marshaller.afterPropertiesSet(Jaxb2Marshaller.java:317) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1477) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1417) 
    ... 44 more 
Caused by: javax.xml.bind.JAXBException 
- with linked exception: 
[java.lang.NullPointerException] 
    at org.eclipse.persistence.jaxb.JAXBContext$ContextPathInput.createContextState(JAXBContext.java:661) 
    at org.eclipse.persistence.jaxb.JAXBContext$ContextPathInput.createContextState(JAXBContext.java:621) 
    at org.eclipse.persistence.jaxb.JAXBContext.<init>(JAXBContext.java:134) 
    at org.eclipse.persistence.jaxb.JAXBContextFactory.createContext(JAXBContextFactory.java:108) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
    at java.lang.reflect.Method.invoke(Method.java:597) 
    at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:128) 
    at javax.xml.bind.ContextFinder.find(ContextFinder.java:249) 
    at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:372) 
    at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:337) 
    at org.springframework.oxm.jaxb.Jaxb2Marshaller.createJaxbContextFromContextPath(Jaxb2Marshaller.java:355) 
    at org.springframework.oxm.jaxb.Jaxb2Marshaller.getJaxbContext(Jaxb2Marshaller.java:328) 
    ... 47 more 
Caused by: java.lang.NullPointerException 
    at org.eclipse.persistence.jaxb.javamodel.Helper.isBuiltInJavaType(Helper.java:261) 
    at org.eclipse.persistence.jaxb.compiler.AnnotationsProcessor.shouldGenerateTypeInfo(AnnotationsProcessor.java:1526) 
    at org.eclipse.persistence.jaxb.compiler.AnnotationsProcessor.processClass(AnnotationsProcessor.java:1029) 
    at org.eclipse.persistence.jaxb.compiler.AnnotationsProcessor.processAdditionalClasses(AnnotationsProcessor.java:994) 
    at org.eclipse.persistence.jaxb.compiler.AnnotationsProcessor.postBuildTypeInfo(AnnotationsProcessor.java:576) 
    at org.eclipse.persistence.jaxb.compiler.AnnotationsProcessor.processClassesAndProperties(AnnotationsProcessor.java:230) 
    at org.eclipse.persistence.jaxb.compiler.Generator.<init>(Generator.java:104) 
    at org.eclipse.persistence.jaxb.JAXBContext$ContextPathInput.createContextState(JAXBContext.java:658) 
    ... 60 more 

나는 개인공공 (그리고는 EclipseLink를 사용)의 NPE 더 이상에서 @Embeddable 클래스를 변경하는 경우 발생합니다. 그래서 나는 작동하지만 왜 그 이유를 알고 싶은 해결책이 있습니다.

+0

정말 좋은 발견. +1 –

답변

3

JPA 2.0 Specification은 포함 할 수있는 클래스가 엔터티에 대해 명시된 동일한 요구 사항을 준수해야한다고 명시합니다. 이러한 요구 사항은 규격의 2.1 절에 명시되어, 그들은 것을 주장 :

  • 엔티티 클래스는 인수 없음의 생성자가 있어야합니다. 다른 생성자도있을 수 있습니다. 인수가없는 생성자는 public 또는 protected이어야합니다.
  • 엔터티 클래스 은 최상위 클래스이어야합니다. enum 또는 인터페이스는 엔터티로 지정된 이 아니어야합니다.
  • 엔티티 클래스는 final이어서는 안됩니다. 엔티티 클래스의 메소드 나 영구 인스턴스 변수는 final이 될 수 없습니다.

따라서, 나는 영향을 당신이 임베드 클래스가 톱 레벨의 클래스가 플러스가 개인이라는 사실이 아니라고 할 수 있다고 생각합니다.

시도해 볼 수도 있습니다. 이것이 이유가 아니더라도 표준의 권장 사항을 따르는 것이 좋을 수도 있습니다. 그렇지 않으면 코드가 해당 표준을 준수한다는 것을 보증 할 수 없습니다.

+0

+1 감사합니다. 최상위 클래스는 _private_ 할 수 없으므로 _top-level class_ 요구 사항에 대한 답을 얻을 수 있다고 생각합니다. 몇 가지 다른 JPA 2.0 공급 업체와 시도해보고이를 처리하는 방법을 살펴 보겠습니다. 나는 표준에 부합하는 것에 동의한다. 나는 왜 내가 처음에 클래스 _private_를 선언했는지 확신 할 수 없다! – andyb

1

이것은 아마도 기본 impl이 다른 것보다 Embeddable 클래스를로드하는 방법에 더 의존합니다. EclipseLink 2.0.0 (해당 버전의 src를 찾을 수 없음)의 코드를 보면 NPE이 클래스에 대한 메타 데이터에 있음을 알 수 있습니다.

교육적인 추측을해야한다면 Hibernate가 클래스로드 (또는 바이트 코드를 통해)를로드하는 다른 메커니즘을 사용하는 동안 EclipseLink가 자동으로 클래스 로딩 (NPE를 유발 함)에 실패했다고 말하고 싶다.

+0

+1 감사합니다. 그래서, _ 이론적으로 당신은 이것이 이클립스 링크의 버그라는 데 동의합니까? – andyb

+0

edarlozo의 대답에 따르면, 클래스가 최상위 레벨이어야한다는 요구 사항이므로 유일한 "버그"는 EclipseLink의 오류보고입니다. –

관련 문제