@XmlTransient for serialization but not for deserialization?

Is there a way to tweak the @XmlTransient JPA2.0 annotation so that it will block the JAXB mechanism only when the Java-Object is serialized to xml and not when the incoming XML is converted to a java object?

Background: I have a REST api that speaks XML. There is an endpoint for creating a new Attachment. Since we are talking about attachment, there is a byte field [] in this class. In the optional attachment lists, I do not want to deliver the contents of the byte [] of each attachment.

@Entity
@XmlRootElement
public class Attachment {

private String name;

private String mimeType;

private byte[] dataPart;

public String getName() {
    return name;
}

public void setName( String name ) {
    this.name = name;
}

public String getMimeType() {
    return mimeType;
}

public void setMimeType( String mimeType ) {
    this.mimeType = mimeType;
}

public byte[] getDataPart() {

    return dataPart.clone();
}

public void setDataPart( byte[] dataPart ) {
    this.dataPart = dataPart.clone();
}
}

So, when I mark getDataPart () with an XmlTransient, the incoming byte [] data is ignored and set to null -> it is lost. Does anyone know how to indicate the direction of XmlTransient?

+3
source share
4

=) XmlAdapter, . , . .

:

public class DuplexBase64MarshallAdapter extends XmlAdapter<String, byte[]> {

        /**
         * running the adapter in half duplex mode means, the incoming data is marshaled but the
         * outgoing data not.
         */
        public static final boolean HALF_DUPLEX = false;

        /**
         * Running the adapter in full duplex means, the incoming and outgoing data is marshalled.
         */
        public static final boolean FULL_DUPLEX = true;

        private boolean isFullDuplexMode;

        public DuplexBase64MarshallAdapter() {
            this.isFullDuplexMode = HALF_DUPLEX;
        }

        /**
         * Constructor
         * 
         * @param fullDuplex
         *            use {@link #HALF_DUPLEX} or {@link #FULL_DUPLEX}
         */
        public DuplexBase64MarshallAdapter( boolean fullDuplex ) {
            this.isFullDuplexMode = fullDuplex;
        }

        @Override
        public byte[] unmarshal( String v ) throws Exception {
            return Base64.decode( v );
        }

        /**
         * Return always an empty string. We do not want to deliver binary content here.
         */
        @Override
        public String marshal( byte[] v ) throws Exception {
            if( isFullDuplexMode ) {
                return Base64.encodeBytes( v );
            }
            return "";
        }

    }

:

@Entity
@XmlRootElement
public class Attachment {

    private String name;

    private String mimeType;

    private byte[] dataPart;

    public String getName() {
        return name;
    }

    public void setName( String name ) {
        this.name = name;
    }

    public String getMimeType() {
        return mimeType;
    }

    public void setMimeType( String mimeType ) {
        this.mimeType = mimeType;
    }

    @XmlJavaTypeAdapter( DuplexBase64MarshallAdapter.class )
    public byte[] getDataPart() {

        return dataPart.clone();
    }

    public void setDataPart( byte[] dataPart ) {
        this.dataPart = dataPart.clone();
    }
}

exepcted. : , / . , . , XMLAdapter, base64: (

+1

, , ", , ", : → , → . , byte[], ? (?) .

, null, . REST :

@PersistenceContext(unitName = "myPersistenceUnit")
privat EntityManager em;

@Path("/upload")
@POST
public Response storeAttachment(JAXBElement<Attachment> jaxbAttachment) {
  Attachment attachment = jaxbAttachment.getValue();

  // store it in the DB
  em.persist(attachment);

  // detach it, so that modifications are no longer reflected in the database
  em.detach(attachment);

  // modify your guts out, it'll only affect this instance
  attachment.setDataPart(null);   // <-- NPE if you don't get rid of .clone() in your entity

  URI newUri = ...
  return Response.created(newUri).entity(attachment).build();
}
0

, -, , @XmlAccessorType(XmlAccessType.FIELD) getter @XmlElement.

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Something {

  public Integer foo;

  public Integer getFoo() {
    return foo;
  }

  public void setFoo(Integer foo) {
    this.foo = foo;
  }

  @XmlElement
  public Integer getBar() {
    return 42;
  }
}

(, foo 17),

<something>
  <foo>17</foo>
  <bar>42</bar>
</something>

( ), bar unmarshaller ( ).

0
Hans, I had the same problem. Your answer put me on the right track. If the problem is serialization only, this does the trick:
public class HalfDuplexXmlAdapter extends XmlAdapter<String, String> {

    @Override
    public String unmarshal(String value) throws Exception {
        return value;
    }

    @Override
    public String marshal(String value) throws Exception {
        //ignore marshall so you have half duplex
        return null;
    }

}

and then use it like this:

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class User {

    String login;

    @XmlJavaTypeAdapter(HalfDuplexXmlAdapter.class)
    String password;

    // getters and setters
}

Thus, sending the password from the client to the server is serialized and deserialized, but when the user is sent from the server to the client password, it is not serialized and / or not deserialized, and therefore not sent (null).

0
source

All Articles