জার্সির সাথে নির্ভরতা ইনজেকশন ২.০


108

কোনও পূর্ববর্তী জার্সি 1.x জ্ঞান ছাড়াই স্ক্র্যাচ থেকে শুরু করে, আমার জার্সি ২.০ প্রকল্পে নির্ভরতা ইনজেকশন কীভাবে সেটআপ করতে হবে তা বুঝতে আমার খুব কষ্ট হচ্ছে।

আমি আরও বুঝতে পেরেছি যে এইচকে 2 জার্সি ২.০ এ উপলব্ধ, তবে আমি জার্সি ২.০ ইন্টিগ্রেশনটিতে সহায়তা করে এমন ডকগুলি খুঁজে পাচ্ছি না।

@ManagedBean
@Path("myresource")
public class MyResource {

    @Inject
    MyService myService;

    /**
     * Method handling HTTP GET requests. The returned object will be sent
     * to the client as "text/plain" media type.
     *
     * @return String that will be returned as a text/plain response.
     */
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    @Path("/getit")
    public String getIt() {
        return "Got it {" + myService + "}";
    }
}

@Resource
@ManagedBean
public class MyService {
    void serviceCall() {
        System.out.print("Service calls");
    }
}

pom.xml

<properties>
    <jersey.version>2.0-rc1</jersey.version>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.glassfish.jersey</groupId>
            <artifactId>jersey-bom</artifactId>
            <version>${jersey.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

<dependencies>
    <dependency>
        <groupId>org.glassfish.jersey.core</groupId>
        <artifactId>jersey-common</artifactId>
    </dependency>
    <dependency>
        <groupId>org.glassfish.jersey.core</groupId>
        <artifactId>jersey-server</artifactId>
    </dependency>
    <dependency>
        <groupId>org.glassfish.jersey</groupId>
        <artifactId>jax-rs-ri</artifactId>
    </dependency>
</dependencies>

আমি আমার সংস্থান শুরু এবং পরিবেশন করার জন্য ধারকটি পেতে পারি তবে আমি @ মাই সার্ভিসে ইনজেক্ট যুক্ত করার সাথে সাথে ফ্রেমওয়ার্কটি একটি ব্যতিক্রম ছুঁড়ে ফেলেছে:

SEVERE: Servlet.service() for servlet [com.noip.MyApplication] in context with path [/jaxrs] threw exception [A MultiException has 3 exceptions.  They are:
1. org.glassfish.hk2.api.UnsatisfiedDependencyException: There was no object available for injection at Injectee(requiredType=MyService,parent=MyResource,qualifiers={}),position=-1,optional=false,self=false,unqualified=null,1039471128)
2. java.lang.IllegalArgumentException: While attempting to resolve the dependencies of com.noip.MyResource errors were found
3. java.lang.IllegalStateException: Unable to perform operation: resolve on com.noip.MyResource
] with root cause
org.glassfish.hk2.api.UnsatisfiedDependencyException: There was no object available for injection at Injectee(requiredType=MyService,parent=MyResource,qualifiers={}),position=-1,optional=false,self=false,unqualified=null,1039471128)
    at org.jvnet.hk2.internal.ThreeThirtyResolver.resolve(ThreeThirtyResolver.java:74)


আমার স্টার্টার প্রকল্পটি গিটহাবটিতে উপলব্ধ: https://github.com / डोোনাল্ডারজমস্ট্রং / জ্যাকার্স

উত্তর:


107

আপনার একটি AbstractBinderJAX-RS অ্যাপ্লিকেশন এ আপনাকে একটি সংজ্ঞায়িত করতে হবে এবং এটি নিবন্ধভুক্ত করতে হবে। বাইন্ডারটি নির্ভর করে যে কীভাবে নির্ভরতা ইঞ্জেকশনটি আপনার ক্লাস তৈরি করবে।

public class MyApplicationBinder extends AbstractBinder {
    @Override
    protected void configure() {
        bind(MyService.class).to(MyService.class);
    }
}

যখন @Injectকোনও প্যারামিটার বা প্রকারের ক্ষেত্রটিতে সনাক্ত হয় MyService.classএটি ক্লাস ব্যবহার করে ইনস্ট্যান্ট করা হয় MyService। এই বাইন্ডারটি ব্যবহার করতে, এটি JAX-RS অ্যাপ্লিকেশনটির সাথে নিবন্ধিত হওয়া দরকার। আপনার মধ্যে web.xml, একটি জ্যাক্স-আরএস অ্যাপ্লিকেশনটি সংজ্ঞায়িত করুন:

