powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Java [игнор отключен] [закрыт для гостей] / Адаптер для JAXBElement<T>
14 сообщений из 14, страница 1 из 1
Адаптер для JAXBElement<T>
    #39357518
ivanra
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Можно ли изменить представление элемента JAXBElement<T> во время маршаллинга?
В частности, интересует JAXBElement<Date>, хочется получить значение без "хвоста" (2016-11-30T11:30:05.539+03:00), на приемной стороне понимают значения только до секунды.
Код: xml
1.
<ns2:dateParameter>2016-11-30T11:30:05.539+03:00</ns2:dateParameter>


Использование XmlAdapter<String, Date> в данном случае не помогает. Обертка JAXBElement требуется, поскольку необходимо передавать null значения
Код: xml
1.
<ns2:dateParameter xsi:nil="true" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>
...
Рейтинг: 0 / 0
Адаптер для JAXBElement<T>
    #39357523
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ivanra,

http://stackoverflow.com/questions/11743306/how-to-represent-null-value-as-empty-element-with-jaxb
Не очень понял почему JAXBElement нужен для xsi:nil? JAXB, ведь должен уметь транслировать и обычный null.
...
Рейтинг: 0 / 0
Адаптер для JAXBElement<T>
    #39357532
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ivanra,

Вот ещё интересный хак
http://stackoverflow.com/a/7110001
Я бы попробовал, чтобы адаптер выбросить.
А JAXBElement заменить на аннотацию @XmlElement(required=true, nillable=true)
...
Рейтинг: 0 / 0
Адаптер для JAXBElement<T>
    #39357538
ivanra
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Там еще есть и строковые параметры, которые могут принимать как null, так и пустую строку. Поэтому JAXBElement.
Да и в принципе непонятно, можно ли тут отрефакторить. На уровень выше список параметров выглядит так
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
    @XmlElementRefs({
        @XmlElementRef(name = "dateParameter", namespace = NS, type = JAXBElement.class),
        @XmlElementRef(name = "floatParameter", namespace = NS, type = JAXBElement.class),
        @XmlElementRef(name = "booleanParameter", namespace = NS, type = JAXBElement.class),
        @XmlElementRef(name = "timeInstantParameter", namespace = NS, type = JAXBElement.class),
        @XmlElementRef(name = "emptyParameter", namespace = NS, type = EmptyParameter.class),
        @XmlElementRef(name = "binaryParameter", namespace = NS, type = JAXBElement.class),
        @XmlElementRef(name = "integerParameter", namespace = NS, type = JAXBElement.class),
        @XmlElementRef(name = "stringParameter", namespace = NS, type = JAXBElement.class)
    })
    protected List<Object> items;
...
Рейтинг: 0 / 0
Адаптер для JAXBElement<T>
    #39358871
Фотография Usman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ivanra,
Код: java
1.
2.
3.
@XmlAnyElement 
@XmlMixed
protected List<Object> items;
...
Рейтинг: 0 / 0
Адаптер для JAXBElement<T>
    #39358901
Фотография Usman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Точнее так.ivanra
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
 
    @XmlAnyElement(lax="true")
    @XmlElementRefs({
        @XmlElementRef(name = "dateParameter", namespace = NS, type = JAXBElement.class),
        @XmlElementRef(name = "floatParameter", namespace = NS, type = JAXBElement.class),
        @XmlElementRef(name = "booleanParameter", namespace = NS, type = JAXBElement.class),
        @XmlElementRef(name = "timeInstantParameter", namespace = NS, type = JAXBElement.class),
        @XmlElementRef(name = "emptyParameter", namespace = NS, type = EmptyParameter.class),
        @XmlElementRef(name = "binaryParameter", namespace = NS, type = JAXBElement.class),
        @XmlElementRef(name = "integerParameter", namespace = NS, type = JAXBElement.class),
        @XmlElementRef(name = "stringParameter", namespace = NS, type = JAXBElement.class)
    })
    protected List<Object> items;


