如何修复服务的无XML自动装配 [英] How to fix xml-less autowiring of service

查看:133
本文介绍了如何修复服务的无XML自动装配的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我直接在main()中调用服务时,我可以查询数据库,并且一切正常.当球衣请求传入并将JSON映射到NewJobRequest时,我无法使用我的服务,因为@Autowire失败.

When I call a service directly in my main() I can query the database and things work fine. When a jersey request comes in and maps the JSON to NewJobRequest I can't use my service because the @Autowire failed.

我的应用:

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";
    }
}

Jersey正在将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;
    }
}

推荐答案

我已找出问题所在,并在此处进行了博客发布:

I've figured out the issue and blogged about it here: http://blog.benkuhl.com/2013/02/how-to-access-a-service-layer-on-a-jersey-json-object/

同时,我还将在此处发布解决方案:

In the mean time, I'm also going to post the solution here:

我需要利用Spring已经创建的bean,所以我使用了Spring的

I need to tap into the bean that Spring already created so I used Spring's ApplicationContextAware

public class ApplicationContextProvider implements ApplicationContextAware {
    private static ApplicationContext applicationContext;

    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }

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

然后使用要映射到我对象中的静态上下文引用,以便我可以在服务中执行查找:

And then used that static context reference within my object to be mapped to so I can perform lookups in the service:

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
    }
    ....
}

这篇关于如何修复服务的无XML自动装配的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