<servlet>
  <servlet-name>MyApplication</servlet-name>
  <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
  <init-param>
    <param-name>javax.ws.rs.Application</param-name>
    <param-value>com.mypackage.MyApplication</param-value>
  </init-param>
  <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
  <servlet-name>MyApplication</servlet-name>
  <url-pattern>/*</url-pattern>
</servlet-mapping>

MyApplicationক্লাসটি প্রয়োগ করুন (উপরে উল্লিখিত init-param)।

public class MyApplication extends ResourceConfig {
    public MyApplication() {
        register(new MyApplicationBinder());
        packages(true, "com.mypackage.rest");
    }
}

বাইন্ডার নির্দিষ্ট করে নির্ভরতা ইনজেকশনটি ক্লাসের কনস্ট্রাক্টারে নিবন্ধিত রয়েছে এবং আমরা পদ্ধতিটি কলটি MyResourceব্যবহার করে আরআরইএসটি রিসোর্সগুলি (আপনার ক্ষেত্রে, ) কোথায় পাবেন তাও আমরা অ্যাপ্লিকেশনটিকে packages()বলি।


1
অ্যান্টিটি ম্যানেজার সম্পর্কে কী? কীভাবে বাঁধবেন কোনও ইঙ্গিত, তাই আমি @PersistanceContext এর মাধ্যমে এটি ইনজেক্ট করতে পারি?
জোহানেস স্টেহলিন

4
আমি কী তা নিশ্চিত নই EntityManager, তবে ডকস.অরাকল.com/ জাভা / //api/javax/persistance/… দ্বারা বিচার করা এটি একটি ইন্টারফেস বলে মনে হচ্ছে। আপনি এটি ব্যবহার করে বেঁধে রাখতে পারেন bind(EntityManagerImpl.class).to(EntityManager.class)(যা EntityManagerImplইন্টারফেস প্রয়োগকারী কোনও শ্রেণিকে আবদ্ধ করবে you EntityManagerযদি আপনাকে কোনও কারখানা ব্যবহার করার প্রয়োজন হয় তবে bindFactory()এটি একবার দেখুন AbstractBinder। আপনার যদি এই সহায়তার প্রয়োজন হয় তবে দয়া করে একটি নতুন প্রশ্ন তৈরি করুন (আমার কাছে জায়গা নেই মন্তব্যে এর জবাব দিন) এছাড়াও, আমি নিশ্চিত না যে আপনার @ পার্সিয়েন্ট কনটেক্সট ব্যবহার করা উচিত, সবকিছুর জন্য কেবল @ ইনজেক্ট ব্যবহার করুন
joscarsson

হ্যাঁ, সত্তা ম্যানেজারটি জেপিএ (জাভা ইই) নির্দিষ্ট। আপনার মন্তব্যের জন্য ধন্যবাদ, আমি যদি একটি নির্দিষ্ট সমস্যা নিয়ে চলে যাই তবে আমি আরও একটি প্রশ্ন খুলব!
জোহানেস স্টেহলিন

শুধু রেকর্ডের জন্য, জেপিএ জাভা এসইতেও চলে। oracle.com/technetwork/java/javaee/tech/…
prefabSOFT

2
বাঁধাই কি করে? আমার যদি একটি ইন্টারফেস এবং একটি বাস্তবায়ন থাকে?
ডিজেল

52

প্রথমে গ্রহণের উত্তরগুলিতে একটি মন্তব্যের উত্তর দেওয়ার জন্য।

"বাঁধাই কী করে? আমার যদি একটি ইন্টারফেস এবং বাস্তবায়ন থাকে তবে কী হবে?"

এটা সহজভাবে পড়া bind( implementation ).to( contract )। আপনি বিকল্প চেইন করতে পারেন .in( scope )। এর ডিফল্ট সুযোগ PerLookup। সুতরাং আপনি যদি একটি সিঙ্গলটন চান, আপনি পারেন

bind( implementation ).to( contract ).in( Singleton.class );

একটি RequestScopedউপলব্ধ আছে

এছাড়াও, পরিবর্তে bind(Class).to(Class), আপনি এটিও করতে পারেন bind(Instance).to(Class), যা স্বয়ংক্রিয়ভাবে সিঙ্গলটন হবে।


গৃহীত উত্তরে যুক্ত করা হচ্ছে

AbstractBinderআপনার ওয়েব.এক্সএমএমএল (যেমন আপনি কোনও ব্যবহার করছেন না ResourceConfig) আপনার প্রয়োগটি কীভাবে নিবন্ধভুক্ত করবেন তা বোঝার চেষ্টা করছেন তাদের কাছে মনে হয় প্যাকেজ স্ক্যানিংয়ের মাধ্যমে বাইন্ডারটি আবিষ্কার করা হবে না, অর্থাৎ

<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
    <param-name>jersey.config.server.provider.packages</param-name>
    <param-value>
        your.packages.to.scan
    </param-value>
</init-param>

অথবা এটি হয়

<init-param>
    <param-name>jersey.config.server.provider.classnames</param-name>
    <param-value>
        com.foo.YourBinderImpl
    </param-value>
</init-param>

এটি কাজ করতে, আমাকে একটি প্রয়োগ করতে হয়েছিল Feature:

import javax.ws.rs.core.Feature;
import javax.ws.rs.core.FeatureContext;
import javax.ws.rs.ext.Provider;

@Provider
public class Hk2Feature implements Feature {

    @Override
    public boolean configure(FeatureContext context) {
        context.register(new AppBinder());
        return true;
    }
}

@Providerটীকা অনুমতি থাকবে Featureপ্যাকেজ স্ক্যানিং দ্বারা কুড়ান হবে। বা প্যাকেজ স্ক্যানিং ছাড়াই আপনি স্পষ্টভাবে রেজিস্টার করতে পারেন Featureমধ্যেweb.xml

<servlet>
    <servlet-name>Jersey Web Application</servlet-name>
    <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
    <init-param>
        <param-name>jersey.config.server.provider.classnames</param-name>
        <param-value>
            com.foo.Hk2Feature
        </param-value>
    </init-param>
    ...
    <load-on-startup>1</load-on-startup>
</servlet>

আরো দেখুন:

এবং জার্সির ডকুমেন্টেশন থেকে সাধারণ তথ্যের জন্য


হালনাগাদ

কারখানা

গৃহীত উত্তরের মূল বাইন্ডিং বাদে আপনার কাছে কারখানা রয়েছে, যেখানে আপনার আরও জটিল সৃষ্টি যুক্তি থাকতে পারে এবং প্রসঙ্গে তথ্যের অনুরোধ করার অ্যাক্সেসও থাকতে পারে। উদাহরণ স্বরূপ

public class MyServiceFactory implements Factory<MyService> {
    @Context
    private HttpHeaders headers;

    @Override
    public MyService provide() {
        return new MyService(headers.getHeaderString("X-Header"));
    }

    @Override
    public void dispose(MyService service) { /* noop */ }
}

