I am unable to create a table and insert the values into it using the Hibernate annotations. i am executing using command prompt. Following is my code.
Contact.java
import javax.persistence.*;
#Entity
#Table(name="Contact")
public class Contact {
private String firstName;
private String lastName;
private String email;
private long id;
#Column(name="Email")
public String getEmail() {
return email;
}
#Column(name="First_Name")
public String getFirstName() {
return firstName;
}
#Column(name="Last_Name")
public String getLastName() {
return lastName;
}
public void setEmail(String s) {
email = s;
}
public void setFirstName(String s) {
firstName = s;
}
public void setLastName(String s) {
lastName = s;
}
#Id
#GeneratedValue
#Column(name="id")
public long getId() {
return id;
}
public void setId(long l) {
id = l;
}
}
FirstExample.java
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;
public class FirstExample {
public static void main(String[] args) {
Session session = null;
try{
SessionFactory sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();
session =sessionFactory.openSession();
System.out.println("Inserting Record");
Contact contact = new Contact();
contact.setId(3);
contact.setFirstName("Tausif");
contact.setLastName("rahmathullah");
contact.setEmail("t.r#vl.net");
session.save(contact);
session.update(contact);
System.out.println("updated");
}catch(Exception e){
System.out.println(e.getMessage());
}finally{
if(session!=null){
session.flush();
session.close();
}
}
}
}
hibernate.cfg.xml
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost/my_db</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">root</property>
<property name="hibernate.connection.pool_size">10</property>
<property name="show_sql">true</property>
<property name="dialect">org.hibernate.dialect.MySQL5Dialect</property>
<property name="hibernate.hbm2ddl.auto">update</property>
<mapping resource="Contact"/>
</session-factory>
</hibernate-configuration>
JarFiles
antlr-2.7.6.jar
commons-collections-3.1.jar
dom4j-1.6.1.jar
hibernate3.jar
hibernate3.3.1-slf4j-api-1.5.2.jar
hibernate-jpa-2.0-api-1.0.1.Final.jar
javassist-3.4.ga.jar
jcl-over-slf4j-1.5.2.jar
jta-1.1.jar
log4j.jar
mysql-connector-java-5.0.0-bin.jar
slf4j-log4j-1.5.2.jar
ejb3-persistence.jar
hibernate-annotation.jar
hibernate-commons-annotations.jar
Log
log4j:WARN No appenders could be found for logger (org.hibernate.cfg.annotations.Version).
log4j:WARN Please initialize the log4j system properly.
Exception in thread "main" java.lang.NoSuchFieldError: INSTANCE
at org.hibernate.type.BasicTypeRegistry.<init>(BasicTypeRegistry.java:94)
at org.hibernate.type.TypeResolver.<init>(TypeResolver.java:59)
at org.hibernate.cfg.Configuration.<init>(Configuration.java:250)
at org.hibernate.cfg.Configuration.<init>(Configuration.java:302)
at org.hibernate.cfg.AnnotationConfiguration.<init>(AnnotationConfiguration.java:87)
at FirstExample.main(FirstExample.java:15)
I can compile without errors, but not able to run the app. I am guessing there's a problem with jar files. Please advise me on the above as well. Thanks in advance.
instead of
<mapping resources> use <mapping class>
a silly mistake indeed. My app is now running perfectly!
Related
I have created a Jackson PropertyFilter an registered it with an XmlMapper, but it is not used to filter properties returned from a Spring #RestController.
I have created and used a Jackson PropertyFilter to filter JSON results produced by an ObjectMapper for a Spring #RestController. I'm trying to enable the same functionality for XML, but can't get it working.
I've tried registering the filter directly on an XmlMapper instance and through a Jackson2ObjectMapperBuilder. In both cases it isn't called.
I've stepped through the code and the XmlBeanSerializer seems to have a reference to the filter, but the filter never gets called.
I created a LogAllPropertyFilter class to just log if the filter is called and no log messages are ever produced.
public class LogAllPropertyFilter extends SimpleBeanPropertyFilter implements PropertyFilter {
private Logger logger = LoggerFactory.getLogger(getClass());
#Override
public void serializeAsField(Object pojo, JsonGenerator gen, SerializerProvider prov, PropertyWriter writer)
throws Exception {
logger.info(" *** *** serializeAsField {}.{}",
pojo.getClass().getSimpleName(),
writer.getName());
super.serializeAsField(pojo, gen, prov, writer);
}
#Override
public void serializeAsElement(Object elementValue, JsonGenerator gen, SerializerProvider prov,
PropertyWriter writer) throws Exception {
logger.info(" *** *** serializeAsElement {}.{}",
elementValue.getClass().getSimpleName(),
writer.getName());
super.serializeAsElement(elementValue, gen, prov, writer);
}
#SuppressWarnings("deprecation")
#Override
public void depositSchemaProperty(PropertyWriter writer, ObjectNode propertiesNode, SerializerProvider provider)
throws JsonMappingException {
logger.info(" *** *** depositSchemaProperty {} (deprecated)",
writer.getName());
super.depositSchemaProperty(writer, propertiesNode, provider);
}
#Override
public void depositSchemaProperty(PropertyWriter writer, JsonObjectFormatVisitor objectVisitor,
SerializerProvider provider) throws JsonMappingException {
logger.info(" *** *** depositSchemaProperty {} (deprecated)",
writer.getName());
super.depositSchemaProperty(writer, objectVisitor, provider);
}
}
I'm creating and registering the PropertyFilter like this:
<bean id="logAllFilter" class="calpers.eai.config.auth.jacksonpropertyfilter.LogAllPropertyFilter" />
<bean id="logAllFilterProvider"
class="com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider">
<constructor-arg>
<map>
<entry key="logAllFilter"
value-ref="logAllFilter" />
</map>
</constructor-arg>
</bean>
<bean id="xmlObjectMapper"
class="com.fasterxml.jackson.dataformat.xml.XmlMapper" />
<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetObject" ref="xmlObjectMapper" />
<property name="targetMethod" value="setFilterProvider" />
<property name="arguments" ref="logAllFilterProvider" />
</bean>
<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetObject" ref="xmlObjectMapper" />
<property name="targetMethod" value="disable" />
<property name="arguments" value="WRITE_DATES_AS_TIMESTAMPS" />
</bean>
<!-- indent json - disable this in prod -->
<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetObject" ref="xmlObjectMapper" />
<property name="targetMethod" value="enable" />
<property name="arguments" value="INDENT_OUTPUT" />
</bean>
<bean id="xmlConverter" class="org.springframework.http.converter.xml.MappingJackson2XmlHttpMessageConverter">
<constructor-arg ref="xmlObjectMapper" />
</bean>
<mvc:annotation-driven>
<mvc:message-converters>
<!-- json works -->
<ref bean="jsonConverter" />
<!-- xml doesn't work -->
<ref bean="xmlConverter" />
</mvc:message-converters>
</mvc:annotation-driven>
The XML output is indented so I know it the XmlMapper instance is getting picked up. However, the PropertyFilter methods are never called. I'm stumped.
The filter won't be applied unless the class is linked to the filter somehow. Typically an annotation is used, but in this case, I need to filter properties on all objects, regardless of their provenance, so we'll use a mix-in on the common base-class of all Java objects:
<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetObject" ref="xmlObjectMapper" />
<property name="targetMethod" value="addMixIn" />
<property name="arguments">
<list>
<value type="java.lang.Class">java.lang.Object</value>
<value type="java.lang.Class">eai.config.auth.jacksonpropertyfilter.SecurityRoleAwareJacksonMixIn</value>
</list>
</property>
</bean>
With this added to the config, my filters are running on every XML object served from my Spring MVC #RestController.
Here is a handy filter to control access to class properties based on security roles in Spring Security. Enjoy!
package eai.config.auth.jacksonpropertyfilter;
import java.io.IOException;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.ldap.userdetails.LdapAuthority;
import com.fasterxml.jackson.databind.introspect.AnnotatedMember;
import com.fasterxml.jackson.databind.ser.BeanPropertyWriter;
import com.fasterxml.jackson.databind.ser.PropertyWriter;
import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter;
import eai.config.auth.jacksonpropertyfilter.xml.SecurityRole;
import eai.config.refreshable.Refreshable;
/**
* Filters based on the union of properties a principal can view. In JsonViewConfiguration a user
* with multiple views will be assigned the highest ranked view and only see the properties that are
* included in that view. With SecurityRoleAwareJacksonFilterImpl, the user will see any property they
* have access to based on ALL the groups they are members of. Therefore, it is the union of
* all #JsonView's.
*
* This class should be instantiated as a Spring Bean, probably in the XML config to maximize
* configuration options that avoid a re-compile.
*
* #author TPerry2
*/
public class SecurityRoleAwareJacksonFilterImpl extends SimpleBeanPropertyFilter
implements SecurityRoleAwareJacksonFilter, Refreshable {
private final Logger logger = LoggerFactory.getLogger(
SecurityRoleAwareJacksonFilterImpl.class);
Map<Class<?>, Map<String, Collection<SecurityRole>>> classPropertyRoles =
new HashMap<>();
List<SecurityRoleToClassPropertyReader> securityRoleToClassPropertyReaders =
new ArrayList<>();
private ConcurrentHashMap<String, String> knownUserNoRole =
new ConcurrentHashMap<>();
private ConcurrentHashMap<Class<?>, Set<String>> classPropsWithNoAccess =
new ConcurrentHashMap<>();
/**
* Add mapping for what class properties a LDAP role can view.
*
* #param securityRoleToClassPropertyXmlReaders to obtain mapping data from.
* #throws ClassNotFoundException if the java class can not be found.
* #throws IOException when security role to class property XML files can't be read.
*/
#Override
#Autowired
public void setSecurityRoleToClassPropertyReaders(
List<SecurityRoleToClassPropertyReader> securityRoleToClassPropertyReaders)
throws ClassNotFoundException, IOException {
this.securityRoleToClassPropertyReaders = securityRoleToClassPropertyReaders;
loadClassPropertyRoles();
}
/**
* Method called to determine whether property will be included
* (if 'true' returned) or filtered out (if 'false' returned)
*/
protected boolean include(BeanPropertyWriter writer) {
AnnotatedMember memberToSerialize = writer.getMember();
if (memberToSerialize == null) {
logger.warn("Could not get member to serialize for writer {}",
writer.getClass().getName());
return false;
}
final Class<?> clazz = memberToSerialize.getDeclaringClass();
return include(clazz, writer.getName());
}
/**
* Method called to determine whether property will be included
* (if 'true' returned) or filtered out (if 'false' returned)
*/
protected boolean include(PropertyWriter writer) {
AnnotatedMember memberToSerialize = writer.getMember();
if (memberToSerialize == null) {
logger.warn("Could not get member to serialize for writer {}",
writer.getClass().getName());
return false;
}
final Class<?> clazz = memberToSerialize.getDeclaringClass();
return include(clazz, writer.getName());
}
protected boolean include(
Class<?> clazz,
String propertyName) {
logger.info("Checking {}.{}", clazz.getSimpleName(), propertyName);
final Map<String, Collection<SecurityRole>> propertyLdapRoleMap =
classPropertyRoles.get(clazz);
if (propertyLdapRoleMap != null) {
final Collection<SecurityRole> securityRoles =
propertyLdapRoleMap.get(propertyName);
if (securityRoles != null && securityRoles.size() > 0) {
Authentication auth = getAuthentication();
if (isAuthorized(getGrantedAuthorities(auth), securityRoles)) {
logger.info("allowing {}.{}", clazz.getSimpleName(), propertyName);
return true;
} else {
logUserNoRole(clazz, propertyName, securityRoles, auth);
}
} else {
logPropertyWithNoAccess(clazz, propertyName);
}
} else {
logPropertyWithNoAccess(clazz, "-- all properties --");
}
return false;
}
private void logUserNoRole(
Class<?> clazz,
String propertyName,
Collection<SecurityRole> allowedRoles,
Authentication auth) {
if (!logger.isDebugEnabled()) {
return;
}
String username = (auth == null ? "anonymous" : auth.getName());
final String knownUserNoRoleString = ""
+ clazz.getName() + "." + propertyName + "."
+ username;
boolean known = knownUserNoRole.containsKey(knownUserNoRoleString);
if (!known) {
knownUserNoRole.put(knownUserNoRoleString, "");
logger.debug("User {} does not have valid role for {}.{}. "
+ "Requires one of {}", username, clazz.getName(),
propertyName, allowedRoles);
}
}
private void logPropertyWithNoAccess(Class<?> clazz, String propertyName) {
Set<String> knownPropsWithNoAccess = classPropsWithNoAccess.get(clazz);
if (knownPropsWithNoAccess == null) {
logger.warn("No roles enable access to {}.{}",
clazz.getSimpleName(), propertyName);
knownPropsWithNoAccess = new HashSet<>();
classPropsWithNoAccess.put(clazz, knownPropsWithNoAccess);
}
boolean wasAdded = false;
synchronized (knownPropsWithNoAccess) {
wasAdded = knownPropsWithNoAccess.add(propertyName);
}
if (wasAdded) {
logger.warn("No roles enable access to {}.{}",
clazz.getSimpleName(), propertyName);
}
}
private boolean isAuthorized(
Collection<? extends GrantedAuthority> grantedAuths,
Collection<SecurityRole> securityRoles) {
try {
if (grantedAuths == null) {
return false;
}
for (GrantedAuthority grantedAuth : grantedAuths) {
if (grantedAuth instanceof LdapAuthority) {
LdapAuthority ldapAuth = (LdapAuthority) grantedAuth;
for (SecurityRole secRole : securityRoles) {
if (secRole.distinguishedNameIsAuthorized(
ldapAuth.getDn())) {
return true;
}
if (secRole.displayNameIsAuthorized(
ldapAuth.getAuthority())) {
return true;
}
}
} else {
for (SecurityRole secRole : securityRoles) {
if (secRole.displayNameIsAuthorized(
grantedAuth.getAuthority())) {
return true;
}
}
}
}
return false;
} catch (NullPointerException npe) {
logger.error("FIXME", npe);
return false;
}
}
private Collection<? extends GrantedAuthority> getGrantedAuthorities(
Authentication auth) {
if (auth == null) {
return Collections.emptyList();
}
try {
return auth.getAuthorities();
}
catch (Exception e) {
logger.error("Could not retrieve authorities", e);
return Collections.emptyList();
}
}
private Authentication getAuthentication() {
try {
SecurityContext secCtxt = SecurityContextHolder.getContext();
if (secCtxt == null) {
logger.warn("SecurityContextHolder.getContext() returned null, " +
+ "no authorities present");
return null;
}
Authentication auth = secCtxt.getAuthentication();
if (auth == null) {
logger.warn("SecurityContextHolder.getContext().getAuthentication() "
+ "returned null, no authorities present");
}
return auth;
} catch (Exception e) {
logger.error("Could not retrieve Authentication", e);
return null;
}
}
private void loadClassPropertyRoles() {
Map<Class<?>, Map<String, Collection<SecurityRole>>> newClassPropertyRoles =
new HashMap<>();
for (SecurityRoleToClassPropertyReader reader : securityRoleToClassPropertyReaders) {
Map<Class<?>, Map<String, Collection<SecurityRole>>> readerClassPropertyRoles =
reader.loadClassPropertyRoles();
for (Class<?> clazz : readerClassPropertyRoles.keySet()) {
Map<String, Collection<SecurityRole>> propertyRoles =
newClassPropertyRoles.get(clazz);
if (propertyRoles == null) {
propertyRoles = new HashMap<>();
newClassPropertyRoles.put(clazz, propertyRoles);
}
for (String propertyName : readerClassPropertyRoles.get(clazz).keySet()) {
Collection<SecurityRole> allowedRolesForProp =
propertyRoles.get(propertyName);
if (allowedRolesForProp == null) {
allowedRolesForProp = new ArrayList<>();
propertyRoles.put(propertyName, allowedRolesForProp);
}
Collection<SecurityRole> newLdapRoles =
readerClassPropertyRoles.get(clazz).get(propertyName);
for (SecurityRole securityRole : newLdapRoles) {
if (!allowedRolesForProp.contains(securityRole)) {
allowedRolesForProp.add(securityRole);
}
}
}
}
}
this.classPropertyRoles = newClassPropertyRoles;
}
}
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
we are working on springMVC java config app. I am facing a problem every time when i trying to view child object properties but getting lazyinitialisationexception no session error. this i am getting on ajax calls also. I know that eager fetching is one solution and Hibernate.initailize(child) is another. But what is the standard way to resolve this?
My entities are like this
import java.io.Serializable;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
#Entity
#Table(name = "COUNTRY_DETAILS")
public class Country implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
private Long id;
private String name;
private Set<State> states;
#Id
#GeneratedValue
#Column(name = "ID", length = 20, nullable = false)
public Long getId() {
return id;
}
public void set Id(Long id) {
this.id = id;
}
#Column(name = "NAME", length = 20, nullable = false)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Country() {
super();
// TODO Auto-generated constructor stub
}
public Country(String name) {
super();
this.name = name;
}
#OneToMany(fetch = FetchType.LAZY, mappedBy = "countryId")
public Set<State> getStates() {
return states;
}
public void setUnits(Set<State> states) {
this.states = states;
}
}
States entity
#Entity
#Table(name = "State_DETAILS")
public class State implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue
#Column(name = "State_ID", length = 20, nullable = false)
private Long StateId;
#Column(name = "State_NAME", length = 20, nullable = false)
private String StateName;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "Country_ID", nullable = false, //
foreignKey = #ForeignKey(name = "Country_DETAIL_State_FK") )
private Country countryId;
Public Long getStateId() {
return StateId;
}
public void setStateId(Long StateId) {
this.StateId = StateId;
}
public String getStateName() {
return StateName;
}
public void setStateName(String StateName) {
this.StateName = StateName;
}
public Country getCountryId() {
return countryId;
}
public void setCmdId(Country countryId) {
this.countryId = countryId;
}
public State(Long StateId) {
super();
this.StateId = StateId;
}
public State() {
super();
// TODO Auto-generated constructor stub
}
}
My Controller
This is my controler
#RequestMapping(value = "/findStatesByCountry", method = RequestMethod.GET)
public #ResponseBody List<State> findAllStateByCountryId() {
Country c=new Country();
c.setId((long) 1);
List<State> states=stateService.getStatesByCommand(c);
return units;
}
Error I am getting is
org.springframework.http.converter.HttpMessageNotWritableException: Could not write content: could not initialize proxy - no Session
I want to show in view like country.state.stateId ,state.country.name e.t.c .
How to resolve this type of situation?
Eager is the not the solution i want to use
Found the answer finally.OpenEMInViewFilter is the solution..I tried the following and working fine...
<filter-name>openSessionInViewFilter</filter-name>
<filter-class>
org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter
</filter-class>
</filter>
<filter-mapping>
<filter-name>openSessionInViewFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
I have used interceptor also..
<mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/**"/> <mvc:exclude-mapping
path="/resources/**"/>
<bean class="org.springframework.orm.jpa.support.OpenEntityManagerInViewInterceptor"
/>
</mvc:interceptor>
</mvc:interceptors>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
it is working fine now and able to fetch associations in views.Let me know if any cons in this type of usage...
Thanx
Initially I had a converter for almost every entity classes in my project. I decided to drop all those converters and created a ConverterFactory that will do all the conversion.
#Service("dataConverterFactory")
public class DataConverterFactory implements ConverterFactory<String, CommonEntity> {
private static final Logger logger = LoggerFactory.getLogger(DataConverterFactory.class);
private final EntityManager em;
#Autowired
public DataConverterFactory(EntityManager em) {
this.em = em;
}
#Override
public <T extends CommonEntity> Converter<String, T> getConverter(Class<T> targetType) {
return new GenericConverter(targetType);
}
private final class GenericConverter<T extends CommonEntity> implements Converter<String, T> {
private final Class<T> targetType;
public GenericConverter(Class<T> targetType) {
this.targetType = targetType;
}
#Override
public T convert(String text) {
if (text != null && !text.isEmpty() && !text.equalsIgnoreCase("-1")) {//Ignore - to be determined later
try {
return (T) em.find(targetType, Integer.valueOf(text.trim()));
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
}
return null;
}
}
}
This works fine but my tests are failing when conversion is required. Here is a snippet from my test xml configuration file
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<set>
<ref bean="dataConverterFactory"/>
</set>
</property>
</bean>
<bean id="dataConverterFactory" class="com.xyz.converter.DataConverterFactory"/>
Sample test
mockMvc.perform(fileUpload("/complaint/new")
.file(file)
.param("customer", "1")
)
In the above test,I am trying to submit a Complaint but it will fail because customer will be null.
Parameter customer should be converted to class Customer which extends CommonEntity.
public class Complaint extends CommonEntity {
#NotNull
#ManyToOne
#JoinColumn(name = "customer_id", updatable = false)
private Customer customer;
}
How do mock/set conversion service to work in my tests?
private MockMvc mockMvc;
#Before
public void setUp() {
YourController converterController = new YourController();
FormattingConversionService cs = new FormattingConversionService();
cs.addConverter(new YourConverter());/////here
mockMvc = MockMvcBuilders.standaloneSetup(converterController)
.setConversionService(cs)/////here
.build();
}
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