reload in play framework 2.2 java giving exceptions when used with spring data jpa and hibernate - spring

I am using Play Framework 2.2, Hibernate as JPA provider (4.2.8.Final), Spring (4.0.1.RELEASE) and Spring Data JPA (1.4.3.RELEASE).
I am using spring to instantiate to the controllers and using context:component-scan at the application load time to collect and configure all the required dependencies(repositories etc).
The way I have configured spring with play framework is
public class Global extends GlobalSettings {
private ApplicationContext applicationContext;
#Override
public void onStart(Application arg0) {
String configLocation = Play.application().configuration().getString("spring.context.location");
applicationContext = new ClassPathXmlApplicationContext(configLocation);
}
#Override
public <A> A getControllerInstance(Class<A> type) throws Exception {
return applicationContext.getBean(type);
}
}
and relevant section in application-context.xml is
Everything works extremely good when application loads for the first time. How ever as soon as I make any changes either in views or controllers and application reloads, Spring Data Jpa breaks and complains that my models are not of managed types.
Caused by: java.lang.IllegalArgumentException: Not an managed type: class models.User
Though it is not a problem in general, restarts works fine, I would really appreciate if someone can provide any inputs to reload the applicationContext completely on play reload.

I've had the same problem. Changing Spring Data JPA 1.4.3.RELEASE to 1.4.2.RELEASE solved it. I didn't have time to look further into the problem, so I don't know what is the cause.
This project is a good starting point: https://github.com/typesafehub/play-spring-data-jpa but it uses 1.3 version of Spring Data JPA.

Related

Spring (Security) dependency injection

I asked a question more specific to my case about 2 hours ago, but I realised I'm not really addressing my problem at the root cause.
I have a Spring application that uses Spring Security. Throughout my application, (Controllers, service classes etc) I'm using dependency injection and it all works fine. However, I recently started configuring Spring Security, and I can't inject any dependencies inside the classes in my "security" package. Online I read somewhere: "Also when you use #Autowired in the class of which you created a new instance, the Spring context will not be known to it and thus most likely this will also fail" and I was wondering if this maybe had something to do with my issue. My spring configuration basically has one "starting-point", that is the following class:
#Component
#Service
public class AppInitializer implements WebApplicationInitializer {
#Override
public void onStartup(ServletContext sc) throws ServletException {
AnnotationConfigWebApplicationContext root = new AnnotationConfigWebApplicationContext();
root.register(SecSecurityConfig.class);
sc.addListener(new ContextLoaderListener(root));
sc.addFilter("securityFilter", new DelegatingFilterProxy("springSecurityFilterChain"))
.addMappingForUrlPatterns(null, false, "/*");
}
}
This code is run on startup. As you can see, it is registering the SecSecurityConfig.class which is where I configure Spring Security. Inside of that class and onwards (all classes it uses and all classes that those classes use) I can't inject any dependencies. I was wondering if anyone could tell me what the problem could be. Sorry if I'm unclear or incorrect - please tell me so, I find the concept of DI somewhat hard to grasp. My component-scan in XML is: <context:component-scan base-package="com.qars"/> which is the package that my security package is also in.
Also all my classes are annotated with #Component or #Service

What Is the Correct Way To Use AbstractReactiveWebInitializer

I've got a Spring WebFlux application running successfully as a standalone spring boot application.
I am attempting to run the same application in a Tomcat container, and following the documentation, I've created a class that extends AbstractReactiveWebInitializer. The class requires that I implement a method getConfigClasses that would return classes normally annotated with #Configuration. If the working spring boot app started with a class called ApplicationInitializer, then the resulting implementations would look like this:
#SpringBootApplication(scanBasePackages = "my.pkg")
#EnableDiscoveryClient
#EnableCaching
public class ApplicationInitializer {
public static void main(String... args) {
SpringApplication.run(ApplicationInitializer.class, args);
}
}
and
public class ServletInitializer extends AbstractReactiveWebInitializer {
#Override
protected Class<?>[] getConfigClasses() {
return new Class[] {ApplicationInitializer.class};
}
}
When deployed, the only thing that starts is ApplicationInitializer, none of the autoconfigured Spring Boot classes (Cloud Config, DataSource, etc) ever kick off.
The documenation states this is the class I need to implement, I just expected the remainder of the spring environment to "just work".
How should I be using this class to deploy a Reactive WebFlux Spring Boot application to a Tomcat container ?
Edit:
After some additional research, I've narrowed it down to likely just Cloud Config. During bean post processing on startup, the ConfigurationPropertiesBindingPostProcessor should be enriched with additional property sources (from cloud config), but it appears to be the default Spring properties instead, with no additional sources.
The misisng properties is causing downstream beans to fail.
Spring Boot does not support WAR packaging for Spring WebFlux applications.
The documentation you're referring to is the Spring Framework doc; Spring Framework does support that use case, but without Spring Boot.
you can extend SpringBootServletInitializer, add add reactive servlet on onStartup method

Convert a Spring MVC application to Spring Boot - BeanCurrentlyInCreationException issue

