4

認証を行い、リクエストで Cookie をチェックして、同じクライアントからの後続の呼び出しを許可する Web アプリケーションがあります。Eclipse から実行すると問題なく動作するコードを作成しましたが、Android エミュレーターから実行すると失敗します。これが私がしたことです

URI の Web リソースを作成し、それにフィルターをバインドして Cookie をリクエストに添付するクラス

public class TolvenRestClient {
        private static Client client;
        private static final ThreadLocal<String> instance = new ThreadLocal<String>();

    static {
        ClientConfig config = new DefaultClientConfig();
        client = Client.create(config);
        client.setFollowRedirects(true);
    }

    private Client getClient() {
        return client;
    }

    public WebResource getResource(String path){
        WebResource webResource = getClient().resource(path);
        webResource.addFilter(new ClientFilter() {
            @Override
            public ClientResponse handle(ClientRequest clientRequest) throws ClientHandlerException {
                if (instance.get() != null) {
                    clientRequest.getHeaders().putSingle("Cookie", "SSOCookie=" + instance.get());
                }
                ClientResponse clientResponse = getNext().handle(clientRequest);
                String cookieName = "SSOCookie";
                System.out.println("cookies "+clientResponse.getCookies());
                for (NewCookie newCookie : clientResponse.getCookies()) {
                    if (cookieName.equals(newCookie.getName())) {
                        String extendedSessionId = newCookie.getValue();                            
                        instance.set(extendedSessionId);
                        break;
                    }
                }
                return clientResponse;
            }
        }); 
        return webResource;
    }

次に、Web サービス呼び出しをトリガーするサンプル コード

RestClient client = new RestClient();

    MultivaluedMap<String, String> formData = new MultivaluedMapImpl();
    formData.add("username", "demo");
    formData.add("password", "1234qwer");
    formData.add("realm", "tolven");
    WebResource webResource = client.getResource("https://dev.example.com:8443/gatekeeper/rs/authenticate/login");
    ClientResponse response = webResource.type(MediaType.APPLICATION_FORM_URLENCODED).post(ClientResponse.class,formData);
    //ClientResponse response = webResource.accept("text/html").get(ClientResponse.class);
    System.out.println("Here ....." + response.toString());     
    webResource = client.getResource("https://dev.example.com:8443/api/vestibule/accountList");
    response = webResource.get(ClientResponse.class);
    Accounts accounts = response.getEntity(Accounts.class);

このコードは、Eclipse から実行すると問題なく動作します。しかし、Androidエミュレーター内で実行すると、クライアントの応答からCookieを読み取ることができません

以下の例外が発生します

09-20 19:55:31.067: W/System.err(1172): java.lang.NullPointerException
09-20 19:55:31.077: W/System.err(1172):     at javax.ws.rs.core.NewCookie.valueOf(NewCookie.java:126)
09-20 19:55:31.077: W/System.err(1172):     at com.sun.jersey.api.client.ClientResponse.getCookies(ClientResponse.java:714)
09-20 19:55:31.077: W/System.err(1172):     at com.userexample.LoginActivityTolven$1$1.handle(LoginActivityTolven.java:71)
09-20 19:55:31.088: W/System.err(1172):     at com.sun.jersey.api.client.WebResource.handle(WebResource.java:680)
09-20 19:55:31.088: W/System.err(1172):     at com.sun.jersey.api.client.WebResource.access$200(WebResource.java:74)
09-20 19:55:31.097: W/System.err(1172):     at com.sun.jersey.api.client.WebResource$Builder.post(WebResource.java:568)
09-20 19:55:31.097: W/System.err(1172):     at com.userexample.LoginActivityTolven$1.onClick(LoginActivityTolven.java:86)
09-20 19:55:31.097: W/System.err(1172):     at android.view.View.performClick(View.java:4240)
09-20 19:55:31.097: W/System.err(1172):     at android.view.View$PerformClick.run(View.java:17721)
09-20 19:55:31.107: W/System.err(1172):     at android.os.Handler.handleCallback(Handler.java:730)
09-20 19:55:31.107: W/System.err(1172):     at android.os.Handler.dispatchMessage(Handler.java:92)
09-20 19:55:31.107: W/System.err(1172):     at android.os.Looper.loop(Looper.java:137)
09-20 19:55:31.107: W/System.err(1172):     at android.app.ActivityThread.main(ActivityThread.java:5103)
09-20 19:55:31.107: W/System.err(1172):     at java.lang.reflect.Method.invokeNative(Native Method)
09-20 19:55:31.117: W/System.err(1172):     at java.lang.reflect.Method.invoke(Method.java:525)
09-20 19:55:31.117: W/System.err(1172):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737)
09-20 19:55:31.117: W/System.err(1172):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
09-20 19:55:31.117: W/System.err(1172):     at dalvik.system.NativeStart.main(Native Method)

