JAXB가 목록에 대한 setter를 생성하지 않는 이유
XSD에서 JAXB 클래스를 생성 할 때 maxOccurs="unbounded"
다음과 같이 요소가 생성 된 getter 메서드 를 가져 오지만 setter 메서드는 없습니다.
/**
* Gets the value of the element3 property.
*
* <p>
* This accessor method returns a reference to the live list,
* not a snapshot. Therefore any modification you make to the
* returned list will be present inside the JAXB object.
* This is why there is not a <CODE>set</CODE> method for the element3 property.
*
* <p>
* For example, to add a new item, do as follows:
* <pre>
* getElement3().add(newItem);
* </pre>
*
*
* <p>
* Objects of the following type(s) are allowed in the list
* {@link Type }
*
*
*/
public List<Type> getElement3() {
if (element3 == null) {
element3 = new ArrayList<Type>();
}
return this.element3;
}
메소드 주석을 통해 어떻게 사용할 수 있는지 명확하게 알 수 있지만 내 질문은 다음과 같습니다.
JAXB가 Java Beans 규칙에 따라 setter를 생성하지 않는 이유는 무엇입니까? setter 메서드를 직접 작성할 수 있다는 것을 알고 있지만 생성 된 getter 메서드에서 제안 된 접근 방식에 이점이 있습니까?
이것은 내 XSD입니다.
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://www.example.org/DoTransfer/" targetNamespace="http://www.example.org/DoTransfer/">
<element name="CollectionTest" type="tns:CollectionTest"></element>
<complexType name="CollectionTest">
<sequence>
<element name="element1" type="string" maxOccurs="1" minOccurs="1"></element>
<element name="element2" type="boolean" maxOccurs="1" minOccurs="1"></element>
<element name="element3" type="tns:type" maxOccurs="unbounded" minOccurs="1" nillable="true"></element>
</sequence>
</complexType>
<complexType name="type">
<sequence>
<element name="subelement1" type="string" maxOccurs="1" minOccurs="1"></element>
<element name="subelement2" type="string" maxOccurs="1" minOccurs="0"></element>
</sequence>
</complexType>
</schema>
다음은 JAXB 사양의 정당성입니다-60 페이지.
디자인 노트 – List 속성에 대한 setter 메서드는 없습니다. getter는 참조로 List를 반환합니다. java.util.List에 정의 된 적절한 메소드를 사용하여 getter 메소드가 리턴 한 List에 항목을 추가 할 수 있습니다. JAXB 1.0에서이 디자인의 근거는 구현이 목록을 래퍼하고 목록에서 콘텐츠가 추가되거나 제거 될 때 검사를 수행 할 수 있도록하는 것입니다.
따라서 목록의 구현이 유효성 검사를 수행하기 위해 추가 / 제거를 재정의하는 경우 해당 '특별한'목록을 (예를 들어) ArrayList로 대체하면 이러한 검사가 무효화됩니다.
링크 : 목록에 대한 setter 없음
getter 메서드의 코드는 List가 생성되었는지 확인합니다. 해당하는 setter 가 없으므로 목록 요소의 모든 추가 또는 삭제는 "라이브" 목록 에서 이루어져야 합니다.
따옴표에서 getter 메소드를 사용할 때 setter가 없다고 말했듯이 목록의 새 인스턴스가 없으면 초기화됩니다.
그 후에는 추가하거나 제거해야 할 때
getElement3().add(Type);
업데이트 : 마샬링 null
및 빈 목록의 차이
목록이있는 예 null
@XmlRootElement(name = "list-demo")
public class ListDemo {
@XmlElementWrapper(name = "list")
@XmlElement(name = "list-item")
private List<String> list;
}
OUTPUT은
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<list-demo/>
목록이 비어있는 예
@XmlRootElement(name = "list-demo")
public class ListDemo {
@XmlElementWrapper(name = "list")
@XmlElement(name = "list-item")
private List<String> list = new ArrayList<String>();
}
OUTPUT은 다음과 같습니다.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<list-demo>
<list/>
</list-demo>
위의 Patrick의 우려에 동의하십시오. 생성 된 자바 클래스에 직접 코딩하는 경우 기꺼이 의무를 지지만 내성 도구를 사용하고 있는데 setter 또는 직접 액세스 가능한 멤버를 기대합니다. https://github.com/highsource/jaxb2-basics/wiki/JAXB2-Setters-Plugin 에서 XJC에 대한 플러그인을 사용하고 wsimport에 -B-Xsetter 인수를 추가하는 데 성공했습니다.
XJC plugin
특정 요구 사항에 대해 직접 작성할 수 있습니다 .
이 예제에서는 다음 에서 생성 된 모든 Java 파일 id
에 유형 필드 를 추가하려고합니다 .long
xjc
package com.ricston;
import java.io.IOException;
import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXException;
import com.sun.codemodel.JBlock;
import com.sun.codemodel.JCodeModel;
import com.sun.codemodel.JFieldVar;
import com.sun.codemodel.JMethod;
import com.sun.codemodel.JMod;
import com.sun.codemodel.JType;
import com.sun.codemodel.JVar;
import com.sun.tools.xjc.BadCommandLineException;
import com.sun.tools.xjc.Options;
import com.sun.tools.xjc.Plugin;
import com.sun.tools.xjc.outline.ClassOutline;
import com.sun.tools.xjc.outline.Outline;
public class XJCPlugin extends Plugin {
public final static String ID = "id";
public final static JType LONG_TYPE = new JCodeModel().LONG;
public final static String ID_GETTER = "getId";
public final static JType VOID_TYPE = new JCodeModel().VOID;
public final static String ID_SETTER = "setId";
@Override
public String getOptionName() {
return "Xexample-plugin";
}
@Override
public int parseArgument(Options opt, String[] args, int i)
throws BadCommandLineException, IOException {
return 1;
}
@Override
public String getUsage() {
return " -Xexample-plugin : xjc example plugin";
}
@Override
public boolean run(Outline model, Options opt, ErrorHandler errorHandler)
throws SAXException {
for (ClassOutline classOutline : model.getClasses()) {
JFieldVar globalId = classOutline.implClass.field(JMod.PRIVATE,
LONG_TYPE, ID);
JMethod idGetterMethod = classOutline.implClass.method(JMod.PUBLIC,
LONG_TYPE, ID_GETTER);
JBlock idGetterBlock = idGetterMethod.body();
idGetterBlock._return(globalId);
JMethod idSetterMethod = classOutline.implClass.method(JMod.PUBLIC,
VOID_TYPE, ID_SETTER);
JVar localId = idSetterMethod.param(LONG_TYPE, "_" + ID);
JBlock idSetterBlock = idSetterMethod.body();
idSetterBlock.assign(globalId, localId);
}
return true;
}
}
여기에 또 다른 예 :
Their are plugins available for generating hashCode
, equals
, setters-for-list
at github too.
References:
Answer to a question I had asked.
In case anyone is here looking for a way to get rid of those annoying lazy initializers in XJC-generated code... In my Maven POM, this goes under <build><plugins>
:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.8</version>
<executions>
<execution>
<id>remove-jaxb-generated-lazy-initializers</id>
<phase>process-sources</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<target if="${remove-jaxb-generated-lazy-initializers}">
<echo message="Running 'replaceregexp' target on generated sources..."/>
<echo message="This removes JAXB-generated lazy initializers from collection accessors."/>
<replaceregexp match="if \([\w_]+ == null\) \{\s+[\w_]+ = new ArrayList<[\w_]+>\(\);\s+\}\s+" replace="" flags="g">
<fileset dir="${project.build.directory}/generated-sources" includes="**/*.java"/>
</replaceregexp>
</target>
</configuration>
</execution>
</executions>
</plugin>
For setters, I'm also adding @lombok.Setter
to certain classes using org.jvnet.jaxb2_commons:jaxb2-basics-annotate
and a bindings file. Thus the classes end up being standard beans.
I would love to hear it if anyone knows of a less hacky way--e.g., a XJC plugin.
ReferenceURL : https://stackoverflow.com/questions/13913000/why-doesnt-jaxb-generate-setters-for-lists
'Program Tip' 카테고리의 다른 글
ssh : 호스트 이름을 확인할 수 없습니다. github.com : 이름 또는 서비스를 알 수 없습니다. (0) | 2021.01.08 |
---|---|
OS 스케줄러는 어떻게 CPU를 다시 제어합니까? (0) | 2021.01.08 |
OpenCL과 OpenGL의 컴퓨 트 셰이더의 차이점은 무엇입니까? (0) | 2021.01.08 |
웹 서버에 라 라벨 프로젝트 업로드 (0) | 2021.01.08 |
completablefuture 조인 대 get (0) | 2021.01.08 |