Но в этом случае придется вручную реализовывать ObjectFactory.

см. доки http://docs.oracle.com/javaee/5/api/javax/xml/bind/annotation/XmlAnyElement.html Using XmlAnyElement with XmlElementRef

The XmlAnyElement annotation can be used with XmlElementRefs to designate additional elements that can participate in the content tree.

The following schema would produce the following Java class:


<xs:complexType name="foo">
<xs:choice maxOccurs="unbounded" minOccurs="0">
<xs:element name="a" type="xs:int" />
<xs:element name="b" type="xs:int" />
<xs:any namespace="##other" processContents="lax" />
</xs:choice>
</xs:complexType>

class Foo {
@XmlAnyElement(lax="true")
@XmlElementRefs({
@XmlElementRef(name="a", type="JAXBElement.class")
@XmlElementRef(name="b", type="JAXBElement.class")
})
List<Object> others;
}

@XmlRegistry
class ObjectFactory {
...
@XmlElementDecl(name = "a", namespace = "", scope = Foo.class)
JAXBElement<Integer> createFooA( Integer i ) { ... }

@XmlElementDecl(name = "b", namespace = "", scope = Foo.class)
JAXBElement<Integer> createFooB( Integer i ) { ... }

It can unmarshal instances like

<foo xmlns:e="extra">
<a>1</a> // this will unmarshal to a <A HREF="../../../../javax/xml/bind/JAXBElement.html" title="class in javax.xml.bind"><CODE>JAXBElement</CODE></A> instance whose value is 1.
<e:other /> // this will unmarshal to a DOM <A HREF=" http://java.sun.com/j2se/1.5/docs/api/org/w3c/dom/Element.html" title="class or interface in org.w3c.dom"><CODE>Element</CODE></A>.
<b>3</b> // this will unmarshal to a <A HREF="../../../../javax/xml/bind/JAXBElement.html" title="class in javax.xml.bind"><CODE>JAXBElement</CODE></A> instance whose value is 1.
</foo>

...
Рейтинг: 0 / 0
Адаптер для JAXBElement<T>
    #39359162
ivanra
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Usman, не то. Вопрос был про кастомизацию маршаллинга.
Чтобы вместо этого
Код: xml
1.
2.
3.
4.
        <ns2:commandParameters>
            <ns2:binaryParameter>0000000000018892</ns2:binaryParameter>
            <ns2:dateParameter>2016-12-02T09:42:51.124+03:00</ns2:dateParameter>
        </ns2:commandParameters>

передавалось вот это
Код: xml
1.
2.
3.
4.
        <ns2:commandParameters>
            <ns2:binaryParameter>0000000000018892</ns2:binaryParameter>
            <ns2:dateParameter>2016-12-02T09:42:51</ns2:dateParameter>
        </ns2:commandParameters>


Можно ли задействовать адаптеры для типов данных внутри JAXBElement?. Например, есть
Код: java
1.
public class SimpleDateTimeAdapter extends XmlAdapter<String, Date> {...}

но помещение его в package-info не дает эффекта для JAXBElement<Date>, хотя в случае обычных пропертей типа Date всё работает
Код: java
1.
@XmlJavaTypeAdapter(value=SimpleDateTimeAdapter.class,type=Date.class)
...
Рейтинг: 0 / 0
Адаптер для JAXBElement<T>
    #39359194
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ivanra,

Так что на Calendar заменить никак?
...
Рейтинг: 0 / 0
Адаптер для JAXBElement<T>
    #39359236
ivanra
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Blazkowiczivanra,
Так что на Calendar заменить никак?Тоже не то
- при маршаллинге всё равно есть миллисекунды (если установить в 0, то будет окончание .000)
- хочется также избавиться от бойлеркода Date <-> XMLGregorianCalendar
...
Рейтинг: 0 / 0
Адаптер для JAXBElement<T>
    #39359277
ferc
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ivanra,

можно так

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
public class TimeFromDateAdapter extends XmlAdapter<XMLGregorianCalendar, Date> {