I have a Spring MVC application, using Hibernate for my entities persistence management. I am able to build, deploy and run it on some application server such as glashfish or tomcat, all is fine.
Now, I want to convert it into a Spring Boot application. I added the following class:
#SpringBootApplication
public class Application extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
public static void main(String[] args) {
ConfigurableApplicationContext context =
SpringApplication.run(Application.class, args);
}
}
and added the spring-boot, spring-boot-autoconfigure, and spring-boot-starter-tomcat dependencies to my pom.
Alas, when trying to run the application, I get the following error:
BeanCurrentlyInCreationException: Error creating bean with name
'MyClassDAO': Bean with name 'MyClassDAO' has been injected into
other beans [MyOtherClassDAO] in its raw version as part of a circular
reference, but has eventually been wrapped. This means that said other
beans do not use the final version of the bean. This is often the result
of over-eager type matching - consider using 'getBeanNamesOfType' with
the 'allowEagerInit' flag turned off, for example.
I don't know how to use 'getBeanNamesOfType' and set the allowEagerInit off (I do not use XML configuration). Of course, I'm not sure this would solve my issue anyway.
Any ideas on how I can fix this?
If it's really some intilization issue then i believe the you must be having your class in other package and due to some cache issues it doesn't include those classes in class path to scan in container so to do this manually you can put a annotation just below #springbootapllication is #EnableComponentScan("enter the package name of the class which is not initializing") also on that dao class put #service or #component annotation to let the application include then in container

#Rollback(true) not working in spring boot 1.3.X

I have updated my pom from spring-boot-starter-parent 1.2.5.RELEASE to 1.3.2.RELEASE.
The problem is that everything stay the same but all the test #Rollback(true) not working at all after migration.
#Transactional
#Rollback(true)
#Test
public void testRollBack() {
dao.saveToDb();
throw new RunTimeException();
}
Configaturation:
#Bean
#Primary
public PlatformTransactionManager txManager() {
return new DataSourceTransactionManager(dataSource());
}
It works perfectly in the same configuration and code and the only change is spring boot version. I cannot see that Transaction is being created in logs as suppose too
Anyone has a clue? Maybe a way to debug and understand what is the problem?
Thanks
TransactionTestExecutionListener has changed quite a lot between Spring Framework 4.1 (used by Spring Boot 1.2) and Spring Framework 4.2 (used by Spring Boot 1.3). It sounds like there's been a change in behaviour which I suspect probably wasn't intentional.
To fix your problem without renaming one of your beans, you need to tell the test framework which transaction manager to use. The easiest way to do that is via the #Transactional annotation:
#Transactional("txManager")
#Rollback(true)
#Test
public void testRollBack() {
dao.saveToDb();
throw new RunTimeException();
}
I have put spring on debug..
There is a problem/bug in the test framework or i don't understand the use correctly.
I checked the code of spring and saw this:
bf.getBean(DEFAULT_TRANSACTION_MANAGER_NAME, PlatformTransactionManager.class);
This happens when we have several transaction manager, instead of getting the bean marked by #Primary annotation spring try to get transaction manager that called "transactionManager".
The solution is just mark the bean in that name.. Tried to open issue to spring-test project but don't know where.. If anyone knows how please advise.
Thanks
EDIT: So the solution is eiether what i have wrote above or just name them transaction(#Transactional("myManager")) and use it in the test method signature

Integrate Mongeez with Spring Boot and Spring Data MongoDB

I want to integrate Mongeez with my Spring Boot application and was wondering how to properly run Mongeez during application startup. Mongeez suggests creating a MongeezRunner bean. However, the challenge is to run Mongeez before any of the Spring Data initialization is happening, specifically, before the MongoTemplate instance is created. This is crucial because there might be changes in the database that prevent the application to start at all (e.g. changing index definitions).
My current approach is to provide the MongoTemplate bean myself, running Mongeez before creating it:
#Bean
public MongoTemplate mongoTemplate(Mongo mongo, MongoDbFactory mongoDbFactory,
MongoConverter converter) throws IOException {
// make sure that Mongeez runs before Spring Data is initialized
runMongeez(mongo);
return new MongoTemplate(mongoDbFactory, converter);
}
private void runMongeez(Mongo mongo) throws IOException {
Mongeez mongeez = new Mongeez();
mongeez.setMongo(mongo);
mongeez.setDbName(mongodbDatabaseName);
mongeez.setFile(new ClassPathResource("/db/migrations.xml"));
mongeez.process();
}
It works, but it feels like a hack. Is there any other way to do this?
After taking a look at Spring Boot's source code, it turns out that this problem isn't anything new. The FlywayAutoConfiguration for example has to make sure that Flyway (a migration tool for SQL-based databases) runs before any EntityManagerFactory beans are created. To achieve this the auto-configuration registers a BeanFactoryPostProcessor that dynamically makes every EntityManagerFactory bean depend on the Flyway bean, thus forcing Spring to create the Flyway bean first.
I solved my problem by creating a Spring Boot starter with a similar auto-configuration for Mongeez: mongeez-spring-boot-starter.

Resources