以前に Android で Jersey クライアントを使用して、この問題を見た人はいますか?

4

1 に答える 1

1

Jersey 1.x を使用していて、NewCookie で JAX-RS ランタイム デリゲートが null になっているようです。

これは、Jersey META-INF/services ファイルが見つからない場合に発生する可能性があります。META-INF/services ファイルを再パッケージ化しない場合、Android の再パッケージ化プロセスが問題の原因となる可能性があります。必ず確認してください。

そのための 1 つの方法は、独自のServiceIteratorProviderを提供してサービス ロケーション アルゴリズムをオーバーライドすることです。

見る :

参考までに、サンプルコードは次のとおりです。

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;

import com.sun.jersey.spi.service.ServiceFinder.ServiceIteratorProvider;

public class YourOwnServiceIteratorProvider<T> extends ServiceIteratorProvider<T>
{
    private static final HashMap<String, String[]> SERVICES = new HashMap<String, String[]>();

    private static final String[] com_sun_jersey_spi_HeaderDelegateProvider = new String[] {
            "com.sun.jersey.core.impl.provider.header.LocaleProvider",
            "com.sun.jersey.core.impl.provider.header.EntityTagProvider",
            "com.sun.jersey.core.impl.provider.header.MediaTypeProvider",
            "com.sun.jersey.core.impl.provider.header.CacheControlProvider",
            "com.sun.jersey.core.impl.provider.header.NewCookieProvider",
            "com.sun.jersey.core.impl.provider.header.CookieProvider",
            "com.sun.jersey.core.impl.provider.header.URIProvider",
            "com.sun.jersey.core.impl.provider.header.DateProvider",
            "com.sun.jersey.core.impl.provider.header.StringProvider"

    };
    private static final String[] com_sun_jersey_spi_inject_InjectableProvider = new String[] {
            "com.sun.jersey.core.impl.provider.xml.SAXParserContextProvider",
            "com.sun.jersey.core.impl.provider.xml.XMLStreamReaderContextProvider",
            "com.sun.jersey.core.impl.provider.xml.DocumentBuilderFactoryProvider",
            "com.sun.jersey.core.impl.provider.xml.TransformerFactoryProvider"
    };
    private static final String[] javax_ws_rs_ext_MessageBodyReader = new String[] {
            "com.sun.jersey.core.impl.provider.entity.StringProvider",
            "com.sun.jersey.core.impl.provider.entity.ByteArrayProvider",
            "com.sun.jersey.core.impl.provider.entity.FileProvider",
            "com.sun.jersey.core.impl.provider.entity.InputStreamProvider",
            "com.sun.jersey.core.impl.provider.entity.DataSourceProvider",
            "com.sun.jersey.core.impl.provider.entity.RenderedImageProvider",
            "com.sun.jersey.core.impl.provider.entity.MimeMultipartProvider",
            "com.sun.jersey.core.impl.provider.entity.FormProvider",
            "com.sun.jersey.core.impl.provider.entity.FormMultivaluedMapProvider",
            "com.sun.jersey.core.impl.provider.entity.XMLRootElementProvider$App",
            "com.sun.jersey.core.impl.provider.entity.XMLRootElementProvider$Text",
            "com.sun.jersey.core.impl.provider.entity.XMLRootElementProvider$General",
            "com.sun.jersey.core.impl.provider.entity.XMLJAXBElementProvider$App",
            "com.sun.jersey.core.impl.provider.entity.XMLJAXBElementProvider$Text",
            "com.sun.jersey.core.impl.provider.entity.XMLJAXBElementProvider$General",
            "com.sun.jersey.core.impl.provider.entity.XMLListElementProvider$App",
            "com.sun.jersey.core.impl.provider.entity.XMLListElementProvider$Text",
            "com.sun.jersey.core.impl.provider.entity.XMLListElementProvider$General",
            "com.sun.jersey.core.impl.provider.entity.ReaderProvider",
            "com.sun.jersey.core.impl.provider.entity.DocumentProvider",
            "com.sun.jersey.core.impl.provider.entity.SourceProvider$StreamSourceReader",
            "com.sun.jersey.core.impl.provider.entity.SourceProvider$SAXSourceReader",
            "com.sun.jersey.core.impl.provider.entity.SourceProvider$DOMSourceReader",
            "com.sun.jersey.core.impl.provider.entity.XMLRootObjectProvider$App",
            "com.sun.jersey.core.impl.provider.entity.XMLRootObjectProvider$Text",
            "com.sun.jersey.core.impl.provider.entity.XMLRootObjectProvider$General",
            "com.sun.jersey.core.impl.provider.entity.EntityHolderReader"
    };
    private static final String[] javax_ws_rs_ext_MessageBodyWriter = new String[] {
            "com.sun.jersey.core.impl.provider.entity.StringProvider",
            "com.sun.jersey.core.impl.provider.entity.ByteArrayProvider",
            "com.sun.jersey.core.impl.provider.entity.FileProvider",
            "com.sun.jersey.core.impl.provider.entity.InputStreamProvider",
            "com.sun.jersey.core.impl.provider.entity.DataSourceProvider",
            "com.sun.jersey.core.impl.provider.entity.RenderedImageProvider",
            "com.sun.jersey.core.impl.provider.entity.MimeMultipartProvider",
            "com.sun.jersey.core.impl.provider.entity.FormProvider",
            "com.sun.jersey.core.impl.provider.entity.FormMultivaluedMapProvider",
            "com.sun.jersey.core.impl.provider.entity.XMLRootElementProvider$App",
            "com.sun.jersey.core.impl.provider.entity.XMLRootElementProvider$Text",
            "com.sun.jersey.core.impl.provider.entity.XMLRootElementProvider$General",
            "com.sun.jersey.core.impl.provider.entity.XMLJAXBElementProvider$App",
            "com.sun.jersey.core.impl.provider.entity.XMLJAXBElementProvider$Text",
            "com.sun.jersey.core.impl.provider.entity.XMLJAXBElementProvider$General",
            "com.sun.jersey.core.impl.provider.entity.XMLListElementProvider$App",
            "com.sun.jersey.core.impl.provider.entity.XMLListElementProvider$Text",
            "com.sun.jersey.core.impl.provider.entity.XMLListElementProvider$General",
            "com.sun.jersey.core.impl.provider.entity.ReaderProvider",
            "com.sun.jersey.core.impl.provider.entity.DocumentProvider",
            "com.sun.jersey.core.impl.provider.entity.StreamingOutputProvider",
            "com.sun.jersey.core.impl.provider.entity.SourceProvider$SourceWriter"
    };