register(new AbstractBinder() {
    @Override
    public void configure() {
        bindFactory(MyServiceFactory.class).to(MyService.class)
                .in(RequestScoped.class);
    }
});

তারপরে আপনি MyServiceনিজের রিসোর্স ক্লাসে ইনজেক্ট করতে পারেন ।


আমি গ্রহণযোগ্য উত্তরে যেমন দেখানো হয়েছে ঠিক তেমন একটি রিসোর্স কনফিগ বাস্তবায়নের মাধ্যমে আমি আমার বাইন্ডার ক্লাসটি নিবন্ধ করতে পারি। কোন ফিচার ক্লাস দরকার ছিল না।
প্যাট্রিক কোরেভর

চালু থাকা web.xmlসত্ত্বেও ব্যবহার করা , সংস্থানটির অনুরোধ করে একটি । @ পলসমসোথাconfigure()Hk2FeatureNullPointerException
বাইটস্যান্ডক্যাফিন

12

নির্বাচিত উত্তরের কিছুক্ষণ আগে থেকে তারিখ। কাস্টম এইচকে 2 বাইন্ডারে প্রতিটি বাঁধাই ঘোষণা করা ব্যবহারিক নয়। আমি টমক্যাট ব্যবহার করছি এবং আমাকে কেবল একটি নির্ভরতা যুক্ত করতে হয়েছিল। যদিও এটি গ্লাসফিশের জন্য ডিজাইন করা হয়েছিল এটি অন্যান্য পাত্রে পুরোপুরি ফিট করে।

   <dependency>
        <groupId>org.glassfish.jersey.containers.glassfish</groupId>
        <artifactId>jersey-gf-cdi</artifactId>
        <version>${jersey.version}</version>
    </dependency>

আপনার ধারকটিও সঠিকভাবে কনফিগার হয়েছে কিনা তা নিশ্চিত করুন ( ডকুমেন্টেশন দেখুন )।


শেষ লাইনটি (আপনার ধারকটিও ঠিকঠাকভাবে কনফিগার করা আছে কিনা তা নিশ্চিত করুন) কিছুটা অস্পষ্ট। এখানে কোন সাহায্য? আমরা কোথায় কোন টীকাগুলি ব্যবহার করব?
মার্কথেগ্রিয়া

