1

自分で直接サービスを呼び出すとmain()、データベースにクエリを実行でき、問題なく動作します。ジャージリクエストが届き、JSONをマップするとNewJobRequest、失敗したためサービスを使用できませ@Autowireん。

私のアプリ:

public class Main {

    public static final URI BASE_URI = getBaseURI();

    private static URI getBaseURI() {
        return UriBuilder.fromUri("http://localhost/").port(9998).build();
    }

    protected static HttpServer startServer() throws IOException {
        ResourceConfig rc = new PackagesResourceConfig("com.production.api.resources");
        rc.getFeatures()
            .put(JSONConfiguration.FEATURE_POJO_MAPPING, true);

        return GrizzlyServerFactory.createHttpServer(BASE_URI, rc);
    }

    public static void main(String[] args) throws IOException {
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(Config.class);

        //if this is uncommented, it'll successfully query the database
        //VendorService vendorService = (VendorService)ctx.getBean("vendorService");
        //Vendor vendor = vendorService.findByUUID("asdf"); 

        HttpServer httpServer = startServer();
        System.out.println(String.format("Jersey app started with WADL available at " + "%sapplication.wadl\nTry out %shelloworld\nHit enter to stop it...", BASE_URI, BASE_URI));
        System.in.read();
        httpServer.stop();
    }
}

私のリソース(コントローラー):

@Component
@Path("/job")
public class JobResource extends GenericResource {
    @Path("/new")
    @POST
    public String New(NewJobRequest request) {
        return "done";
    }
}

ジャージーはJSON投稿を次の場所にマッピングしています:

@Component
public class NewJobRequest {

    @Autowired
    private VendorService vendorService;

    @JsonCreator
    public NewJobRequest(Map<String, Object> request) {
        //uh oh, can't do anything here because @Autowired failed and vendorService is null
    }
}

VendorService:

@Service
public class VendorService extends GenericService<VendorDao> {

    public Vendor findByUUID(String uuid) {
        Vendor entity = null;
        try {
            return (Vendor)em.createNamedQuery("Vendor.findByUUID")
                    .setParameter("UUID", uuid)
                    .getSingleResult();
        } catch (Exception ex) {
            return null;
        }
    }
}

-

@Service
public class GenericService<T extends GenericDao> {

    private static Logger logger = Logger.getLogger(Logger.class.getName());

    @PersistenceContext(unitName = "unit")
    public EntityManager em;

    protected T dao;

    @Transactional
    public void save(T entity) {
        dao.save(entity);
    }
}

私のサービス構成:

@Configuration
public class Config {
    @Bean
    public VendorService vendorService() {
        return new VendorService();
    }
}

私の設定

@Configuration
@ComponentScan(basePackages = {
        "com.production.api",
        "com.production.api.dao",
        "com.production.api.models",
        "com.production.api.requests",
        "com.production.api.requests.job",
        "com.production.api.resources",
        "com.production.api.services"
})
@Import({
        com.production.api.services.Config.class,
        com.production.api.dao.Config.class,
        com.production.api.requests.Config.class
})
@PropertySource(value= "classpath:/META-INF/application.properties")
@EnableTransactionManagement
public class Config {
    private static final String PROPERTY_NAME_DATABASE_URL = "db.url";
    private static final String PROPERTY_NAME_DATABASE_USER = "db.user";
    private static final String PROPERTY_NAME_DATABASE_PASSWORD = "db.password";

    private static final String PROPERTY_NAME_HIBERNATE_DIALECT = "hibernate.dialect";
    private static final String PROPERTY_NAME_HIBERNATE_FORMAT_SQL = "hibernate.format_sql";
    private static final String PROPERTY_NAME_HIBERNATE_SHOW_SQL = "hibernate.show_sql";
    private static final String PROPERTY_NAME_ENTITYMANAGER_PACKAGES_TO_SCAN = "entitymanager.packages.to.scan";

    @Resource
    Environment environment;

    @Bean
    public DataSource dataSource() {
        MysqlDataSource dataSource = new MysqlDataSource();

        dataSource.setUrl(environment.getRequiredProperty(PROPERTY_NAME_DATABASE_URL));
        dataSource.setUser(environment.getRequiredProperty(PROPERTY_NAME_DATABASE_USER));
        dataSource.setPassword(environment.getRequiredProperty(PROPERTY_NAME_DATABASE_PASSWORD));

        return dataSource;
    }

    @Bean
    public JpaTransactionManager transactionManager() throws ClassNotFoundException {
        JpaTransactionManager transactionManager = new JpaTransactionManager();

        transactionManager.setEntityManagerFactory(entityManagerFactoryBean().getObject());

        return transactionManager;
    }

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean() throws ClassNotFoundException {
        LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();

        entityManagerFactoryBean.setDataSource(dataSource());
        entityManagerFactoryBean.setPersistenceUnitName("unit");
        entityManagerFactoryBean.setPackagesToScan(environment.getRequiredProperty(PROPERTY_NAME_ENTITYMANAGER_PACKAGES_TO_SCAN));
        entityManagerFactoryBean.setPersistenceProviderClass(HibernatePersistence.class);

        Properties jpaProperties = new Properties();
        jpaProperties.put(PROPERTY_NAME_HIBERNATE_DIALECT, environment.getRequiredProperty(PROPERTY_NAME_HIBERNATE_DIALECT));
        jpaProperties.put(PROPERTY_NAME_HIBERNATE_FORMAT_SQL, environment.getRequiredProperty(PROPERTY_NAME_HIBERNATE_FORMAT_SQL));
        jpaProperties.put(PROPERTY_NAME_HIBERNATE_SHOW_SQL, environment.getRequiredProperty(PROPERTY_NAME_HIBERNATE_SHOW_SQL));

        entityManagerFactoryBean.setJpaProperties(jpaProperties);

        return entityManagerFactoryBean;
    }
}
4

2 に答える 2

0

私はこの問題を理解し、ここにブログを書きました: http://blog.benkuhl.com/2013/02/how-to-access-a-service-layer-on-a-jersey-json-object/

それまでの間、私はここにも解決策を投稿するつもりです:

Spring が既に作成した Bean を利用する必要があるため、Spring のApplicationContextAwareを使用しました

public class ApplicationContextProvider implements ApplicationContextAware {
    private static ApplicationContext applicationContext;

    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    public void setApplicationContext (ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }
}

次に、オブジェクト内でその静的コンテキスト参照をマップ先として使用して、サービスでルックアップを実行できるようにします。

public class NewJobRequest {

    private VendorService vendorService;

    public NewJobRequest() {
        vendorService = (VendorService) ApplicationContextProvider.getApplicationContext().getBean("vendorService");
    }

    @JsonCreator
    public NewJobRequest(Map<String, Object> request) {
        setVendor(vendorService.findById(request.get("vendorId")); //vendorService is null
    }
    ....
}
于 2013-02-21T20:46:16.050 に答える
0

@Pathおよびアノテーションは、@POSTSpring ではなく JAX-RS です。そのため、コンテナーは、Spring Bean の知識がなくても、独自にエンドポイントをインスタンス化しています。Spring がまったく使用されていないため、Spring ログを取得していない可能性があります。

于 2013-02-21T19:41:26.133 に答える