Spring Boot - Auto wiring service having String constructor - spring-boot

How do i #autowire bean class TransactionManagerImpl which is having 1(String) argument constructor without using new in spring-boot application?
Even after searching through many post i couldn't get any clue to autowire without using new
I need to autowire TransactionManager in three different classes and the parameters are different in all three classes.
This looks like very basic scenario.
#Service
public class TransactionManagerImpl implements TransactionManager {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
String txnLogFile;
#ConstructorProperties({"txnLogFile"})
public TransactionManagerImpl(String txnLogFile) {
this.txnLogFile= txnLogFile;
}
}

is there any specific requirement where you want to use #Service annotation?
if not then you can use #Bean to create a bean for TransactionManagerImpl like below.
#Configuration
public class Config {
#Value("${txnLogFile}")
private String txnLogFile;
#Bean
public TransactionManager transactionManager() {
return new TransactionManagerImpl(txnLogFile);
}
}
and remove #Service annotation from TransactionManagerImpl.

Putting aside other complications, it can be done like this
public TransactionManagerImpl(#Value("${txnLogFile}") String txnLogFile) {
this.txnLogFile= txnLogFile;
}

Finally, i did it as below, now sure if this is the best way to do. I did not want to have three implementation just because of one variable.
application.yaml
app:
type-a:
txn-log-file: data/type-a-txn-info.csv
type-b:
txn-log-file: data/type-b-txn-info.csv
default:
txn-log-file: data/default/txn-info.csv
MainApplication.java
#SpringBootApplication
public class MainApplication {
public static void main(String[] args) {
new SpringApplicationBuilder(MainApplication.class).web(WebApplicationType.NONE).run(args);
}
#Bean
public TransactionManager transactionManager(#Value("${app.default.txn-log-file}") String txnLogFile) {
return new TransactionManagerImpl(txnLogFile);
}
#Bean
public CsvService csvService(String txnLogFile) {
return new CsvServiceImpl(txnLogFile);
}
}
TypeOneRoute.java
#Configuration
public class TypeOneRoute extends RouteBuilder {
#Value("${app.type-a.txn-log-file}")
private String txnLogFile;
#Autowired
private ApplicationContext applicationContext;
private TransactionManager transactionManager;
#Override
public void configure() throws Exception {
transactionManager = applicationContext.getBean(TransactionManager.class, txnLogFile);
transactionManager.someOperation();
}
}
TypeTwoRoute.java
#Configuration
public class TypeTwoRoute extends RouteBuilder {
#Value("${app.type-b.txn-log-file}")
private String txnLogFile;
#Autowired
private ApplicationContext applicationContext;
private TransactionManager transactionManager;
#Override
public void configure() throws Exception {
transactionManager = applicationContext.getBean(TransactionManager.class, txnLogFile);
transactionManager.create();
}
}
TransactionManager.java
#Service
#Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public interface TransactionManager {
public ZonedDateTime create() throws IOException, ParseException;
}
TransactionManagerImpl.java
public class TransactionManagerImpl implements TransactionManager {
#Autowired
private ApplicationContext applicationContext;
private String txnLogFile;
public TransactionManagerImpl(String txnLogFile) {
this.txnLogFile = txnLogFile;
}
private CsvService csvService;
#PostConstruct
public void init() {
csvService = applicationContext.getBean(CsvService.class, txnLogFile);
}
public ZonedDateTime create() throws IOException, ParseException {
try {
csvService.createTxnInfoFile();
return csvService.getLastSuccessfulTxnTimestamp();
} catch (IOException e) {
throw new IOException("Exception occured in getTxnStartDate()", e);
}
}
}
Initially TransactionManager Bean will be registered with the app.default.txn-info.csv and when i actually get it from ApplicationContext i am replacing the value with the parameter passed to get the bean from ApplicationContext

Related

Spring #Autowired field returns null on type of PropertySourcesPlaceholderConfigurer bean object

