Spring Boot version update breaks repository - java

See edit at the end...
I updated the dependencies of an app from 1.5.3-RELEASE to 1.5.9-RELEASE
***************************
APPLICATION FAILED TO START
***************************
Description:
Field mrepo in com.test.svc.TestHandler required a bean of type 'com.test.data.MongoTestRepository' that could not be found.
Action:
Consider defining a bean of type 'com.test.MongoTestRepository' in your configuration.
My Application.java is at com.test.Application and has the usual stuff:
#ServletComponentScan
#SpringBootApplication
public class Application extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
public static void main(String[] args) throws Exception {
SpringApplication.run(Application.class, args);
}
}
My TestHandler is a #Service
#Service
public class TestHandler {
#Autowired
private MongoTestRepository mrepo;
...
}
My MongoTestRepository is a #Repository interface that operates on MongoTest classes
#Repository
public interface MongoTestRepository extends MongoRepository<MongoTest, String> {
}
So, with the older version of the spring-boot packages (1.5.3-RELEASE) everything worked fine. Updating to 1.5.9-RELEASE and it builds but gives me the above error on deployment/startup.
What's going on here? Is there some new annotation that I'm missing? Why would a minor version update suddenly break this?
EDIT=I am wrong, it's an update to the spring-data-mongodb package that broke it. It was updated from 1.10.9-RELEASE To 2.0.2-RELEASE at the same time and I didn't notice right away.

Related

Spring Boot Application not registering #Repository

I'm creating a simple SpringBoot application with spring-data-jpa for learning purposes.
My problem is when I try to #Autowire a #Repository the application always fails to start with the error:
APPLICATION FAILED TO START
***************************
Description:
Field pedidoRepository in com.pedidos.services.PedidoService required a bean of type 'com.pedidos.repositories.PedidoRepository' that could not be found.
The injection point has the following annotations:
- #org.springframework.beans.factory.annotation.Autowired(required=true)
Action:
Consider defining a bean of type 'com.pedidos.repositories.PedidoRepository' in your configuration.
All the answers that i have found so far tells me to do something that is already done in my application. I'm probably missing something and I can't find out what it is.
This is how my application is now (imports are omitted):
Application:
package com.pedidos;
#SpringBootApplication
public class PedidosApplication {
public static void main(String[] args) {
SpringApplication.run(PedidosApplication.class, args);
}
}
Repository:
package com.pedidos.repositories;
#Repository
public abstract class PedidoRepository implements JpaRepository<Pedido, UUID> {
}
Service:
package com.pedidos.services;
#Service
public class PedidoService {
#Autowired
private PedidoRepository pedidoRepository;
public Optional<Pedido> findById(UUID id){
return pedidoRepository.findById(id);
}
public Pedido save(Pedido pedido){
return pedidoRepository.save(pedido);
}
}
Controller:
package com.pedidos.controllers;
#Controller("/pedido")
public class PedidoController {
#Autowired
private PedidoService pedidoService;
#GetMapping("/{id}")
public Pedido get(#PathVariable(name = "id") UUID id){
return pedidoService.findById(id).get();
}
}
Here is my Project structure
If do not inject the repository the application runs fine.
The entire code is in this GitHub repo: https://github.com/brunomokan/pedidos
Like what ILya Cyclone say. A Spring-Data Repository should be an interface which get a proxy at runtime. Something like this. Its fine if you extend from another interface.

Spring Boot can connect to Cassandra when running as Servlet but not as Command Line

