I am new to spring and want to use the following project structure in spring boot application.
Different package for each type of entity and its corresponding repository implementation.
A Package for repository configuration
*
**com.demo.Customer**
Customer.java
CustomerRepository.java
Application.java
**com.demo.Order**
Order.java
OrderRepository.java
**com.demo.config**
ApplicationConfig.java
CustomerConfig.java
OrderConfig.java
CustomerConfig.java
import com.demo.cstore.core.Customer;
#Configuration
#EnableJpaRepositories(basePackageClasses = Customer.class)
public class CustomerConfiguration {
}
Application.java
#SpringBootApplication
#ComponentScan(basePackages = {"com.demo.order"}) //inject repository from other packages
public class Application {
private static final Logger log = LoggerFactory.getLogger(Application.class);
public static void main(String[] args) {
SpringApplication.run(Application.class);
}
After compiling and running the application, only customer entity is created. Is that because application file just recognizes customer entity as it exists in the same package com.demo.Customer. How can Order entity be injected and and an entity is created?
The EnableJpaRepositories annotation accepts an array of Strings basePackages here you can add all packages where your entities are:
#EnableJpaRepositories(basePackages={"com.demo.order"
,"com.demo.customer"
,"com.demo.config"})
That must be enough. Hope this helps.
you don't need to use #ComponentScan.
According to documentation
The #SpringBootApplication annotation is equivalent to using
#Configuration, #EnableAutoConfiguration and #ComponentScan with their
default attributes
so you can just use #SpringBootApplication on your main class which is located in the base package of your packages hierarchy and you will be fine.
you can too refer to this link to know about how to structure your code and main class location
http://docs.spring.io/spring-boot/docs/current/reference/html/using-boot-structuring-your-code.html
and this the API documentation for #SpringBootApplication
https://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/autoconfigure/SpringBootApplication.html
In our application we customize LocalContainerEntityManagerFactoryBean, so had to set the packages to scan there eg.:
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
factory.setDataSource(dataSource);
factory.setPackagesToScan("com.example.multitenancy.test.entity");
Related
On Finchley.SR2, here is the code
#Configuration
#EnableAutoConfiguration
#SpringBootApplication
#EnableBinding(Processor.class)
#RestController
public class Application {
private static Logger log = LoggerFactory.getLogger(Application.class);
#Autowired
private Processor processor;
#Autowired
MappingJackson2MessageConverter testConverter;
#Bean
#StreamMessageConverter
MappingJackson2MessageConverter createTestConverter(){
return new MappingJackson2MessageConverter();
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
When I start up, I got
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.cloud.stream.messaging.Processor' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
But if I take out #StreamMessageConverter, the Processor can be autowired successfully.
What should I do to keep my customized message converter and autowired Processor at the same time? Thanks!
There is a lot going on there, so lets try to parse it put. . .
First question, why do you need to autowire the following?
#Autowired
private Processor processor;
You, generally don't need to interact with Processor directly since it is used bt the framework to provide a delegation/connectivity model between remote destinations exposed by the binders and your message handlers
Further more, your actual issue is related to a lifecycle which may be a minor yet harmless bug on our end and probably relates to configuring and autowiring Processor in the same configuration class.
Second:
#Configuration
#EnableAutoConfiguration
#SpringBootApplication
You only need one
#SpringBootApplication
Third:
Why do you need to configure MappingJackson2MessageConverter? Content type conversion is a transparent feature of he framework and while we do provide an ability to configure custom message converters, the one you are configuring is already configured by the framework and in fact is the first in the stack of seven pre-configured message converters
The final question:
What is it that your are trying to do? Can you explain your use case?
I have setup a SpringBootAdmin server, and trying to register an application with SpringBootAdmin client. It does not seem to be registering.
Do I neccesarily have to register with Eureka?
How do I debug?
Configuration on adminserver
build.gradle
dependencies {
compile('de.codecentric:spring-boot-admin-server-ui')
compile('de.codecentric:spring-boot-admin-server-ui-login')
compile('de.codecentric:spring-boot-admin-server')
compile('org.springframework.boot:spring-boot-starter-web-services')
testCompile('org.springframework.boot:spring-boot-starter-test')
}
application.properties
spring.application.name=Boot-Admin
server.port=8093
security.user.name=admin
security.user.password=admin
logging.level.de.codecentric.boot.admin.client=DEBUG
logging.level.de.codecentric.boot.admin=DEBUG
App is
#SpringBootApplication
#Configuration
#EnableAdminServer
public class AdminApp {
public static void main(String[] args) {
SpringApplication.run(AdminApp.class, args);
}
}
On the client side,
build.gradle
dependencies {
compile('de.codecentric:spring-boot-admin-starter-client')
compile('org.springframework.boot:spring-boot-starter-actuator')
compile('org.springframework.boot:spring-boot-starter-web-services')
testCompile('org.springframework.boot:spring-boot-starter-test')
}
application.properties
server.port=8091
spring.boot.admin.client.enabled=true
spring.boot.admin.url=http://localhost:8093
spring.boot.admin.client.auto-registration=true
spring.boot.admin.username=admin
spring.boot.admin.password=admin
logging.level.de.codecentric.boot.admin.client=DEBUG
Code is
#Configuration
#SpringBootApplication
public class SBACApp {
public static void main(String[] args) {
SpringApplication.run(SBACApp.class, args);
}
}
According to all the Stackoverflow articles and tutorials, this should be adequate.
Even though logging is set on the client side, there seems to be no log-line starting with d.c....
What could I be missing
Any additional knowledge on how to debug this may help.
If you are using spring boot admin 2.0 the the client url property would be
spring.boot.admin.client.url: http://localhost:8093
I would check to see what version you are using and then double check the property names.
In Spring Boot 2.x.x version client url property is different that Spring Boot 1.x.x
spring.boot.admin.client.enabled=true
spring.boot.admin.client.url= http://localhost:8093
spring.boot.admin.client.auto-registration=true
make sure you have other two properties. in my case i was missing auto registration property
I'm trying to apply an aspect on a Spring Data JPA Repository and it works fine with default Spring AOP config
#EnableAspectJAutoProxy
(when Spring uses standard Java interface-based proxies).
However, when I switch to CGLIB proxies:
#EnableAspectJAutoProxy(proxyTargetClass = true)
I get this exception:
Caused by: org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class [class com.sun.proxy.$Proxy59]:
Looks like Spring tries to wrap a CGLIB proxy on a repository class, which is already a CGLIB proxy (generated by Spring Data) and fails.
Any ideas how to make it work?
My Spring Data Repository:
import org.springframework.data.jpa.repository.JpaRepository;
public interface DummyEntityRepository extends JpaRepository<DummyEntity, Integer> {
}
and the aspect:
#Aspect
public class DummyCrudRepositoryAspect {
#After("this(org.springframework.data.repository.CrudRepository)")
public void onCrud(JoinPoint pjp) {
System.out.println("I'm there!");
}
}
For a variety of reasons, I ended up using spring boot 1.2.0 RC2.
So a spring data mongo application that worked fine in spring boot1.1.8 is now having issues. No code was changed except for the bump to spring boot 1.2.0 RC2. This is due to the snapshot version of spring cloud moving to this spring boot version.
The repository class is as follows
#Repository
public interface OAuth2AccessTokenRepository extends MongoRepository<OAuth2AuthenticationAccessToken, String> {
public OAuth2AuthenticationAccessToken findByTokenId(String tokenId);
public OAuth2AuthenticationAccessToken findByRefreshToken(String refreshToken);
public OAuth2AuthenticationAccessToken findByAuthenticationId(String authenticationId);
public List<OAuth2AuthenticationAccessToken> findByClientIdAndUserName(String clientId, String userName);
public List<OAuth2AuthenticationAccessToken> findByClientId(String clientId);
}
This worked quite well before the bump in versions and now I see this in the log.
19:04:35.510 [main] DEBUG o.s.c.a.ClassPathBeanDefinitionScanner - Ignored because not a concrete top-level class: file [/Users/larrymitchell/rpilprojects/corerpilservicescomponents/channelMap/target/classes/com/cisco/services/rpil/mongo/repository/oauth2/OAuth2AccessTokenRepository.class]
I do have another mongo repository that is recognized but it was defined as a class implementation
#Component
public class ChannelMapRepository { ... }
This one is recognized (I defined it as a implementation class as a workaround for another problem I had). This class is recognized and seems to work fine.
19:04:35.513 [main] DEBUG o.s.c.a.ClassPathBeanDefinitionScanner - Identified candidate component class: file [/Users/larrymitchell/rpilprojects/corerpilservicescomponents/channelMap/target/classes/com/cisco/services/rpil/services/Microservice.class]
Anyone have an idea why? I looked up the various reasons for why component scanning would not work and nothing lends itself to my issue.
Try removing the #Repository annotation? Worked for me. This was an issue in Github as well.
Environment
Application server: JBoss AS7 (7.1.1 Final)
JPA implementation: EclipseLink (2.4.1)
OS: Windows 7 DB: PostgreSQL 8.4
Update 2, solved
The problem was that i instantiated the AccountService class instead of injecting it using #EJB. After fixing that EntityManager was inected correctly in the service and a transaction was available when doing em.persist(account);
Update
I made a minimal project that shows my problems. Posted to Github:
https://github.com/gotling/jboss-eclipselink-problem
I have two problems that are probably related and due to me not understanding the use of EJB's correct.
I can not get EnityManager to be injected in AccountService.java in persistance JAR, resulting in NullPointerException.
If sending EntityManager in constructor to AccountService no tranasaction is found when doing em.persist.
Project structure
EJB
lib/persistanceunit.jar
web-service.war
Problem
I'm trying to get JBoss to manage transactions in my Java EE service. Problem is that EclipseLink does not seem to pick up the transaction managed by JBoss when trying to persist an entity.
I have followed the guide https://community.jboss.org/wiki/HowToUseEclipseLinkWithAS7 (Alternative 1 and Alternative 2 Step 4) on how to configure JBoss with EclipseLink.
Setup
WAR
Entity manager is injected like this in web-service.war:
#WebService(....)
public class NotificationConsumerImpl implements NotificationConsumer {
#PersistenceContext(unitName="foo")
EntityManager em;
public void notify(Notify notify) {
AccountService accountService = new AccountService(em);
accountService.create(notify);
}
}
There is actually a controller class between the class above and the service class, where transformation of the Account object is done, removed it to shorten code.
Persistance Unit
Entity is created like this
AccountService.java in persistanceunit.jar
#Stateless
public class AccountService {
private EntityManager em;
public AccountService(EntityManager em) {
this.em = em;
}
public void create(Account account) {
em.persist(account);
}
}
Stack trace
When calling a WS that should persist the Account entity I get an exception on em.persist(account);
...
Caused by: javax.persistence.TransactionRequiredException: JBAS011469: Transaction is required to perform this operation (either use a transaction or extended persistence context)
at org.jboss.as.jpa.container.AbstractEntityManager.transactionIsRequired(AbstractEntityManager.java:692) [jboss-as-jpa-7.1.1.Final.jar:7.1.1.Final]
at org.jboss.as.jpa.container.AbstractEntityManager.persist(AbstractEntityManager.java:562) [jboss-as-jpa-7.1.1.Final.jar:7.1.1.Final]
at se.magos.service.AccountService.create(AccountService.java:50) [persistenceunit-0.0.1-SNAPSHOT.jar:]
Questions
I've enabled Trace logging. Should not id.au.ringerc.as7.eclipselinkpersistence be visible in the log?
Is it somehow possible to get the EntityManager injected inside the service class inside the persistanceunit.jar?
In which JBoss / EclipseLink version should this wor out of the box?
You should annotate the bean with #TransactionManagement(TransactionManagementType.CONTAINER) and the create method with #TransactionAttribute(TransactionAttributeType.REQUIRED).
The first annotation is required in order to let the application server know that transactions are managed by the container, the latter to let the method start a transaction, if there is no current one, as soon as it is invoked.
The problem was that AccountService class was instantiated instead of injected using #EJB annotation. After fixing that EntityManager was injected correctly in the service and a transaction was available when doing em.persist(account);
Before
#WebService(....)
public class NotificationConsumerImpl implements NotificationConsumer {
#PersistenceContext(unitName="foo")
EntityManager em;
public void notify(Notify notify) {
AccountService accountService = new AccountService(em);
accountService.create(notify);
}
}
After
#WebService(....)
public class NotificationConsumerImpl implements NotificationConsumer {
#PersistenceContext(unitName="foo")
EntityManager em;
#EJB
AccountService accountService;
public void notify(Notify notify) {
accountService.create(notify);
}
}