Osobní stránky

Jersey Exception: java.lang.VerifyError: Expecting a stackmap frame at branch target 14

Při vývoji mé semestrální práce pro předmět MI-MDW (Webové služby a Middleware) do školy (ČVUT FIT – fakulta informačních technologií) jsem narazil na zajímavou chybu. Mám napsanou aplikaci v Javě pro cloud od Google App Engine. V naší aplikaci implementováno rozhraní REST pro webové služby a některé jiné služby pomocí tohoto rozhraní využíváme. Více o tomto způsobu práce se můžete dočíst například na wikipedii pod heslem Representational state transfer. K tomuto účelu se nám nejvíce hodí knihova Jersey, ta implemntuje standard JAX-RS pro práci s webovými službami a také obsahuje některé další technologie, jako například JAX-B pro převod mezi formáty JSON nebo XML na objekty v Javě.

Při integraci jedné ze služeb na mne vyskočila zajímavá výjmka:

java.lang.VerifyError: Expecting a stackmap frame at branch target 14 in method cms.model.rest.bean.Event$JaxbAccessorM_isPublic_setPublic_boolean.set(Ljava/lang/Object;Ljava/lang/Object;)V at offset 5

Jednalo se o automaticky vygenerovanou třídu, která se stará o konverzi mezi JSONem a Javou. Když jsem se pokoušel zmíněnou chybu googlit, všichni radili místo JDK 1.7 použít starší verzi 1.6. Nechtělo se mi měnit toto nastavení, protože používám další knihovny, které by nemuseli fungovat na 100%. Začal jsem zkoušet kód upravit a přišel jsem na jednoduché řešení.

Chyba se týkala tohoto kódu ve třídě starající se o převod mezi JSONem a Javou. Kód vypadal přibližně takto:

public class Event {
    private Boolean admin;

    public Boolean isAdmin() {
        return admin;
    }

    public function setAdmin(Boolean admin) {
        this.admin = admin;
    }
}

Jedná se o běžnou třídu, obsahující jednu property typu boolean a dále její gettery a settery. Problém byl v tom, že JSON je celý jako String, takže vygenerovaný objekt si neporadí s paramterem typu boolean. Pomohl proto jednoduchý trik: deklarace vlastnosti admin jako objekt Boolean, který odpovÍdá primitivnímu typu boolean a lze je navzájem převádět (takzvaný autoboxing). Uvedený trik mi bez problému funguje a nemusím kvuli tomu měnit verzi Javy. Uvedená výjimka se již neobjevuje. Výsledný kód tedy bude vypadat takto:

public class Event {
    private Boolean admin;

    public Boolean isAdmin() {
        return admin;
    }

    public function setAdmin(Boolean admin) {
        this.admin = admin;
    }
}

Doufám že toto řešení někomu pomůže. Jedná se o jednoduchou úpravu, která bez problému funguje s vynaložením minimálního úsilí.

Jakub Škvára


Jakub je cestovatel, blogger a webový vývojář. Zajímá se především o technické novinky a rád navštěvuje konference. Používá: Symfony2 Framework, AngularJS, NodeJS, MongoDB a další moderní technologie. Aktuálně žije v Londýně.