Background: I'm trying to set up a code-based data migration system for our Cassandra database. I don't have a ton of experience with Java, but if this were a .NET project I'd set up the migrations as a different project under the same solution. However, based on guidance from other team members that are more experienced, it was recommended that I include the migrations in the same package as the rest of the application (which I'm fine with). It was also suggested that the easiest method would be to run the migrations via a web API endpoint (which I'm more skeptical of). In the interest of avoiding opening up a potential security vulnerability, I thought I'd take a shot at making a command-line utility to execute the migrations.
I have a Spring Boot web application with an entry point class that looks like this:
#Configuration
#SpringBootApplication
#EnableAutoConfiguration
#EnableCaching
#EnableScheduling
public class MyApplication extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(MyApplication.class);
}
public static void main(String[] args) {
new MyApplication().configure(new SpringApplicationBuilder(MyApplication.class)).run(args);
}
}
However, I'm trying to add the functionality to run a couple migration scripts that are packaged with this application via the command line (e.g. java -jar MyApplication.jar migrate), so I added the following class:
#Configuration
#SpringBootApplication
#EnableAutoConfiguration
public class MigrationRunner implements CommandLineRunner {
#Autowired
Session session;
#Override
public void run(String[] args)
{
MigrationResources mr = new MigrationResources();
mr.addMigration(...);
mr.addMigration(...);
MigrationEngine.withSession(session).migrate(mr);
}
}
And then updated my entry point class like this:
// annotations
public class MyApplication extends SpringBootServletInitializer {
private final static String MIGRATE_COMMAND = "migrate";
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(MyApplication.class);
}
public static void main(String[] args) {
if (args.length > 0 && args[0].equalsIgnoreCase(MIGRATE_COMMAND)) {
new SpringApplicationBuilder()
.sources(MigrationRunner.class)
.run(Arrays.copyOfRange(args, 1, args.length));
} else {
new MyApplication().configure(new SpringApplicationBuilder(MyApplication.class)).run(args);
}
}
}
The problem is that when I execute this with the migrate arg, Spring throws this error:
Error creating bean with name 'migrationRunner': Unsatisfied dependency expressed through field 'session'
Error creating bean with name 'session' defined in class path resource [org/springframework/boot/autoconfigure/data/cassandra/CassandraDataAutoConfiguration.class]: Invocation of init method failed
All host(s) tried for query failed (tried: server022/XX.YY.ZZ.022:9042 (com.datastax.driver.core.exceptions.TransportException: [server022/XX.YY.ZZ.022:9042] Connection has been closed), server022/XX.YY.ZZ.020:9042 (com.datastax.driver.core.exceptions.TransportException: [server020/XX.YY.ZZ.020:9042] Connection has been closed), server020/XX.YY.ZZ.021:9042 (com.datastax.driver.core.exceptions.TransportException: [server020/XX.YY.ZZ.021:9042] Connection has been closed))
Running it without the migrate arg still works fine. I suspect that Spring is simply not picking up the correct certificates for this Cassandra server, even though it appears to be getting all the other configuration properties (server name, keyspace, etc.)
Question: How can I make a Spring Boot servlet that also has a command-line mode and can connect to the configured Cassandra server in both modes?
All you need to do is,
#SpringBootApplication
public class MyApplication
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
You have over complicated the application. If you run the MyApplication.main that will run in port 8080 by default.
Bonus, If you need both to start from same class.
#SpringBootApplication
public class MigrationRunner implements CommandLineRunner {
#Autowired
Session session;
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
#Override
public void run(String[] args)
{
MigrationResources mr = new MigrationResources();
mr.addMigration(...);
mr.addMigration(...);
MigrationEngine.withSession(session).migrate(mr);
}
}

Spring boot addInterceptors not being called in Websphere application server