    public Date unmarshal(XMLGregorianCalendar value){
        Calendar cal = value.toGregorianCalendar();
        Date d = cal.getTime();
        return d;
    }

    public XMLGregorianCalendar marshal(Date value){
        GregorianCalendar cal = new GregorianCalendar();

        cal.setTime(value);

        try{
            XMLGregorianCalendar xmlDate = DatatypeFactory.newInstance().newXMLGregorianCalendarDate(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH) + 1, cal.get(Calendar.DAY_OF_MONTH), 0);
            xmlDate.setTimezone(DatatypeConstants.FIELD_UNDEFINED);
            return xmlDate;
        }
        catch (Exception e){
            e.printStackTrace();
            return null;
        }
    }
}
...
Рейтинг: 0 / 0
Адаптер для JAXBElement<T>
    #39359415
ivanra
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ferc, тоже миллисекунды будут. Тут кровавый легаси энтернпрайз, надо только в определенном формате.
Вот 2 возможных решения:
1) Для случаев, когда не надо передавать пустые значения, заменяем JAXBElement<Date> на свою обертку
Код: java
1.
2.
3.
4.
5.
6.
7.
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "dateParameter")
public class DateParameter {
	@XmlValue
	private Date value;
	//getter+setter
}

На уровень выше меняем аннотацию, чтобы указывала на этот класс
Код: java
1.
@XmlElementRef(name = "dateParameter", namespace = NS, type = DateParameter.class)

Всё прозрачно работает, но в этом случае пустые даты будут передаваться как <dateParameter/> без атрибута nil. Дальше остается только надеяться, что на приемной стороне анмаршаллинг пройдет нормально.

2) другой вариант - вместо JAXBElement<Date> использовать JAXBElement<String>, форматируя это всё в слое логики. Ничего хорошего, но для штучных случаев сойдет
...
Рейтинг: 0 / 0
Адаптер для JAXBElement<T>
    #39359609
Фотография Usman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
Адаптер для JAXBElement<T>
    #39372772
Фотография IHmG
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ivanraМожно ли изменить представление элемента JAXBElement<T> во время маршаллинга?
что надо гуглить, чтобы понять Ваш вопрос?

Правильно ли я понял? Вы используете jaxb для того, чтобы сформировать xml и во время маршалинга (сохранение объектов в xml) имеете хвост в виде милисекунд?

Что такое JAXBElement<T>? Что значит представление элемента?
Удалось ли как-то задачу уже решить?
...
Рейтинг: 0 / 0
Адаптер для JAXBElement<T>
    #39373029
ivanra
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
IHmG, всё выглядело примерно так. Есть некий сервис, в схеме которого написано:
Код: xml
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
	<xsd:element name="dateParameter" type="xsd:date">
		<xsd:annotation>
			<xsd:documentation>
				An element for passing a date parameter to or from an AppServer Rule (server script).  Uses the format YYYY-MM-DD, e.g. "1978-07-23".
			</xsd:documentation>
		</xsd:annotation>
	</xsd:element>
...
	<xsd:complexType name="parameters">
		<xsd:annotation>
			<xsd:documentation>
				Elements of this type represent an array of zero or more parameters used by an AppServer rule (server script).
			</xsd:documentation>
		</xsd:annotation>
		<xsd:sequence>
			<xsd:choice minOccurs="0" maxOccurs="unbounded">
				<xsd:element ref="binaryParameter"/>
				<xsd:element ref="booleanParameter"/>
				<xsd:element ref="dateParameter"/>
				<xsd:element ref="emptyParameter"/>
				<xsd:element ref="floatParameter"/>
				<xsd:element ref="integerParameter"/>
				<xsd:element ref="stringParameter"/>
				<xsd:element ref="timeInstantParameter"/>
			</xsd:choice>
		</xsd:sequence>
	</xsd:complexType>