    static
    {
        SERVICES.put("com.sun.jersey.spi.HeaderDelegateProvider",
            com_sun_jersey_spi_HeaderDelegateProvider);
        SERVICES.put("com.sun.jersey.spi.inject.InjectableProvider",
            com_sun_jersey_spi_inject_InjectableProvider);
        SERVICES.put("javax.ws.rs.ext.MessageBodyReader", javax_ws_rs_ext_MessageBodyReader);
        SERVICES.put("javax.ws.rs.ext.MessageBodyWriter", javax_ws_rs_ext_MessageBodyWriter);
    }

    @SuppressWarnings("unchecked")
    @Override
    public Iterator<Class<T>> createClassIterator(Class<T> service, String serviceName,
        ClassLoader loader, boolean ignoreOnClassNotFound)
    {
        String[] classesNames = SERVICES.get(serviceName);
        int length = classesNames.length;
        ArrayList<Class<T>> classes = new ArrayList<Class<T>>(length);
        for (int i = 0; i < length; i++)
        {
            try
            {
                classes.add((Class<T>) Class.forName(classesNames[i]));
            } catch (ClassNotFoundException e)
            {
                e.printStackTrace();
            }
        }
        return null;
    }

    @Override
    public Iterator<T> createIterator(Class<T> service, String serviceName, ClassLoader loader,
        boolean ignoreOnClassNotFound)
    {
        String[] classesNames = SERVICES.get(serviceName);
        int length = classesNames.length;
        ArrayList<T> classes = new ArrayList<T>(length);
        for (int i = 0; i < length; i++)
        {
            try
            {
                classes.add(service.cast(Class.forName(classesNames[i]).newInstance()));
            } catch (IllegalAccessException e)
            {
                e.printStackTrace();
            } catch (InstantiationException e)
            {
                e.printStackTrace();
            } catch (ClassNotFoundException e)
            {
                e.printStackTrace();
            }
        }
        return classes.iterator();
    }
}

それは次のように使用できます。

// ...
Client client = Client.create();
// ...
ServiceFinder.setIteratorProvider(new YourOwnServiceIteratorProvider());
// ...

HTH

于 2013-09-23T09:21:49.900 に答える