I have a Spring Boot app using SpringWS. Inside of the WsConfigurerAdapter I am overriding addInterceptors in order to add logging/authentication/validation/etc.
#Configuration
#EnableCaching
#EnableWs
public class WebServiceConfig extends WsConfigurerAdapter {
...
#Override
public void addInterceptors(List<EndpointInterceptor> interceptors) {
EnvironmentSettings environment = getEnvironmentSettings();
interceptors.add(getLogSetupInterceptor());
interceptors.add(getAuthenticationInterceptor());
interceptors.add(getServerLoggingInterceptor());
interceptors.add(getAuthorizationInterceptor());
ServerPayloadValidatingInterceptor validatingInterceptor = new ServerPayloadValidatingInterceptor();
validatingInterceptor.setValidateRequest(environment.isValidateSoapRequest());
validatingInterceptor.setValidateResponse(environment.isValidateSoapResponse());
validatingInterceptor.setXsdSchema( xsdSchema());
interceptors.add(validatingInterceptor);
}
}
What is strange is that when run locally, all of these interceptors are being added and run for every request just fine. However, when I deploy the application as a .war to WAS, this one method is not being run. I even added logging statements and I can tell that it's this method that's getting skipped over instead of the interceptors themselves. Does anybody know something about spring boot .war files that I don't?
Also, here is my Application class:
#SpringBootApplication
public class Application extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
I figured out what I did wrong. It turns out I was creating a servlet mapping in both my WebServiceConfig and my web.xml both at /*.

Cannot load bean in different package in Spring Boot application

I'm trying to load beans from a different package on a Spring boot application. Here's my main class, that lives in com.xyz.app package:
Application.java:
#SpringBootApplication(scanBasePackages = { "com.xyz.app.repository" })
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);
context.getBean(MyInterfaceRepository.class).loadData();
}
The interface MyInterfaceRepository.java is inside the com.xyz.app.repository package, and is defined as follows:
#RepositoryRestResource(collectionResourceRel = "aas", path = "aas")
public interface MyInterfaceRepository extends MongoRepository<MyClass, Long>,
MyCustomInterface {
...
}
Then, I also have a MyInterfaceRepositoryImpl.java, that lives in com.xyz.app.repository, that provides an implementation for MyCustomInterface.java, that also lives in com.xyz.app.repository.
Starting my application I get the following:
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.xyz.app.repository.MyInterfaceRepository] is defined
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:372)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:332)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1066)
at com.xyz.app.Application.main(Application.java:60)
I already checked, and indeed if I put MyInterfaceRepository.java and MyInterfaceRepositoryImpl.java in the same package as Application.java, com.xyz.app, than it works.
It seems that Spring is not able to load the beans from a different package than the one where Application.java is.
Also, I tried replacing the #SpringBootApplication with these:
#Configuration
#EnableAutoConfiguration
#ComponentScan({"com.xyz.app.repository"})
Same issue.. Any idea?
if you are using spring mongodb, you don't need to use annotation: #RepositoryRestResource(collectionResourceRel = "aas", path = "aas")
You also can use #Autowired in the MyInterfaceRepository.
On your application class/main class add #EnableMongoRepositories. You should have something like this:
#SpringBootApplication(scanBasePackages = {"com.xyz.app"})
#EnableMongoRepositories(basePackages = {"com.xyz.app.repository"}, repositoryBaseClass = MyInterfaceRepositoryImpl.class)
public class Application extends SpringBootServletInitializer {
...
}
See EnableMongoRepositories for more details about the annotation.

Spring-boot Auto-config: DataSource not getting autowired in daoimpl class, but works properly when autowired in contoller

I am working on a REST WebService, i need to interact with a database by using a Jboss Data Source.
The problem is that when i am trying to autowire the datasource inside the DAO's impl class, it is having null.
But if I autowire the datasource on Controller, it works fine
DaoClass:
#Repository
public class OrderListDaoImpl implements OrderListDao{
#Autowired
private DataSource dataSource; // this here gives null
public List<OrderDTO> getOrderList(SearchOrderDto searchOrderDto,int pageSize,
int pageNumber,String sortBy,String sortType,boolean pagination,DataSource dataSourced)
throws Exception{
}
}
My Application class:
#Configuration
#ComponentScan("net.colt.*")
#EnableAutoConfiguration
public class Application extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(applicationClass, args);
}
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(applicationClass);
}
private static Class<Application> applicationClass = Application.class;
}
my controller:
#RestController
public class OrderSearchController {
#Autowired
private DataSource dataSource; // This gets initialized properly
#RequestMapping("/getOrderList")
ResponseEntity<String> getOrderList(){
}
}
I am using spring boot auto config. my application property file is :
spring.datasource.jndi-name=java\:jboss/datasources/orders_ds
server.servlet-path=/*
I was not creating the bean properly and which was creating a new instance for each of my class,
thanks to #M.Deinum for pointing that out.
Once I corrected the bean creating, it worked properly

Categories