Java 8

2014-07-02 69 views
5

kullanarak package-info.java adresinin açıklaması değiştirilemedi. Bir paket bilgisini değiştirmem gereken bir sorunla karşılaşıyorum.Java 8

package-info.java

@javax.xml.bind.annotation.XmlSchema(namespace = "http://some.url/soap/style/document_literal") 
package org.example.wsdl.wsdl; 

Aşağıdaki kod 1.7.0_45 ile çalışıyor.

java.lang.NoSuchFieldException: annotations 
    at java.lang.Class.getDeclaredField(Class.java:2057) 

Ben onun Hack en azından öyle görünüyor, biliyorum: derlenmesi ve 1.8.0_05 ile aynı kod yürütürken

//   do not load any classes before, this could break the following code. 
      Class<?> pkgInfo = Class.forName("org.example.wsdl.package-info", true, NameSpaceModifier.class.getClassLoader()); 
      Field field = Class.class.getDeclaredField("annotations"); 
      field.setAccessible(true); 

      final XmlSchema oldAnnotation = (XmlSchema) pkgInfo.getAnnotations()[0]; 
      logger.debug("Old Annotation namespace value was: " + oldAnnotation.namespace()); 
      XmlSchema newAnnotation = new XmlSchema() { 

       @Override 
       public XmlNs[] xmlns() { 
        return oldAnnotation.xmlns(); 
       } 

       @Override 
       public String namespace() { 
        return "newNs"; 
       } 

       @Override 
       public XmlNsForm elementFormDefault() { 
        return oldAnnotation.elementFormDefault(); 
       } 

       @Override 
       public XmlNsForm attributeFormDefault() { 
        return oldAnnotation.attributeFormDefault(); 
       } 

       @Override 
       public String location() { 
        return oldAnnotation.location(); 
       } 

       @Override 
       public Class<? extends Annotation> annotationType() { 
        return oldAnnotation.annotationType(); 
       } 
      }; 

      @SuppressWarnings("unchecked") 
      Map<Class<? extends Annotation>, Annotation> annotations = (Map<Class<? extends Annotation>, Annotation>) field.get(pkgInfo); 
      annotations.put(XmlSchema.class, newAnnotation); 

      XmlSchema modifiedAnnotation = (XmlSchema) pkgInfo.getAnnotations()[0]; 

Bu hata mesajı alıyorum. Ama Java 8 beklendiği gibi burada çalışıyor mu? O kodun Java 8 ile çalıştığını nasıl değiştirmeliyim?

cevap

3

Java 8 açıklamalar içten depolandığı nasıl değişti);

Javassist cevaplar çok açıktır. Sabit kodlanmış bir alan adıyla kötü bir yansıma kesmek kullandığınızdan, herhangi bir Java güncellemesinin kodunuzu yeniden başlatma potansiyeli vardır.

java.lang.Class

:

/** 
* @since 1.5 
*/ 
public Annotation[] getAnnotations() { 
    return AnnotationParser.toArray(annotationData().annotations); 
} 

private volatile transient AnnotationData annotationData; 

private AnnotationData annotationData() { 
    while (true) { // retry loop 
     AnnotationData annotationData = this.annotationData; 
     int classRedefinedCount = this.classRedefinedCount; 
     if (annotationData != null && 
      annotationData.redefinedCount == classRedefinedCount) { 
      return annotationData; 
     } 
     // null or stale annotationData -> optimistically create new instance 
     AnnotationData newAnnotationData = createAnnotationData(classRedefinedCount); 
     // try to install it 
     if (Atomic.casAnnotationData(this, annotationData, newAnnotationData)) { 
      // successfully installed new AnnotationData 
      return newAnnotationData; 
     } 
    } 
} 

private static class AnnotationData { 
    final Map<Class<? extends Annotation>, Annotation> annotations; 
    final Map<Class<? extends Annotation>, Annotation> declaredAnnotations; 

    // Value of classRedefinedCount when we created this AnnotationData instance 
    final int redefinedCount; 

    AnnotationData(Map<Class<? extends Annotation>, Annotation> annotations, 
        Map<Class<? extends Annotation>, Annotation> declaredAnnotations, 
        int redefinedCount) { 
     this.annotations = annotations; 
     this.declaredAnnotations = declaredAnnotations; 
     this.redefinedCount = redefinedCount; 
    } 
} 

Ben geçici olarak kodunu çözmek için yeni alan değerlerini kullanabilirsiniz varsayalım. Kalıcı bir düzeltme, çalışma zamanında dinamik olarak değiştirmek yerine, açıklamanın kendisini değiştirmektir.

Field annotationDataField = Class.class.getDeclaredField("annotationData"); 
annotationDataField.setAccessible(true); 

Object annotationData = annotationDataField.get(pkgInfo); 

Field annotationsField = annotationData.getClass().getDeclaredField("annotations"); 
annotationsField.setAccessible(true); 

Map<Class<? extends Annotation>, Annotation> annotations = (Map<Class<? extends Annotation>, Annotation>) annotationsField 
     .get(annotationData); 
annotations.put(XmlSchema.class, newAnnotation); 

XmlSchema modifiedAnnotation = (XmlSchema) pkgInfo.getAnnotations()[0]; 
+0

Herhangi bir java güncelleştirmesinin kodumu kesebileceğini biliyorum. Farklı bir yol için herhangi bir öneriniz var mı? – Zarathustra

+0

@Zarathustra Neden ek açıklamaları değiştiremiyorsunuz? Üretilen kodu – Jeffrey

+0

. Farklı Sunucularda bir SOAP Hizmeti ile iletişim kuruyorum, hepsi aynı wsdl'yi paylaşıyor, hostname içerdiğinden targetNamespace olmasını bekliyorum. – Zarathustra