Это описание параметров для вызываемых функции. В том числе, параметры могут иметь нулевые значения, и тогда передаются они в таком виде:
Код: xml
1.
<dateParameter nil="true"/>


xjc по этой схеме сгенерировала класс с аннотацией
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
    @XmlElementRefs({
        @XmlElementRef(name = "dateParameter", namespace = NS, type = JAXBElement.class),
        @XmlElementRef(name = "floatParameter", namespace = NS, type = JAXBElement.class),
        @XmlElementRef(name = "booleanParameter", namespace = NS, type = JAXBElement.class),
        @XmlElementRef(name = "timeInstantParameter", namespace = NS, type = JAXBElement.class),
        @XmlElementRef(name = "emptyParameter", namespace = NS, type = EmptyParameter.class),
        @XmlElementRef(name = "binaryParameter", namespace = NS, type = JAXBElement.class),
        @XmlElementRef(name = "integerParameter", namespace = NS, type = JAXBElement.class),
        @XmlElementRef(name = "stringParameter", namespace = NS, type = JAXBElement.class)
    })
    protected List<Object> items;


и дальше встал вопрос, как передавать даты (в комментариях схемы читаем, что это должен быть формат YYYY-MM-DD). Использование адаптера для даты в данном случае не помогает, так как значения обернуты в JAXBElement. Об этом и был вопрос.
Конечным решением для меня стало использование вместо JAXBElement<Date> такого класса
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
@XmlAccessorType(XmlAccessType.PROPERTY)
@XmlRootElement(name = "dateParameter")
public class DateParameter {
	private Date value;
	@XmlValue
	public Date getValue() {
		return value;
	}
	public void setValue(Date value) {
		this.value = value;
	}
	@XmlAttribute(name="nil", namespace="http://www.w3.org/2001/XMLSchema-instance")
	public Boolean getNil() {
		return value==null?Boolean.TRUE:null;
	}
}


Соответственно изменена строчка в аннотации для элемента "dateParameter"
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
    @XmlElementRefs({
        @XmlElementRef(name = "dateParameter", namespace = NS, type = DateParameter.class),
        @XmlElementRef(name = "floatParameter", namespace = NS, type = JAXBElement.class),
        @XmlElementRef(name = "booleanParameter", namespace = NS, type = JAXBElement.class),
        @XmlElementRef(name = "timeInstantParameter", namespace = NS, type = JAXBElement.class),
        @XmlElementRef(name = "emptyParameter", namespace = NS, type = EmptyParameter.class),
        @XmlElementRef(name = "binaryParameter", namespace = NS, type = JAXBElement.class),
        @XmlElementRef(name = "integerParameter", namespace = NS, type = JAXBElement.class),
        @XmlElementRef(name = "stringParameter", namespace = NS, type = JAXBElement.class)
    })
    protected List<Object> items;


В таком виде адаптер для даты работает. Класс простейший:
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
public class SimpleDateTimeAdapter extends XmlAdapter<String, Date> {
	private final SimpleDateFormat shortFormat(){return new SimpleDateFormat("yyyy-MM-dd");}
	@Override
	public Date unmarshal(String v) throws Exception {
		if (v.isEmpty()) return null;
		return shortFormat().parse(v);
	}
	@Override
	public String marshal(Date v) throws Exception {
		if (v==null) return null;
		return shortFormat().format(v);
	}
}


Подключаем его сразу ко всему пакету с помощью аннотации в package-info
Код: java
1.
@XmlJavaTypeAdapter(value=SimpleDateTimeAdapter.class,type=Date.class)
...
Рейтинг: 0 / 0
14 сообщений из 14, страница 1 из 1
Форумы / Java [игнор отключен] [закрыт для гостей] / Адаптер для JAXBElement<T>
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]