আমরা নির্ভরতা ইঞ্জেকশনের জন্য ওয়েল্ড ব্যবহার করছিলাম যার জন্য টমক্যাট (আমাদের অ্যাপ্লিকেশন "ধারক") এর সাথে কাজ করার জন্য কিছু বিশেষ কনফিগার প্রয়োজন। আপনি যদি স্প্রিং ব্যবহার করছেন তবে এটি বাক্সের বাইরে চলে।
ওন্টোলেট

5

দেরীতে তবে আমি আশা করি এটি কারও সহায়ক হবে।

আমি আমার জ্যাক্স আরএস এর মতো সংজ্ঞায়িত করেছি:

@Path("/examplepath")
@RequestScoped //this make the diference
public class ExampleResource {

তারপরে, আমার কোডে শেষ পর্যন্ত আমি ইনজেকশন করতে পারি:

@Inject
SomeManagedBean bean;

আমার ক্ষেত্রে, এটি SomeManagedBeanএকটি অ্যাপ্লিকেশনকপি শিম।

আশা করি এটি কারও পক্ষে সহায়তা করবে।


3

ওরাকল সিডিআইয়ের সাথে জ্যাকএক্স-আরএস সংযুক্ত করার সময় সমস্ত ধরণের ইনজেকশনের জন্য @ পাঠ্য টীকা যুক্ত করার পরামর্শ দেয়: http://docs.oracle.com/javaee/7/tutorial/jaxrs-advanced004.htm যদিও এটি নিখুঁত নয় ( যেমন আপনি শুরুতে জার্সির কাছ থেকে সতর্কতা পাবেন), আমি এই রুটটি নেওয়ার সিদ্ধান্ত নিয়েছি, যা আমাকে একটি বাইন্ডারের মধ্যে সমস্ত সমর্থিত প্রকারের রক্ষণ থেকে বাঁচায়।

উদাহরণ:

@Singleton
@Path("singleton-configuration-service")
public class ConfigurationService {
  .. 
}

@Path("my-path")
class MyProvider {
  @Inject ConfigurationService _configuration;

  @GET
  public Object get() {..}
}

1
লিঙ্কটি মারা গেছে, এখানে
হ্যাঙ্ক

0

আপনি যদি গুইস ব্যবহার করতে পছন্দ করেন এবং আপনি সমস্ত বাঁধাই ঘোষণা করতে না চান, আপনি এই অ্যাডাপ্টারের চেষ্টাও করতে পারেন:

guice-সেতু-jit-প্রবেশক


0

আমার জন্য এটি AbstractBinderযদি আমার ওয়েব অ্যাপ্লিকেশনটিতে নিম্নলিখিত নির্ভরতাগুলি অন্তর্ভুক্ত না করে কাজ করে (টমক্যাট 8.5, জার্সি ২.২27 এ চলমান):

<dependency>
    <groupId>javax.ws.rs</groupId>
    <artifactId>javax.ws.rs-api</artifactId>
    <version>2.1</version>
</dependency>
<dependency>
    <groupId>org.glassfish.jersey.containers</groupId>
    <artifactId>jersey-container-servlet</artifactId>
    <version>${jersey-version}</version>
</dependency>
<dependency>
    <groupId>org.glassfish.jersey.ext.cdi</groupId>
    <artifactId>jersey-cdi1x</artifactId>
    <version>${jersey-version}</version>
</dependency>
<dependency>
    <groupId>org.glassfish.jersey.inject</groupId>
    <artifactId>jersey-hk2</artifactId>
    <version>${jersey-version}</version>
</dependency>

এটি আমার জন্য সিডিআই 1.2 / সিডিআই 2.0 নিয়ে কাজ করে (যথাক্রমে ওয়েল্ড 2/3 ব্যবহার করে)।


0

জার্সি বিশ্রামের পরিষেবাটির জন্য নির্ভরতা প্রয়োজন এবং টমক্যাটটি সার্ভার। যেখানে {ers jersey.version 2. ২.২৯.২.১

    <dependency>
        <groupId>javax.enterprise</groupId>
        <artifactId>cdi-api</artifactId>
        <version>2.0.SP1</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>org.glassfish.jersey.core</groupId>
        <artifactId>jersey-server</artifactId>
        <version>${jersey.version}</version>
    </dependency>
    <dependency>
        <groupId>org.glassfish.jersey.containers</groupId>
        <artifactId>jersey-container-servlet</artifactId>
        <version>${jersey.version}</version>
    </dependency>
    <dependency>
        <groupId>org.glassfish.jersey.inject</groupId>
        <artifactId>jersey-hk2</artifactId>
        <version>${jersey.version}</version>
    </dependency>

বেসিক কোডটি নিম্নরূপ হবে:

@RequestScoped
@Path("test")
public class RESTEndpoint {

   @GET
   public String getMessage() {
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.