my colde below
/* this bean is the bean that alwyas returned as null*/
#Component
public class ContextHolder implements ApplicationContextAware, ServletContextAware {
private static ApplicationContext springContext;
private static ServletContext servletContext;
#Override
public void setServletContext(ServletContext servletContext) {
this.servletContext = servletContext;
}
#Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.springContext = applicationContext;
}
public static ApplicationContext getSpringContext() {
return springContext;
}
public static ServletContext getServletContext() {
return servletContext;
}
}
#Component
#PropertySource("classpath:appProps/globals-${spring.profiles.active}.properties")
public class PropertyManager extends PropertySourcesPlaceholderConfigurer {
#Autowired
ContextHolder contextHolder; // this binding alwasy return null. I don't know the why
public String get(String key) {
// NullpointerException occurs, because contextHolder is null
// But ContextHodler.getSpringContext() static access works, but I want to know
// why Autowired does not work
return contextHolder.getSpringContext().getEnvironment().getProperty(key);
}
}
I want to know why Autowired does not work.
I have search the answer in google. but there no documents about this.
I guess PropertySourcesPlaceholderConfigurer is type of BeanFactoryPostProcessor, So when initialize the PropertySourcesPlaceHolderConfiguer there are no bean of ContextHolder instance in memory, thus contextHolder is null??

Spring Batch : How to change the default isolation level?

