Adding spring-boot-starter-web to dependencies breaks multiple datasources - spring-mvc

I have a project with 3 different DataSources. It works fine if the project is run from with spring-boot:run only with these dependencies:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.2.6.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>RELEASE</version>
</dependency>
<!--<dependency>-->
<!--<groupId>org.springframework.boot</groupId>-->
<!--<artifactId>spring-boot-starter-web</artifactId>-->
<!--</dependency>-->
Here is one datasource, they are all pretty much the same, just changing bean names and database information
#Configuration
#EnableTransactionManagement
#EnableJpaRepositories(entityManagerFactoryRef = "emfIntranet", transactionManagerRef = "tmIntranet", basePackages = {"com.vnt.intranet.repositories"})
#ConfigurationProperties(prefix = "databases.sistemas")
public class IntranetPersistence {
private String address;
private String schema;
private String username;
private String password;
private String eclipselinklog;
private Boolean sqllog;
#Primary
#Bean(name = "dsIntranet")
public DataSource dataSource() {
org.apache.tomcat.jdbc.pool.DataSource dataSource = new org.apache.tomcat.jdbc.pool.DataSource();
dataSource.setUrl("jdbc:postgresql://" + address + "/" + schema);
dataSource.setUsername(username);
dataSource.setPassword(password);
dataSource.setDriverClassName("org.postgresql.Driver");
dataSource.setInitialSize(3);
dataSource.setMaxIdle(10);
dataSource.setMaxActive(10);
return dataSource;
}
private EclipseLinkJpaVendorAdapter getEclipseLinkJpaVendorAdapter() {
EclipseLinkJpaVendorAdapter vendorAdapter = new EclipseLinkJpaVendorAdapter();
vendorAdapter.setDatabasePlatform("org.eclipse.persistence.platform.database.PostgreSQLPlatform");
vendorAdapter.setShowSql(sqllog);
return vendorAdapter;
}
#Primary
#Bean(name = "emfIntranet")
public EntityManagerFactory entityManagerFactory() {
LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
factoryBean.setJpaVendorAdapter(getEclipseLinkJpaVendorAdapter());
factoryBean.setDataSource(dataSource());
factoryBean.setPackagesToScan("com.vnt.intranet.entities");
factoryBean.setPersistenceUnitName("intranet");
Properties jpaProperties = new Properties();
jpaProperties.put("eclipselink.weaving", "false");
jpaProperties.put("eclipselink.logging.level", eclipselinklog); // SEVERE / FINEST
factoryBean.setJpaProperties(jpaProperties);
factoryBean.afterPropertiesSet();
return factoryBean.getObject();
}
#Primary
#Bean(name = "tmIntranet")
public PlatformTransactionManager transactionManager() {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory());
return transactionManager;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getSchema() {
return schema;
}
public void setSchema(String schema) {
this.schema = schema;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getEclipselinklog() {
return eclipselinklog;
}
public void setEclipselinklog(String eclipselinklog) {
this.eclipselinklog = eclipselinklog;
}
public Boolean getSqllog() {
return sqllog;
}
public void setSqllog(Boolean sqllog) {
this.sqllog = sqllog;
}
}
I can access all datasources with no problem... One of them is annotated with #Primary.
But if I uncomment spring-boot-starter-web dependency it breaks it and gives me:
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [javax.persistence.EntityManagerFactory] is defined: more than one 'primary' bean found among candidates: [emfIntranet, entityManagerFactory, emfMkRadius, emfMkData]
I'm trying to convert this to a web project with no success...
Any ideas?
EDIT
Adding other classes for clarity:
MkDataPersistence.class
#Configuration
#EnableTransactionManagement
#EnableJpaRepositories(entityManagerFactoryRef = "emfMkData", transactionManagerRef = "tmMkData", basePackages = {"org.example.mkdata.repositories"})
#ConfigurationProperties(prefix = "databases.mkdata")
public class MkDataPersistence {
private String address;
private String schema;
private String username;
private String password;
private String eclipselinklog;
private Boolean sqllog;
#Bean(name = "dsMkData")
javax.sql.DataSource dataSource() {
DataSource dataSource = new DataSource();
dataSource.setUrl("jdbc:postgresql://" + address + "/" + schema);
dataSource.setUsername(username);
dataSource.setPassword(password);
dataSource.setDriverClassName("org.postgresql.Driver");
dataSource.setInitialSize(3);
dataSource.setMaxIdle(10);
dataSource.setMaxActive(10);
return dataSource;
}
#Bean
HibernateJpaVendorAdapter getHibernateJpaVendorAdapter() {
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
vendorAdapter.setDatabasePlatform("org.hibernate.dialect.PostgreSQL9Dialect");
vendorAdapter.setShowSql(sqllog);
return vendorAdapter;
}
#Bean(name = "emfMkData")
EntityManagerFactory entityManagerFactory() {
LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
factoryBean.setJpaVendorAdapter(getHibernateJpaVendorAdapter());
factoryBean.setDataSource(dataSource());
factoryBean.setPackagesToScan("org.example.mkdata.entities");
factoryBean.setPersistenceUnitName("mkdata");
Properties jpaProperties = new Properties();
jpaProperties.put("eclipselink.weaving", "false");
jpaProperties.put("eclipselink.logging.level", eclipselinklog); // SEVERE / FINEST
factoryBean.setJpaProperties(jpaProperties);
factoryBean.afterPropertiesSet();
return factoryBean.getObject();
}
#Bean(name = "tmMkData")
PlatformTransactionManager transactionManager() {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory());
return transactionManager;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getSchema() {
return schema;
}
public void setSchema(String schema) {
this.schema = schema;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getEclipselinklog() {
return eclipselinklog;
}
public void setEclipselinklog(String eclipselinklog) {
this.eclipselinklog = eclipselinklog;
}
public Boolean getSqllog() {
return sqllog;
}
public void setSqllog(Boolean sqllog) {
this.sqllog = sqllog;
}
}
MkRadiusPersistence.class
#Configuration
#EnableTransactionManagement()
#EnableJpaRepositories(entityManagerFactoryRef = "emfMkRadius", transactionManagerRef = "tmMkRadius", basePackages = {"org.example.mkradius.repositories"})
#ConfigurationProperties(prefix = "databases.mkradius")
public class MkRadiusPersistence {
private String address;
private String schema;
private String username;
private String password;
private String eclipselinklog;
private Boolean sqllog;
#Bean(name = "dsMkRadius")
javax.sql.DataSource dataSource() {
DataSource dataSource = new DataSource();
dataSource.setUrl("jdbc:postgresql://" + address + "/" + schema);
dataSource.setUsername(username);
dataSource.setPassword(password);
dataSource.setDriverClassName("org.postgresql.Driver");
dataSource.setInitialSize(3);
dataSource.setMaxIdle(10);
dataSource.setMaxActive(10);
return dataSource;
}
#Bean
HibernateJpaVendorAdapter getHibernateJpaVendorAdapter() {
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
vendorAdapter.setDatabasePlatform("org.hibernate.dialect.PostgreSQL9Dialect");
vendorAdapter.setShowSql(sqllog);
return vendorAdapter;
}
#Bean(name = "emfMkRadius")
EntityManagerFactory entityManagerFactory() {
LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
factoryBean.setJpaVendorAdapter(getHibernateJpaVendorAdapter());
factoryBean.setDataSource(dataSource());
factoryBean.setPackagesToScan("org.example.mkradius.entities");
factoryBean.setPersistenceUnitName("mkradius");
Properties jpaProperties = new Properties();
jpaProperties.put("eclipselink.weaving", "false");
jpaProperties.put("eclipselink.logging.level", eclipselinklog); // SEVERE / FINEST
factoryBean.setJpaProperties(jpaProperties);
factoryBean.afterPropertiesSet();
return factoryBean.getObject();
}
#Bean(name = "tmMkRadius")
PlatformTransactionManager transactionManager() {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory());
return transactionManager;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getSchema() {
return schema;
}
public void setSchema(String schema) {
this.schema = schema;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getEclipselinklog() {
return eclipselinklog;
}
public void setEclipselinklog(String eclipselinklog) {
this.eclipselinklog = eclipselinklog;
}
public Boolean getSqllog() {
return sqllog;
}
public void setSqllog(Boolean sqllog) {
this.sqllog = sqllog;
}
}
EDIT 2
Application.class
#Configuration
#ComponentScan(basePackages = { "org.example.startup" })
#EnableAutoConfiguration
public class Application {
private static final Logger logger = LoggerFactory.getLogger(Application.class);
#Autowired
CableRouteRepository cableRouteRepository;
#Autowired
CityRepository cityRepository;
#Autowired
RadAcctRepository radAcctRepository;
public static void main(String[] args) {
ConfigurableApplicationContext context = new SpringApplicationBuilder()
.showBanner(false)
.sources(Application.class)
.run(args);
Application app = context.getBean(Application.class);
// for (String bean: context.getBeanDefinitionNames()) {
// logger.info(bean);
// }
app.start();
}
private void start() {
logger.info("Application.start()");
logger.info("{}", cableRouteRepository.findAll());
logger.info("{}", cityRepository.findAll());
logger.info("{}", radAcctRepository.findTest());
}
}
This is the starter class... I printed every repository as a test (each repository here is on a different DataSource)... They work fine as long as I don't have spring-starter-web on the classpath.
EDIT 3
Github Repo
https://github.com/mtrojahn/test-multiple-databases
I hope I did it right... I never really worked with Github :)
EDIT 4
Github updated properly with the failing code.
As a reminder if the dependency bellow is commented, the code works:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
And if the dependency above is uncommented but the code bellow is changed in the IntranetPersistence.class from:
#Primary
#Bean(name = "emfIntranet")
to
#Primary
#Bean(name = "entityManagerFactory")
It overwrites the default bean and starts to fail with:
Caused by: java.lang.IllegalArgumentException: Not an managed type: class org.example.intranet.entities.CableRoute

You're being affected by the behaviour of Spring Boot 1.2's JPA auto-configuration. It only switches off the creation of its own entityManagerFactory bean if there's a user-defined LocalContainerEntityManagerFactoryBean. You're using LocalContainerEntityManagerFactoryBean but calling afterPropertiesSet and getObject on it yourself rather than allowing the container to do so for you. This leaves the context will multiple #Primary EntityManagerFactory beans. This has been improved in Spring Boot 1.3 so that a user-declared EntityManagerFactory bean will also switch off the auto-configuration.
This causes a problem when trying to create openEntityManagerInViewInterceptor as it needs an EntityManagerFactory and the context has no way of knowing whic of the two #Primary beans it should choose.
There are a few ways to proceed. You could update your configuration to define beans that are of type LocalContainerEntityManagerFactoryBeans rather than EntityManagerFactory. Another is to disable the creation of the interceptor by adding the following to your application.yml:
spring:
jpa:
open_in_view: false

Related

CloseableHttpAsyncClient stopped after first call

I have a problem using CloseableHttpAsyncClientBase, i dont understand why my connection was stopped after the first call: the call completed ok without any Excption! When i debug the library code i found that the status changed into stopped in this constructor class:
public CloseableHttpAsyncClientBase(
final NHttpClientConnectionManager connmgr,
final ThreadFactory threadFactory,
final NHttpClientEventHandler handler) {
super();
this.connmgr = connmgr;
if (threadFactory != null && handler != null) {
this.reactorThread = threadFactory.newThread(new Runnable() {
#Override
public void run() {
try {
final IOEventDispatch ioEventDispatch = new InternalIODispatch(handler);
connmgr.execute(ioEventDispatch);
} catch (final Exception ex) {
log.error("I/O reactor terminated abnormally", ex);
} finally {
status.set(Status.STOPPED);//<--- THE BREAKPOINT IS HERE(ISSUE)
}
}
});
} else {
this.reactorThread = null;
}
this.status = new AtomicReference<Status>(Status.INACTIVE);
}
Why and What's wrong?
My maven dependencies are:
<dependencies>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.5</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpasyncclient</artifactId>
<version>4.1.5</version>
</dependency>
</dependencies>
My code like (this class is singleton):
public static final int MAX_SOCKET_TIMEOUT = 40000;
private static final int MAX_CONNECTION_TIMEOUT = 40000;
public static final int MAX_CONN_TOTAL = 20; //numero conn totali nel pool
public static final int MAX_CONN_PER_ROUTE = 4; //max connessioni parallele da usare per indirizzo host + url
private final RequestConfig config;
private final CloseableHttpAsyncClient httpAsyncClient;
private static final ClientAsync instance = new ClientAsync();
private static final Logger logger = LoggerFactory.getLogger(ClientAsync.class);
//SINGLETON
public static ClientAsync getInstance(){
return instance;
}
private ClientAsync() {
//init client
this.config = RequestConfig.custom()
.setSocketTimeout(MAX_SOCKET_TIMEOUT)
.setConnectTimeout(MAX_CONNECTION_TIMEOUT)
.build();
httpAsyncClient = HttpAsyncClients.custom().
setDefaultRequestConfig(config)
.setMaxConnTotal(MAX_CONN_TOTAL)
.setMaxConnPerRoute(MAX_CONN_PER_ROUTE)
.build();
httpAsyncClient.start();//start client
LoggerFactory.getLogger(ClientAsync.class).info("HttpAsyncClients configured and started, configuration: MAX_SOCKET_TIMEOUT:{},MAX_CONNECTION_TIMEOUT:{},MAX_CONN_TOTAL:{},MAX_CONN_PER_ROUTE:{}"
,MAX_SOCKET_TIMEOUT,MAX_CONNECTION_TIMEOUT,MAX_CONN_TOTAL,MAX_CONN_PER_ROUTE);
}
public void callPost(String url, List<CookieVal> cookies, ClientParams params,Supplier<FutureCallback<HttpResponse>> callback){
HttpPost post = new HttpPost(url);
HttpContext httpContext = setCookieAndGetContext(cookies);
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(params.values(), Consts.UTF_8);
post.setEntity(entity);
checkIfNotRunningAndIfSoStart();//causa eventuale eccezioni
httpAsyncClient.execute(post, httpContext, callback.get());
}
private void checkIfNotRunningAndIfSoStart() {
if (!httpAsyncClient.isRunning()){
httpAsyncClient.start();
}
}
private HttpContext setCookieAndGetContext(List<CookieVal> cookies) {
BasicCookieStore cookieStore = new BasicCookieStore();
for (CookieVal theCookie : cookies) {
BasicClientCookie cookie = new BasicClientCookie(theCookie.name, theCookie.value);
cookie.setDomain(theCookie.domain);
cookie.setPath(theCookie.path);
cookieStore.addCookie(cookie);
}
HttpContext localContext = new BasicHttpContext();
localContext.setAttribute(HttpClientContext.COOKIE_STORE, cookieStore);
return localContext;
}
public void closeConnection() throws IOException {
httpAsyncClient.close();
}
static class ClientParams{
private List<NameValuePair> params;
public ClientParams() {
params = new ArrayList<>();
}
public void add(String name, String value) {
BasicNameValuePair nameValuePair = new BasicNameValuePair(name, value);
params.add(nameValuePair);
}
public List<NameValuePair> values() {
return Collections.unmodifiableList(params);
}
public String getParamsMessage() {
StringBuilder msg = new StringBuilder("( ");
for (NameValuePair param : params) {
msg.append(param.getName()).append(": ").append(param.getValue()).append(" ");
}
msg.append(")");
return msg.toString();
}
}
static final class CookieVal {
private final String name;
private final String value;
private final String domain;
private final String path;
public CookieVal(String name, String value, String domain, String path) {
this.name = name;
this.value = value;
this.domain = domain;
this.path = path;
}
}
Could you help me?

Spring Test MVC can not get right result with Spring Validator when I can get right result from postman [duplicate]

I am trying to set up an integration testing with mockMvc, and i have a problem with it. Indeed, spring doesn't integrate any validation annotation.
For more precision, i put the code of the Controller class which could be tested :
#Controller
public class UserRegisterController {
private final Log log = LogFactory.getLog(UserRegisterController.class);
private UserManager userManager;
#Autowired
public UserRegisterController(UserManager userManager){
this.userManager = userManager;
}
/**
* Register a new user.
*
*/
#RequestMapping(value = "/User/Register",
method = RequestMethod.GET
)
public #ResponseBody SimpleMessage submitForm(
#Valid UserInfoNew userInfo,
BindingResult result
){
if(log.isInfoEnabled())
log.info("Execute UserRegister action");
SimpleMessage message;
try {
if(result.hasErrors()){
if(log.isFatalEnabled())
log.fatal("Parameters sent by user for registering aren't conform. Errors are : "
+ result.getFieldErrors().toString());
throw new Exception(result.getFieldErrors().toString());
}
User user = new User();
user.setLogin(userInfo.getLogin());
user.setFamilyName(userInfo.getFamilyName());
user.setFirstName(userInfo.getFirstName());
user.setPassword(userInfo.getPassword());
user.setDateBirthday(userInfo.getDateBirthday());
user.setEmail(userInfo.getEmail());
user.setMobile(userInfo.getMobile());
user.setAddress(userInfo.getAddress());
userManager.createUser(user);
User newUser = userManager.findLastUserCreated();
//Change to null some sensitive or useless return parameters
newUser.setPassword(null);
//
message = new SimpleMessage(null, newUser);
} catch (Exception e) {
if(log.isErrorEnabled())
log.error("A problem of type : " + e.getClass()
+ " has occured, with message : " + e.getMessage());
message = new SimpleMessage(
new SimpleException(e.getClass(), e.getMessage()), null);
}
return message;
}
}
Then, the object with contain both hibernate and javax annotation for validation :
public abstract class UserParameters {
#Min(1)
protected Long id;
#Length(min=4, max=20)
protected String login;
#Length(min=4, max=20)
protected String familyName;
#Length(min=4, max=20)
protected String firstName;
#Pattern(regexp="^.*(?=.{8,20})(?=.*[a-z]+)(?=.*[a-z]+)(?=.*[A-Z]+)(?=.*[A-Z]+)"
+ "(?=.*[0-9]+)(?=.*[0-9]+)(?=.*[#$%*#]+).*$")
protected String password;
#Past
protected Calendar dateBirthday;
#Email
#Length(max=255)
protected String email;
#Pattern(regexp="^[0]{1}[67]{1}[ .-]{1}[0-9]{2}[ .-]{1}"
+ "[0-9]{2}[ .-]{1}[0-9]{2}[ .-]{1}[0-9]{2}$")
protected String mobile;
#Length(max=255)
protected String address;
protected Calendar dateCreation;
protected Calendar dateLastAccess;
}
public class UserInfoNew extends UserParameters implements Serializable{
private static final long serialVersionUID = 4427131414801253777L;
#NotBlank
public String getLogin() {
return login;
}
public void setLogin(String Login) {
this.login = Login;
}
public String getFamilyName() {
return familyName;
}
public void setFamilyName(String Name) {
this.familyName = Name;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String FirstName) {
this.firstName = FirstName;
}
#NotBlank
public String getPassword() {
return password;
}
public void setPassword(String Password){
this.password = Password;
}
public Calendar getDateBirthday() {
return dateBirthday;
}
public void setDateBirthday(Calendar strBirthDay) {
this.dateBirthday = strBirthDay;
}
public String getEmail() {
return email;
}
public void setEmail(String Mail) {
this.email = Mail;
}
#NotBlank
public String getMobile() {
return mobile;
}
public void setMobile(String Mobile) {
this.mobile = Mobile;
}
public String getAddress() {
return address;
}
public void setAddress(String Address) {
this.address = Address;
}
}
and the class which realizes the test:
#RunWith(SpringJUnit4ClassRunner.class)
#WebAppConfiguration
#ContextConfiguration(classes = {
WebInit_Test.class,
AppConfig_Test.class,
WebConfig_1.class,
WebConfig_2.class,
WebSocketConfig.class
})
public class UserControllersTest {
#Autowired
private WebApplicationContext wac;
private MockMvc mockMvc;
#Before
public void setUp() throws Exception {
this.mockMvc = MockMvcBuilders.webAppContextSetup(wac)
.alwaysExpect(status().isOk())
.alwaysExpect(content().contentType("application/json;charset=UTF-8"))
.build();
}
#Test
public void userRegister() throws Exception {
//doesn't consider #Valid during test
mockMvc.perform(get("/User/Register?Login=A&Password=aaAA&Mobile=0134320285")
.contentType(MediaType.ALL)
)
.andExpect(jsonPath("error").exists());
}
}
When i launch the test, the error item doesn't exist, whereas login, password and mobile can't be validate by javax and hibernate annotation. Moreover, when i try to send an URL to localhost, validation worked and new user is not saved in database.
As you can see, i use a java code configuration for my web layer, i suppose the problem come from it. Moreover i download a project from the spring team in github (link : github.com/spring-projects/spring-mvc-showcase) which details all kind of test we can do with mockmvc. The validation one (in "org.springframework.samples.mvc.validation" package) doesn't work with my project configuration but very well with in it's original config.
To finish, i send you all my configuration classes
#Configuration
public class WebInit_Test extends AbstractAnnotationConfigDispatcherServletInitializer {
#Override
protected Class<?>[] getRootConfigClasses() {
return new Class<?>[] { AppConfig_Test.class };
}
#Override
protected Class<?>[] getServletConfigClasses() {
return new Class<?>[] { WebConfig_1.class, WebConfig_2.class, WebSocketConfig.class };
}
#Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
#Override
protected void customizeRegistration(Dynamic registration) {
registration.setInitParameter("dispatchOptionsRequest", "true");
registration.setLoadOnStartup(1);
}
}
#Configuration
#ImportResource({
"classpath:/applicationContext-dao.xml",
"classpath:/applicationContext-datasource-test.xml",
"classpath:/applicationContext-service.xml"
})
public class AppConfig_Test {
}
#Configuration
#EnableWebMvc
#ComponentScan(
basePackages = "project.web",
excludeFilters = #ComponentScan.Filter(type= FilterType.ANNOTATION, value = Configuration.class)
)
public class WebConfig_1 extends WebMvcConfigurationSupport {
#Autowired
private FormattingConversionServiceFactoryBean conversionService;
#Bean
#Override
public FormattingConversionService mvcConversionService() {
FormattingConversionService conversionService = this.conversionService.getObject();
addFormatters(conversionService);
return conversionService;
}
}
#Configuration
public class WebConfig_2 extends WebMvcConfigurerAdapter{
#Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
/**
* Configure output mapping, see
* {#link http://stackoverflow.com/questions/4823358/spring-configure-responsebody-json-format}
* for more information
*
* #param converters
* a list of {#link HttpMessageConverter<?>}
*/
#Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
final MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
final ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
converter.setObjectMapper(objectMapper);
converters.add(converter);
super.configureMessageConverters(converters);
}
}
#Configuration
//#EnableScheduling
#ComponentScan(
basePackages="project.web",
excludeFilters = #ComponentScan.Filter(type= FilterType.ANNOTATION, value = Configuration.class)
)
#EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
#Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/friendship", "/message", "/journey", "/information");
config.setApplicationDestinationPrefixes("/app");
}
#Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/client").withSockJS();
}
}
Thanks for your help.
I got same problem, after updating validator to 5.1.0.Final. Application is working perfectly but REST tests not (#Valid annotation is not considered at all). I resolved the problem with adding one additional dependency only for tests:
<dependency>
<groupId>javax.el</groupId>
<artifactId>javax.el-api</artifactId>
<version>2.2.4</version>
<scope>test</scope>
</dependency>
If you are using hibernate version 5.4.1.Final just add below dependency for your test
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.el</artifactId>
<version>3.0.0</version>
</dependency>
This dependency is "provided" dependency. You can find matching dependency for you version of hibernate at maven site. https://mvnrepository.com/artifact/org.hibernate/hibernate-validator/5.4.1.Final
For example if you are using 5.4.1 version go to above link and check for provided dependencies and use it.
Ok, I have just found what is responsible for the fact that validation was not consider by mockmvc. It's just a bad dependency in my pom:
I used
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.1.0.Final</version>
</dependency>
and when i replaced it by
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.0.0.GA</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>4.1.0.Final</version>
</dependency>
the test work just fine!
the problem is solved, but I am wondering why the problem comes from this part. hibernate-validator 5.1.0.Final include javax validation in transitive dependency, so normally, this problem would never have appeared.
I just added
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
and it worked

How to use Jackson to deserialise list in java?

My Java Class is
public class User {
private List<UserInfo> userInfoList;
public class UserInfo {
private String id;
}
}
Let's assume it has getter, setter method.
json is
{"userInfoList" : [{"id":"a", "id":"b"}]}
I tried to deserialize it like below.
objectMapper.readValue(json, User.class);
But it throws error.
Can not construct instance of User$UserInfoList: no suitable constructor found
How to deserialize it?
I think you should make UserInfo static. Jackson cannot construct the UserInfo class.
I tried with that change and it works for me :
public class User {
private List<UserInfo> userInfoList;
public static class UserInfo {
private String id;
public UserInfo() {
super();
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
public List<UserInfo> getUserInfoList() {
return userInfoList;
}
public void setUserInfoList(List<UserInfo> userInfoList) {
this.userInfoList = userInfoList;
}
}
And :
public class App {
public static void main(String[] args) throws IOException {
ObjectMapper mapper = new ObjectMapper();
User.UserInfo ui1 = new User.UserInfo();
ui1.setId("a");
User.UserInfo ui2 = new User.UserInfo();
ui2.setId("b");
List<User.UserInfo> userInfoList = new ArrayList<User.UserInfo>();
userInfoList.add(ui1);
userInfoList.add(ui2);
User user = new User();
user.setUserInfoList(userInfoList);
System.out.println(mapper.writeValueAsString(user));
user = mapper.readValue(mapper.writeValueAsString(user), User.class);
}
}

Autowired in Spring MVC getting error : Error creating bean with name 'userService': Injection of autowired dependencies

I am having this error for few days and seem to get no luck. Tried googling but still can't get it working. Looking on the log it keeps on telling me that there is something wrong with my "Injection of autowired dependencies" but I just can't get it. Hope to hear from you.
Error Logs.
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userService': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.sesame.repository.UserRepository com.sesame.service.UserService.userRepository; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.sesame.repository.UserRepository] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:334)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1210)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:303)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:299)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:755)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:757)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:480)
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:118)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:686)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:320)
at org.springframework.boot.context.web.SpringBootServletInitializer.run(SpringBootServletInitializer.java:117)
at org.springframework.boot.context.web.SpringBootServletInitializer.createRootApplicationContext(SpringBootServletInitializer.java:108)
at org.springframework.boot.context.web.SpringBootServletInitializer.onStartup(SpringBootServletInitializer.java:68)
at org.springframework.web.SpringServletContainerInitializer.onStartup(SpringServletContainerInitializer.java:175)
.......
Controller class
#Controller
#RequestMapping(value = "/protected/users")
public class UsersControl {
private static final String DEFAULT_PAGE_DISPLAYED_TO_USER = "0";
#Autowired
private UserService userService;
#Autowired
private MessageSource messageSource;
#Value("5")
private int maxResults;
#RequestMapping(method = RequestMethod.GET)
public ModelAndView welcome() {
return new ModelAndView("contactsList");
}
#RequestMapping(method = RequestMethod.GET, produces = "application/json")
public ResponseEntity<?> listAll(#RequestParam int page, Locale locale) {
return createListAllResponse(page, locale);
}
private UserListVO listAll(int page) {
return userService.findAll(page, maxResults);
}
private ResponseEntity<UserListVO> returnListToUser(UserListVO contactList) {
return new ResponseEntity<UserListVO>(contactList, HttpStatus.OK);
}
private ResponseEntity<?> createListAllResponse(int page, Locale locale) {
return createListAllResponse(page, locale, null);
}
private ResponseEntity<?> createListAllResponse(int page, Locale locale, String messageKey) {
UserListVO UserListVO = listAll(page);
addActionMessageToVO(UserListVO, locale, messageKey, null);
return returnListToUser(UserListVO);
}
private UserListVO addActionMessageToVO(UserListVO UserListVO, Locale locale, String actionMessageKey, Object[] args) {
if (StringUtils.isEmpty(actionMessageKey)) {
return UserListVO;
}
UserListVO.setActionMessage(messageSource.getMessage(actionMessageKey, args, null, locale));
return UserListVO;
}
}
service is existing:
#Service("userService")
#Transactional
public class UserService {
#Autowired
private UserRepository userRepository;
#Transactional(readOnly = true)
public UserListVO findAll(int page, int maxResults) {
Page<User> result = executeQueryFindAll(page, maxResults);
if(shouldExecuteSameQueryInLastPage(page, result)){
int lastPage = result.getTotalPages() - 1;
result = executeQueryFindAll(lastPage, maxResults);
}
return buildResult(result);
}
private Page<User> executeQueryFindAll(int page, int maxResults) {
final PageRequest pageRequest = new PageRequest(page, maxResults, sortByNameASC());
System.out.println("Now in ExectueQuery"+pageRequest);
return userRepository.findAll(pageRequest);
}
private Sort sortByNameASC() {
return new Sort(Sort.Direction.ASC, "name");
}
private UserListVO buildResult(Page<User> result) {
return new UserListVO(result.getTotalPages(), result.getTotalElements(), result.getContent());
}
private boolean shouldExecuteSameQueryInLastPage(int page, Page<User> result) {
return isUserAfterOrOnLastPage(page, result) && hasDataInDataBase(result);
}
private boolean isUserAfterOrOnLastPage(int page, Page<User> result) {
return page >= result.getTotalPages() - 1;
}
private boolean hasDataInDataBase(Page<User> result) {
return result.getTotalElements() > 0;
}
}
I've added the repository
#Repository("userRepository")
public interface UserRepository extends JpaRepository<User, Integer> {
Page<User> findByUserNameLike(Pageable pageable, String UserName);
}
WebConfiguration
#Configuration
#EnableWebMvc
#ComponentScan(basePackages="com.sesame")
#EnableAutoConfiguration
#PropertySource(value = { "classpath:application.properties" })
#EnableScheduling
#EnableAspectJAutoProxy
#EnableCaching
public class WebConfig extends WebMvcConfigurerAdapter {
#Autowired
private Environment env;
#Bean
public MessageSource messageSource() {
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
messageSource.setBasename("messages");
return messageSource;
}
#Bean
public LocaleResolver localeResolver() {
SessionLocaleResolver resolver = new SessionLocaleResolver();
resolver.setDefaultLocale(Locale.ENGLISH);
return resolver;
}
#Override
public void addInterceptors(InterceptorRegistry registry) {
LocaleChangeInterceptor changeInterceptor = new LocaleChangeInterceptor();
changeInterceptor.setParamName("language");
registry.addInterceptor(changeInterceptor);
}
#Bean
public InternalResourceViewResolver getInternalResourceViewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix("/");
return resolver;
}
#Bean public static PropertySourcesPlaceholderConfigurer placeHolderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
#Bean
public JavaMailSenderImpl javaMailSenderImpl() {
JavaMailSenderImpl mailSenderImpl = new JavaMailSenderImpl();
mailSenderImpl.setHost(env.getProperty("smtp.host"));
mailSenderImpl.setPort(env.getProperty("smtp.port", Integer.class));
mailSenderImpl.setProtocol(env.getProperty("smtp.protocol"));
mailSenderImpl.setUsername(env.getProperty("smtp.username"));
mailSenderImpl.setPassword(env.getProperty("smtp.password"));
Properties javaMailProps = new Properties();
javaMailProps.put("mail.smtp.auth", true);
javaMailProps.put("mail.smtp.starttls.enable", true);
mailSenderImpl.setJavaMailProperties(javaMailProps);
return mailSenderImpl;
}
#Bean public CacheManager cacheManager() {
return new ConcurrentMapCacheManager();
}
#Bean
public ServletRegistrationBean dispatcherRegistration() {
ServletRegistrationBean registration = new ServletRegistrationBean(
dispatcherServlet());
registration.addUrlMappings("/");
registration.addUrlMappings("*.pdf");
registration.addUrlMappings("*.json");
registration.addUrlMappings("*.js");
registration.addUrlMappings("*.xml");
registration.addUrlMappings("*.css");
return registration;
}
#Bean(name = DispatcherServletAutoConfiguration.DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)
public DispatcherServlet dispatcherServlet() {
return new DispatcherServlet();
}
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/pdfs/**").addResourceLocations(
"/WEB-INF/pdf/");
registry.addResourceHandler("/resources/js/**").addResourceLocations(
"/WEB-INF/resources/js/");
registry.addResourceHandler("/resources/css/**").addResourceLocations(
"/WEB-INF/resources/css/");
registry.addResourceHandler("/resources/img/**").addResourceLocations(
"/WEB-INF/resources/img/");
}
#Bean
public ViewResolver tilesViewResolver() {
return new TilesViewResolver();
}
#Bean
public TilesConfigurer tilesConfigurer() {
TilesConfigurer tiles = new TilesConfigurer();
tiles.setDefinitions(new String[] {"/WEB-INF/tiles.xml"});
tiles.setCheckRefresh(true);
return tiles;
}
}
Create a JPA Config Class as below :
#Configuration
#EnableJpaRepositories(basePackages="com.sesame.repository")
#EntityScan(basePackages="com.sesame.model")
public class JpaConfiguration {
}

JAAS how to tell Glassfish which LoginModule to use?

I want to use JAAS Authentification for my webapp.
For that i have the following classes:
UserPrincipal:
import java.security.Principal;
public class UserPrincipal implements Principal {
private String name = "";
public UserPrincipal(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
RolePrincipal:
import java.security.Principal;
public class RolePrincipal implements Principal {
private String name = "";
public RolePrincipal(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
LoginModule:
public class MyLoginModule implements LoginModule {
private CallbackHandler callbackHandler = null;
private Subject subject = null;
private UserPrincipal userPrincipal = null;
private RolePrincipal rolePrincipal = null;
private String login = null;
private List<String> userGroups = null;
public void initialize(Subject subject, CallbackHandler callbackHandler, Map<String, ?> sharedState, Map<String, ?> options) {
this.callbackHandler = callbackHandler;
this.subject = subject;
}
public boolean login() throws LoginException {
Callback[] callbacks = new Callback[2];
callbacks[0] = new NameCallback("login");
callbacks[1] = new PasswordCallback("password", true);
try {
callbackHandler.handle(callbacks);
String name = ((NameCallback)callbacks[0]).getName();
String password = String.valueOf(((PasswordCallback) callbacks[1]).getPassword());
if(name != null && name.equals("admin") && password != null && password.equals("admin")) {
this.login = name;
this.userGroups = new ArrayList<String>();
this.userGroups.add("admin");
return true;
}
throw new LoginException("Authentication failed");
} catch (IOException e) {
throw new LoginException(e.getMessage());
} catch (UnsupportedCallbackException e) {
throw new LoginException(e.getMessage());
}
}
public boolean commit() throws LoginException {
this.userPrincipal = new UserPrincipal(this.login);
this.subject.getPrincipals().add(this.userPrincipal);
if(this.userGroups != null && this.userGroups.size() > 0) {
for(String groupName: this.userGroups) {
this.rolePrincipal = new RolePrincipal(groupName);
this.subject.getPrincipals().add(this.rolePrincipal);
}
}
return true;
}
public boolean abort() throws LoginException {
return false;
}
public boolean logout() throws LoginException {
this.subject.getPrincipals().remove(this.userPrincipal);
this.subject.getPrincipals().remove(this.rolePrincipal);
return true;
}
}
How do i have to tell my Glassfish server that he has to use MyLoginModule
as the LoginModule?
My web.xml security configuration is that:
<security-constraint>
<web-resource-collection>
<web-resource-name>Admin</web-resource-name>
<url-pattern>/admin/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
</auth-constraint>
</security-constraint>
<security-role>
<role-name>admin</role-name>
</security-role>
<login-config>
<auth-method>FORM</auth-method>
<realm-name>Admin</realm-name>
<form-login-config>
<form-login-page>/login.jsp</form-login-page>
<form-error-page>/error.jsp</form-error-page>
</form-login-config>
</login-config>
The Documentation i found is not really clear in what actually to do.
Hope someone knows!
Edit your config/login.conf and add your LoginModule for the realm you use. In your web.xml, you use the "Admin" realm (realm-name). So I guess your login.conf file should look like :
Admin {
com.mycompany.MyLoginModule required;
}

Resources