I read in the documentation :
"The default is ISOLATION_SERIALIZABLE, which prevents accidental
concurrent execution of the SAME job"
However, when I launch DIFFERENT jobs at the the same time (with a default isolation level at SERIALIZABLE), I have the error : ORA-08177: can't serialize access for this transaction. Is it normal ?
Second, to change the Default Isolation Level to READ_COMMITTED, I understood that we can't change this level in application.properties, and, that I have to redefine BatchConfigurer. Exact ?
Using BasicBatchConfigurer, I must define an explicit contructor (implicit super constructor BasicBatchConfigurer() is undefined for default constructor).
However, I have the error :
Parameter 0 of constructor in MyBatchConfigurer required a bean of type 'org.springframework.boot.autoconfigure.batch.BatchProperties' that could not be found.
How to create : BatchProperties properties, DataSource dataSource and TransactionManagerCustomizers transactionManagerCustomizers ?
This is my code :
PeopleApplication.java
#SpringBootApplication
#EnableAutoConfiguration(exclude = { BatchAutoConfiguration.class })
public class PeopleApplication {
public static void main(String[] args) throws Exception {
ConfigurableApplicationContext ctx = new SpringApplicationBuilder(PeopleApplication.class)
.web(WebApplicationType.NONE)
.run(args);
int exitValue = SpringApplication.exit(ctx);
System.exit(exitValue);
}
}
MyBatchConfigurer.java
#Component
#PropertySource("classpath:fileA.properties")
public class MyBatchConfigurer extends BasicBatchConfigurer implements CommandLineRunner, ExitCodeGenerator {
protected MyBatchConfigurer(BatchProperties properties, DataSource dataSource, TransactionManagerCustomizers transactionManagerCustomizers) {
super(properties, dataSource, transactionManagerCustomizers);
}
#Override
protected String determineIsolationLevel() {
return "ISOLATION_" + Isolation.READ_COMMITTED;
}
#Override
public void run(String... args) {
...
}
...
}
Regards.
RESPONSE :
use #EnableAutoConfiguration instead of :
#EnableAutoConfiguration(exclude = { BatchAutoConfiguration.class })
Like this, the bean BatchProperties, DataSource and TransactionManagerCustomizers will be automatically created.
Please see the reply from Mahmoud that explains very clearly
can't serialize access for this transaction in spring batch.
Example for the usage is below and override only isolation level
--application.properties
spring.application.name=SpringBatch
####### SPRING ##############
spring.main.banner-mode=off
spring.main.web-application-type=none
spring.batch.initialize-schema=always
spring.batch.job.enabled=false // Disable default if you want to control
########JDBC Datasource########
#connection timeout 10 min
spring.datasource.hikari.connection-timeout=600000
spring.datasource.hikari.minimum-idle=5
spring.datasource.hikari.maximum-pool-size=100
spring.datasource.hikari.idle-timeout=600000
spring.datasource.hikari.max-lifetime=1800000
spring.datasource.hikari.auto-commit=true
spring.datasource.hikari.poolName=SpringBoot-HikariCP
spring.datasource.url=jdbc:oracle:thin:#ngecom.ae:1521:ngbilling
spring.datasource.username=ngbilling
springbatch.datasource.password=ngbilling
#SpringBootApplication
public class YourApplication {
public static void main(String[] args) {
SpringApplication.run(SsadapterApplication.class, args);
}
}
// Your manual batch scheduler
class BatchJobScheduler extends BasicBatchConfigurer {
#Autowired
private JobLauncher jobLauncher;
#Autowired
private ApplicationArguments args;
#Autowired
private Job myJob;
protected BatchJobScheduler(BatchProperties properties, DataSource dataSource,
TransactionManagerCustomizers transactionManagerCustomizers) {
super(properties, dataSource, transactionManagerCustomizers);
}
#Override
protected String determineIsolationLevel() {
return "ISOLATION_" + Isolation.READ_COMMITTED;
}
//#Scheduled(cron = "${batch.cron}")
public void notScheduledJob() {
appId= args.getOptionValues("appId").get(0);
JobParameters params = new JobParametersBuilder().addLong("jobId"+appId, System.currentTimeMillis())
.toJobParameters();
jobLauncher.run(myJob, params);
}
// Your batch Configuration And Spring will do everything for you to available
#Configuration
#EnableBatchProcessing
#EnableScheduling
public class BatchConfiguration {
Logger logger = LoggerFactory.getLogger(BatchConfiguration.class);
#Value("${batch.commit.chunk}")
private Integer chunkSize;
#Value("${batch.error.skipCount}")
private Integer skipErrorCount;
#Autowired
private Environment environment;
#Autowired
public JobBuilderFactory jobBuilderFactory;
#Autowired
public StepBuilderFactory stepBuilderFactory;
#Autowired
private DataSource dataSource;
#Autowired
private ApplicationArguments args;
#Autowired
private JdbcTemplate jdbcTemplate;
#Bean
public Job myJob() throws Exception {
return jobBuilderFactory.get("myJob").incrementer(new RunIdIncrementer())
.listener(new JobListener()).start(myStep()).build();
}
#Bean
public Step myStep() throws Exception {
return stepBuilderFactory.get("myStep").<InputObject, OutPutObject>chunk(chunkSize)
.reader(yourReader(null)).processor(yourProcessor()).writer(yourWriter())
//.faultTolerant()
//.skipLimit(skipErrorCount).skip(Exception.class)//.noSkip(FileNotFoundException.class)
.listener(invoiceSkipListener())
//.noRetry(Exception.class)
//.noRollback(Exception.class)
.build();
}

Couldn't find PersistentEntity for type class when using #EnableMongoAuditing

I am getting "Couldn't find PersistentEntity for type class" error when I am using #EnableMongoAuditing features along with MongoRepository.
This happens when I save a document when collection isn't already present in database.
I tried whatever is mentioned in:
https://github.com/spring-projects/spring-boot/issues/12023
https://jira.spring.io/browse/DATAMONGO-1999
Spring boot mongodb auditing error
but nothing is working.
Mentioned things are:
Extend MongoConfig by AbstractMongoConfiguration and override all methods.
Here is my code which reproduced the same error:
MongoConfig class
#Configuration
public class MongoConfig extends AbstractMongoConfiguration {
#Value("${spring.data.mongodb.host}")
private String mongoHost;
#Value("${spring.data.mongodb.port}")
private String mongoPort;
#Value("${spring.data.mongodb.database}")
private String mongoDB;
#Override
public MongoDbFactory mongoDbFactory() {
return new SimpleMongoDbFactory(new MongoClient(mongoHost + ":" + mongoPort), mongoDB);
}
#Override
public MongoClient mongoClient() {
return new MongoClient(mongoHost, Integer.parseInt(mongoPort));
}
#Override
public MongoTemplate mongoTemplate() {
return new MongoTemplate(mongoDbFactory());
}
#Override
public MappingMongoConverter mappingMongoConverter() {
return new MappingMongoConverter(new DefaultDbRefResolver(mongoDbFactory()), new MongoMappingContext());
}
#Override
protected String getDatabaseName() {
return mongoDB;
}
}
Person Collection class
#Document
public class Person {
#Id
private String id;
private String name;
#CreatedDate
private LocalDateTime createdAt;
#LastModifiedDate
private LocalDateTime lastModified;
// Getter Setters Constructors omitted for brevity
}
Main Application class
#EnableMongoAuditing
#EnableMongoRepositories ({"com.example.*", "org.apache.*"})
#SpringBootApplication
#ComponentScan({"com.example.*", "org.apache.*"})
public class DemoApplication implements CommandLineRunner {
#Autowired
PersonRepository personRepository;
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
#Override
public void run(String... args) throws Exception {
Person p1 = new Person("1", "prakhar");
personRepository.save(p1);
}
}
Expected Result is Person entity should be saved in database.
Actual Result is "Couldn't find PersistentEntity for type class Person" error
Looks like you ran into https://github.com/spring-projects/spring-boot/issues/12023
Extending AbstractMongoConfiguration will switch off Spring Boot's auto-configuration of various Mongo components and also customises the base packages that are used to scan for mappings. I would recommend that you don't use it in Spring Boot.
Update
I managed to get the example running with the configuration as simple as
#Configuration
public class MongoConfig {
#Value("${spring.data.mongodb.host}")
private String mongoHost;
#Value("${spring.data.mongodb.port}")
private String mongoPort;
#Value("${spring.data.mongodb.database}")
private String mongoDB;
#Bean
public MongoDbFactory mongoDbFactory() {
return new SimpleMongoDbFactory(new MongoClient(mongoHost + ":" + mongoPort), mongoDB);
}
#Bean
public MongoClient mongoClient() {
return new MongoClient(mongoHost, Integer.parseInt(mongoPort));
}
}
and the app class
#EnableMongoAuditing
#SpringBootApplication
public class DemoApplication implements CommandLineRunner {
#Autowired
PersonRepository personRepository;
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
#Override
public void run(String... args) throws Exception {
Thread.sleep(2000);
Person p1 = new Person("1", "prakhar");
personRepository.save(p1);
}
}
Notice that I followed my own advice and did't inherit from AbstractMongoConfiguration
Explanation
The problem lies in the initialization of
#Bean
public MappingMongoConverter mappingMongoConverter() {
return new MappingMongoConverter(new DefaultDbRefResolver(mongoDbFactory()), new MongoMappingContext());
}
You simply call MongoMappingContext constructor, without calling setInitialEntitySet. Compare that with MongoDataConfiguration auto-configuration class.
#Bean
#ConditionalOnMissingBean
public MongoMappingContext mongoMappingContext(MongoCustomConversions conversions)
throws ClassNotFoundException {
MongoMappingContext context = new MongoMappingContext();
context.setInitialEntitySet(new EntityScanner(this.applicationContext)
.scan(Document.class, Persistent.class));
Class<?> strategyClass = this.properties.getFieldNamingStrategy();
if (strategyClass != null) {
context.setFieldNamingStrategy(
(FieldNamingStrategy) BeanUtils.instantiateClass(strategyClass));
}
context.setSimpleTypeHolder(conversions.getSimpleTypeHolder());
return context;
}
Even worse, you don't register MongoMappingContext as a managed bean.
Due to this fact, auto-configuration class is still created. This leads to a race condition, I tried to run the original code and could easily reproduce the error, but with a breakpoint in AbstractMappingContext.addPersistentEntity the test always passed.
For me I resolved this issue by adding following method in MongoConfig if your class extends from AbstractMongoConfiguration
#Override
protected String getMappingBasePackage() {
return "com.companyName.modulename"
}
If MongoConfig extends from MongoConfigurationSupport then add below method
#Override
protected Collection<String> getMappingBasePackages() {
return Arrays.asList("com.companyName.module1","com.companyName.module2");
}
Note that in later case I can specify multiple package names as base packages.

Spring boot #Autowired is not working in the servlet duriing the server startup

I have servlet whose load on startup property is '1', in this servlet I have to cache database entries during the application server startup.
In this servlet I am calling the CacheService which retrieves the db objects, its annotated with #Autowired annoatation, during the application startup the CacheService object is null.I have annotated the CacheService with #Service annotation. The #Autowired annotation is not working.
#Service
public class CacheService {
#Autowired
private IJobsService jobsServiceImpl;
public List<Jobs> getALLJobs(){
List<Jobs> alljobs = jobsServiceImpl.findAllJobs();
return alljobs;
}
}
public class StartupServlet extends HttpServlet {
#Autowired
private CacheService cacheService; -- object is null not autowired
}
Below is the main class
#EnableCaching
#EnableJpaRepositories(basePackages = {"com.example.demo.repository"})
#EntityScan(basePackages = {"com.example.demo.entity"})
#SpringBootApplication
#ComponentScan(basePackages={"com.example.demo"})
#EnableAutoConfiguration(exclude = {
org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration.class,
org.springframework.boot.actuate.autoconfigure.ManagementWebSecurityAutoConfiguration.class})
public class DemoApplication extends SpringBootServletInitializer implements WebApplicationInitializer{
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(DemoApplication.class);
}
#Bean
ServletRegistrationBean myServletRegistration () {
ServletRegistrationBean srb = new ServletRegistrationBean();
srb.setServlet(new StartupServlet());
srb.setUrlMappings(Arrays.asList("/path2/*"));
srb.setLoadOnStartup(1);
return srb;
}
}
Could some body help me on this...?
You should do some additional work for this. You have to talk to beanFactory-like spring component and ask it to make that particular instance an eligible bean. AutowireCapableBeanFactory should do the trick.
Here is a simple example based on code you have provided
#SpringBootApplication
public class So44734879Application {
public static void main(String[] args) {
SpringApplication.run(So44734879Application.class, args);
}
#Autowired
AutowireCapableBeanFactory beanFactory;
#Bean
ServletRegistrationBean myServletRegistration() {
ServletRegistrationBean srb = new ServletRegistrationBean();
final StartupServlet servlet = new StartupServlet();
beanFactory.autowireBean(servlet); // <--- The most important part
srb.setServlet(servlet);
srb.setUrlMappings(Arrays.asList("/path2/*"));
srb.setLoadOnStartup(1);
return srb;
}
#Bean
MyService myService() {
return new MyService();
}
public static class MyService {
String time() {
return "Time: " + System.currentTimeMillis();
}
}
public static class StartupServlet extends HttpServlet {
#Autowired
MyService myService;
#Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
final PrintWriter writer = resp.getWriter();
writer.write(myService.time());
writer.close();
}
}
}
=>
$ curl -XGET localhost:8080/path2
Time: 1498299772141%
You're creating the servlet by using new so you need to provide its dependencies. Since you're using a mix of annotation and java code configuration you can accomplish it like this:
public class StartupServlet extends HttpServlet {
private CacheService cacheService;
public StartupServlet(CacheService cacheService) {
this.cacheService = cacheService;
}
// ... rest of servlet
}
Main class:
#Bean
ServletRegistrationBean myServletRegistration (CacheService cacheService) { // <<<--- cacheService will be provided here by Spring because it's annotated
ServletRegistrationBean srb = new ServletRegistrationBean();
srb.setServlet(new StartupServlet(cacheService));
srb.setUrlMappings(Arrays.asList("/path2/*"));
srb.setLoadOnStartup(1);
return srb;
}

How to fix xml-less autowiring of service

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.
My app:
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();
}
}
My Resource (controller):
#Component
#Path("/job")
public class JobResource extends GenericResource {
#Path("/new")
#POST
public String New(NewJobRequest request) {
return "done";
}
}
Jersey is mapping the JSON post to:
#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);
}
}
My service config:
#Configuration
public class Config {
#Bean
public VendorService vendorService() {
return new VendorService();
}
}
My config
#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;
}
}
The #Path and #POST annotations are JAX-RS, not Spring. So the container is instantiating your endpoints on its own, without any knowledge of Spring beans. You are most likely not getting any Spring logging because Spring is not being used at all.
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:
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
}
....
}

Resources