Hello i am a fresher i just took i application from online was trying to run it parameters i am using is
Maven
SpringMVC
Mysql
Java
Eclipse
i am able to create a table in the database with this code and delet also but when i am trying to dete it withoutr using save option it's giving me error
****org.hibernate.event.def.DefaultDeleteEventListener deleteTransientEntity
INFO: handling transient entity in delete processing****
when i checked online it show to get the object of the row in the app.java page then delete that object to delete the row i don't know how to get that object and how to pass the row of the database in that object(how to get that field mbedded into the object and how to get that object)plz help all i want is to delete a row from the database base on some column name specific value
App.java class
package com.mkyong.common;
import org.hibernate.Session;
import com.mkyong.persistence.HibernateUtil;
public class App
{
public static void main( String[] args )
{
System.out.println("Maven + Hibernate + MySQL");
Session session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
Stock stock = new Stock();
stock.setStockCode("4715");
stock.setStockName("GENM");
stock.getStockCode();
stock.getStockName();
//session.save(stock);
session.delete(stock);
session.getTransaction().commit();
}
}
AppTest.java
package com.mkyong.common;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
/**
* Unit test for simple App.
*/
public class AppTest
extends TestCase
{
/**
* Create the test case
*
* #param testName name of the test case
*/
public AppTest( String testName )
{
super( testName );
}
/**
* #return the suite of tests being tested
*/
public static Test suite()
{
return new TestSuite( AppTest.class );
}
/**
* Rigourous Test :-)
*/
public void testApp()
{
assertTrue( true );
}
}
Stock.java
package com.mkyong.common;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import static javax.persistence.GenerationType.IDENTITY;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
#Entity
#Table(name = "stock", catalog = "gagan", uniqueConstraints = {
#UniqueConstraint(columnNames = "STOCK_NAME"),
#UniqueConstraint(columnNames = "STOCK_CODE") })
public class Stock implements java.io.Serializable {
private Integer stockId;
private String stockCode;
private String stockName;
public Stock() {
}
public Stock(String stockCode, String stockName) {
this.stockCode = stockCode;
this.stockName = stockName;
}
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "STOCK_ID", unique = true, nullable = false)
public Integer getStockId() {
return this.stockId;
}
public void setStockId(Integer stockId) {
this.stockId = stockId;
}
#Column(name = "STOCK_CODE", unique = true, nullable = false, length = 10)
public String getStockCode() {
return this.stockCode;
}
public void setStockCode(String stockCode) {
this.stockCode = stockCode;
}
#Column(name = "STOCK_NAME", unique = true, nullable = false, length = 20)
public String getStockName() {
return this.stockName;
}
public void setStockName(String stockName) {
this.stockName = stockName;
}
}
HibernateUtil.java
package com.mkyong.persistence;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;
public class HibernateUtil {
private static final SessionFactory sessionFactory = buildSessionFactory();
private static SessionFactory buildSessionFactory() {
try {
// Create the SessionFactory from hibernate.cfg.xml
return new AnnotationConfiguration().configure().buildSessionFactory();
}
catch (Throwable ex) {
// Make sure you log the exception, as it might be swallowed
System.err.println("Initial SessionFactory creation failed." + ex);
throw new ExceptionInInitializerError(ex);
}
}
public static SessionFactory getSessionFactory() {
return sessionFactory;
}
public static void shutdown() {
// Close caches and connection pools
getSessionFactory().close();
}
}
hibernatecfg.xml
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- Database connection settings -->
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<!-- Database connection settings -->
<!-- UAT Database connection settings -->
<property name="connection.url">jdbc:mysql://localhost:3306/gagan</property>
<property name="connection.username">root</property>
<property name="connection.password">123456</property>
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="show_sql">true</property>
<property name="hibernate.hbm2ddl.auto">update</property>
<!-- Think Before made any change in below flag may that clean you complete database -->
<mapping class="com.mkyong.common.Stock"></mapping>
</session-factory>
</hibernate-configuration>
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mkyong.common</groupId>
<artifactId>HibernateExample</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>HibernateExample</name>
<url>http://maven.apache.org</url>
<repositories>
<repository>
<id>JBoss repository</id>
<url>http://repository.jboss.com/maven2/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<!-- MySQL database driver -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.9</version>
</dependency>
<!-- Hibernate core -->
<dependency>
<groupId>hibernate</groupId>
<artifactId>hibernate3</artifactId>
<version>3.2.3.GA</version>
</dependency>
<!-- Hibernate annotation -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>4.3.5.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-c3p0</artifactId>
<version>4.3.5.Final</version>
</dependency>
<!-- Hibernate library dependecy start -->
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.2.1</version>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.2</version>
</dependency>
<!-- Hibernate library dependecy end -->
</dependencies>
</project>
[1]: http://i.stack.imgur.com/tkv2h.png
You can not delete transient object. You need to first synchronize the object with the database. For example you got id of your stock component. Here is a sample piece of code to delete the object based on stockId. Even when you create an object using hibernate it return ID. Use this ID to delete the row from database.
Session session = HibernateUtil.getSessionFactory().openSession();
try {
session.beginTransaction();
Serializable id = stockId;
Object persistentInstance = session.load(Stock.class, id);
if (persistentInstance != null) {
session.delete(persistentInstance);
session.getTransaction().commit();
System.out.println ("Deleted Sucessfully");
}
else {
System.out.println ("Did not find the Stock Object in persistance");
}
}
catch (HibernateException e) {
e.printStackTrace();
}
finally {
if(session!=null){
session.close();
}
}
Stock object is in Transient state ,to delete it, it should be persist in database also note that when you try to delete any object its primary key should be set with it otherwise it will not reflect any changes into the database as STOCK_ID is primary key here .
Related
I am using the spring boot version 2.3.3, below is my pom.xml.
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.group</groupId>
<artifactId>artifact</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>project</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.json/json -->
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20190722</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
I have a custom class/model.
public class Summary {
// attributes
//constructor
// getters/setters for each attributes
}
Its repository (interface and implementation)
public interface SummaryRepository {
List<Summary> getSummaryData(Date date);
}
#Repository
#Transactional
public class SummaryRepositoryImpl implements SummaryRepository {
#PersistenceContext
EntityManager entityManager;
#Override
public List<Summary> getSummaryData(Date date) {
// Implementation
}
}
In the controller, I am having the following code:
#RestController
public class SummaryController {
#Autowired
private SummaryRepository summaryRepository;
#RequestMapping(
value ="/summary-data",
method = RequestMethod.POST,
consumes = "application/json",
produces = MediaType.APPLICATION_JSON_VALUE
)
public ResponseEntity<List<Summary>> getSummaryData(#RequestBody RequestConfig requestConfig ) {
String dateStr = requestConfig.getDate();
Date date = new Date();
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd", Locale.US);
try {
date = formatter.parse(dateStr);
} catch (Exception e) {
System.out.println("Exception: " + e.getMessage());
}
// Some logic
List<Summary> summaries = summaryRepository.getSummaryData(date);
if (summaries.size() > 0 ) {
return ResponseEntity.ok(summaries);
} else {
return ResponseEntity.notFound().build();
}
}
}
When I go to postman and send the POST request to above, I get the output as below:
[["2020-07-31", <values>],["2020-07-31",<values2>],["2020-07-31", <values3>],["2020-07-31",<values4>]]
i.e. literal list of object.
I am looking to get it in Json; something like:
[
{ "date": "2020-07-31", "attr2": "value2", "attr3": "value3" },
{ "date": "2020-07-31", "attr2": "value21", "attr3": "value31" },
{ "date": "2020-07-31", "attr2": "value12", "attr3": "value13" },
{ "date": "2020-07-31", "attr2": "value2", "attr3": "value3" }
]
i.e. "date", "attr2", etc are my attributes of the Summary (already defined with getters/setters).
What is missing here?
--------UPDATE---------
Based on the below response I have my SummaryResponse class.
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.List;
public class SummaryResponse {
#JsonProperty(value = "summary", required = true)
List<Summary> summaryList;
public SummaryResponse() {
}
public List<Summary> getSummaryList() {
return summaryList;
}
public void setSummaryList(List<Summary> summaryList) {
this.summaryList = summaryList;
}
}
I changed my controller logic to return this object.
#RequestMapping(
value ="/summary-data",
method = RequestMethod.POST,
consumes = "application/json"
)
public ResponseEntity<SummaryResponse> getSummaryData(#RequestBody RequestConfig requestConfig ) {
// Logic
List<Summary> summaries = summaryRepository.getSummaryData(date);
SummaryResponse summaryResponse = new SummaryResponse();
summaryResponse.setSummaryList(summaries);
if (summaries.size() > 0 ) {
return new ResponseEntity<>(summaryResponse, HttpStatus.OK);
} else {
return ResponseEntity.notFound().build();
}
}
Still I am not getting the JSON output. It is still Array of attributes.
{"summary":[["2020-07-31","attr2_value","attr3_value", null, "attr5_value"] ,["2020-07-31","attr2_value","attr3_value","attr4_value","attr5_value"]]}
What exactly is the issue here?
I am looking something like below:
[
{ "date": "2020-07-31", "attr2": "attr2_value", "attr3": "attr3_value", "attr4", null, "attr5": "attr5_value" },
{ "date": "2020-07-31", "attr2": "attr2_value", "attr3": "attr3_value", "attr4", "attr4_value", "attr5": "attr5_value" }
]
------------------UPDATE 2: Found the issue.----------------
Thanks for the hints, I got the issue.
In my Repository, I am using the native query where class is not entity.
List<Summary> summaryList = query.getResultList();
return summaryList;
Although I am taking the result in summaryList, it is actually a Object[] and not List. (Didn't knew this, new to spring boot and JPA).
So although my Controller is passing this (summaryList) to response it is actually a Object[].
My Summary Class is not a Entity (does not come from table or has identity), so changed my repository method:
List<Object> result = (List<Object>) query.getResultList();
Iterator it = result.iterator();
List<Summary> summaryList = new ArrayList<>();
while (it.hasNext()) {
Object[] row = (Object[]) it.next();
Summary summary = new Summary();
summary.setDate( (Date) row[0]);
summary.setName(String.valueOf(row[1]));
summary.setAccount(String.valueOf(row[2]));
...
...
// and so on
summaryList.add(summary);
}
Finally it is working as expected.
There are multiple ways to achieve this. You could write your own response class and add Jackson annotations. You need to do the same for the Summary class.
public class MyResponse {
#JsonProperty(value = "summary", required = true)
List<Summary> summaryList;
public List<Summary> getSummaryList() {
return summaryList;
}
public void setSummaryList(List<Summary> summaryList) {
this.summaryList = summaryList;
}
}
Make sure you have the Jackson dependency:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
</dependency>
Check your Summary class.
Based on the http responses you shared, the issue should be there - or at least you should be able to fix it there by adding jackson annotations.
You use a Date type inside your Summary class, which acts strange. If you use regular Date (import java.util.Date;) your response JSON response should look like this:
{
"id": "1",
"name": "Ball",
"date": "2020-10-09T19:05:17.189+00:00"
}
But your JSON has a short String representation of the date: "date": "2020-07-31".
So maybe inside your Summary class you import a Date class, which is not properly supported by Jackson.
Try to remove the date attribute and then check again your JSON response.
Instead of returning the List, just return one element of this List.
This should help you to find your problem.
I wrote this German blog post about handling JSON with Jackson in a Spring RestController - as it is the default in Spring Boot:
https://agile-coding.blogspot.com/2020/10/rest-json-apis-in-java-leicht-gemacht.html
This code works in Spring 5. But my company requires Spring 4.
In Spring 4, login works fine with inMemoryAuthentication. But when I added jdbc logic (c3p0, MySQL dependency && add DataSource code && JDBC connection, c3p0 Connection pool .properties file); server runs, login page opens, but authentication fails (Username/Password is incorrect).
Here is the package Structure
Here is .properties file location and code.
This is the Configuration class
#Configuration
#EnableWebMvc
#ComponentScan(basePackages = "com.nike.mycoolwebapp")
#PropertySource("classpath:persistence-mysql.properties")
public class AppConfig {
// set up variable to hold the properties. One can use spring helper classes or use #Autowired
#Autowired
private Environment env; // will hold the data read from the properties file
// set up a logger for diagnostics
private Logger logger = Logger.getLogger(getClass().getName());
// define a bean for ViewResolver
#Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/view/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
// define a bean for our security datasource
#Bean
public DataSource securityDataSource() {
// create a connection pool
ComboPooledDataSource securityDatasource
= new ComboPooledDataSource();
// set the jdbc driver
try {
securityDatasource.setDriverClass(env.getProperty("jdbc.driver"));
} catch (PropertyVetoException exc) {
// I'm wrapping this exception as runtime exception. It's unchecked and throwing that,
// so, at least the system knows if something goes wrong, or if there's a problem
throw new RuntimeException(exc);
}
// log the connection props
// just for sanity's sake. if it's reading from properties file
logger.info(">>> jdbc.url= " + env.getProperty("jdbc.url"));
logger.info(">>> jdbc.user= " + env.getProperty("jdbc.user"));
logger.info(">>> jdbc.password= " + env.getProperty("jdbc.password"));
// set the database connection props
securityDatasource.setJdbcUrl(env.getProperty("jdbc.url"));
securityDatasource.setUser(env.getProperty("jdbc.user"));
securityDatasource.setPassword(env.getProperty("jdbc.password"));
// set the connection pool props
securityDatasource.setInitialPoolSize(
getIntProperty("connection.pool.initialPoolSize"));
securityDatasource.setMinPoolSize(
getIntProperty("connection.pool.minPoolSize"));
securityDatasource.setMaxPoolSize(
getIntProperty("connection.pool.maxPoolSize"));
securityDatasource.setMaxIdleTime(
getIntProperty("connection.pool.maxIdleTime"));
return securityDatasource;
}
// need a helper method
// read environment property and convert to int
private int getIntProperty(String propName) {
String propValue = env.getProperty(propName);
// now convert to int
int intPropValue = Integer.parseInt(propValue);
return intPropValue;
}
}
Here is Security Config
#Configuration
#EnableWebSecurity
public class AppSecurityConfig extends WebSecurityConfigurerAdapter {
// add a reference to our security data source
#Autowired
private DataSource securityDataSource;
#Autowired
public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception {
/*
//inMemoryAuthentication deprecated in latest Spring
auth.inMemoryAuthentication().withUser("john").password("111").roles(
"EMPLOYEE");
auth.inMemoryAuthentication().withUser("mary").password("111").roles(
"EMPLOYEE", "MANAGER");
auth.inMemoryAuthentication().withUser("susan").password("111").roles(
"EMPLOYEE", "ADMIN");
*/
// use jdbc aunthetication
// tell Spring Security to use JDBC authentication with our data source
auth.jdbcAuthentication().dataSource(securityDataSource);
}
/**
* Configure security of web paths in application, login, logout etc
*/
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
// .anyRequest().authenticated() // any request to the app must be authenticated
// (i.e. logging in)
.antMatchers("/").hasRole("EMPLOYEE").antMatchers("/leaders/**").hasRole("MANAGER")
// show our custom form at the request mapping "/showMyLoginPage"
.antMatchers("/systems/**").hasRole("ADMIN").and().formLogin().loginPage("/showLoginPage")
.loginProcessingUrl("/authenticateTheUser") // Login form should POST data to this URL for processing
// (check username & password)
.usernameParameter("username") // don't add this in spring 5
.passwordParameter("password") // don't add this in spring 5
.permitAll() // Allow everyone to see login page. No need to be logged in.
.and().logout().permitAll().and().exceptionHandling().accessDeniedPage("/access-denied");
}
}
Here is MvcDispatchServletInitializer
public class AppSpringMvsDispatcherServlerInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
#Override
protected Class<?>[] getRootConfigClasses() {
return new Class[] {AppConfig.class};
}
#Override
protected Class<?>[] getServletConfigClasses() {
return null;
}
#Override
protected String[] getServletMappings() {
return new String[] {"/"};
}
}
Here is SecurityWebApplicationInitializer
public class SecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer {
}
Here is pom.xml
http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
<groupId>com.nike.mycoolwebapp</groupId>
<artifactId>mycoolwebapp</artifactId>
<version>1.0</version>
<packaging>war</packaging>
<name>mycoolwebapp</name>
<properties>
<springframework.version>4.1.6.RELEASE</springframework.version>
<springsecurity.version>4.0.1.RELEASE</springsecurity.version>
<c3po.version>0.9.5.2</c3po.version>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<!-- Spring MVC support -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${springframework.version}</version>
</dependency>
<!-- Spring Security -->
<!-- spring-security-web and spring-security-config -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>${springsecurity.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>${springsecurity.version}</version>
</dependency>
<!-- Add Spring Security Taglibs support -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-taglibs</artifactId>
<version>${springsecurity.version}</version>
</dependency>
<!-- Add MySQL support -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.18</version>
</dependency>
<!-- Add c3p0 support -->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>${c3po.version}</version>
</dependency>
<!-- Servlet, JSP and JSTL support -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- to compensate for java 9+ not including jaxb -->
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<!-- TO DO: Add support for Maven WAR Plugin -->
<build>
<finalName>mycoolwebapp</finalName>
<pluginManagement>
<plugins>
<plugin>
<!-- Add Maven coordinates (GAV) for: maven-war-plugin -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.0</version>
</plugin>
</plugins>
</pluginManagement>
</build>
Here is AppController
#Controller
public class AppController {
#RequestMapping(value = "/", method = RequestMethod.GET)
public String showHome() {
return "home";
}
// add a request mapping for /leaders
#RequestMapping(value = "/leaders", method = RequestMethod.GET)
public String showLeader() {
return "leaders";
}
// add a request mapping for /systems
#RequestMapping(value = "/systems", method = RequestMethod.GET)
public String showAdmin() {
return "systems";
}
}
Here is the Login Controller.
#Controller
public class LoginController {
#RequestMapping(value = "/showLoginPage", method = RequestMethod.GET)
public String showLoginPage() {
return "fancy-login";
}
// add a request mapping for /access-denied
#RequestMapping(value = "/access-denied", method = RequestMethod.GET)
public String showAccessDenied() {
return "access-denied";
}
}
Here are MySQL tables
Remove {noop} from the database. {noop} or {bcrypt} is in Spring 5.
i am learning Parameterized Junit test cases, i am trying to get user by Id. while performing this i am getting error:
"Java.lang.IllegelArgumentException: Wrong number of arguments."
please tell me what is the wrong with this code.
#RunWith(Parameterized.class)
public class UserTestCases {
#Mock
UserRepository userRepository;
#InjectMocks
private UserServiceImpl userService;
private User user;
private User expectedUser;
public UserTestCases(User user, User expectedUser) {
super();
this.user = user;
this.expectedUser = expectedUser;
}
#Parameters
public static Collection input() {
User u1=new User(1, "india", "shiva");
User u2=new User(2, "india", "shiva");
User u3=new User(3, "india", "shiva");
return Arrays.asList(new Object[][] {{new User(1L, "india", "shiva"), u1}, {new User(2, "india", "shiva"), u2},{new User(3, "india", "shiva"), u3}});
}
#Test
public void getUserByIdtest() {
when(userRepository.findOne(user.getId())).thenReturn(user);
User result=userService.findById(user.getId());
assertEquals(user.getCountry(), expectedUser.getCountry());
assertEquals(user.getName(), expectedUser.getName());
}
}
Thanks in advance
If you are learning to use JUnit, maybe you can try the last version: JUnit5.
This last version make it easier to compose external features such as mocking, generating test cases, loading Spring beans etc.
Moreover, it as built-in support for parameterized methods (tests), whereas JUnit4 as only parameterized classes (test suites) and was needed JUnitParams and its Runner to support parameterized tests.
Your test can be written like this in JUnit5:
#ExtendWith(MockitoExtension.class)
class UserTestCases {
#Mock UserRepository userRepository;
#InjectMocks UserServiceImpl userService;
#ParameterizedTest
#MethodSource("input")
void getUserByIdtest(User user, User expectedUser) {
when(userRepository.findOne(user.getId())).thenReturn(user);
User result = userService.findById(user.getId());
assertEquals(user.getCountry(), expectedUser.getCountry());
assertEquals(user.getName(), expectedUser.getName());
}
static Stream<Arguments> input() {
return Stream.of(
// static method of Arguments
arguments(
new User(1, "india", "shiva"),
new User(1L, "india", "shiva")),
arguments(
new User(2, "india", "shiva"),
new User(2L, "india", "shiva")),
arguments(
new User(3, "india", "shiva"),
new User(3L, "india", "shiva")),
);
}
}
However, this test is just about delegation from UserServiceImpl to UserRepository, so you do not need parameterized tests here.
The only test that is needed if you want to check delegation (without mapping it seems) is something like:
class UserTestCases {
#Mock UserRepository userRepository;
#InjectMocks UserServiceImpl userService;
#Test
void getUserByIdtest() {
User user = mock(User.class);
when(userRepository.findOne(any())).thenReturn(user);
assertEquals(userService.findById(1L), user);
}
}
Such a test uses JUnit5 and Mockito libraries.
If you are using Maven, your POM can be something like:
<properties>
<junit-jupiter.version>5.3.1</junit-jupiter.version>
<mockito.version>2.23.0</mockito.version>
<surefire-plugin.version>2.22.1</surefire-plugin.version>
</properties>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId>
<version>${junit-jupiter.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>${junit-jupiter.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>${mockito.version}</version>
<scope>test</test>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>${surefire-plugin.version}</version>
</plugin>
</plugins>
</build>
Hope this helps !
I am trying to get a JAX RS resource to return a response with a JSON object. When I display the response properties via println() calls in the resource class I see that the MediaType is correctly set to "application/json", that there is an entity associated with the response with the expected type (SalesOrder), status (Status.FOUND) and that the response object is an instance of OutboundJaxrsResponse. But somehow when the browser (or a Jersey client) receives the response, these response attributes seem to be "replaced" and a HTTP 500 Internal Server error is the result. My SalesOrder class is annotated with #XmlRootElement.
My resource looks like this:
#GET
#Path("{orderUid}")
#Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public Response getSalesOrder(#PathParam("orderUid") Integer orderUid) {
Response response = null;
System.out.println("Entering SalesOrderResource getSalesOrder()...");
SalesOrder retrievedSalesOrder = salesOrderService.retrieveSalesOrder(orderUid);
System.out.println("Service called and found salesOrder Uid: " + retrievedSalesOrder.getSalesOrderUid());
if (retrievedSalesOrder != null) {
System.out.println("SalesOrder found with UID: " + retrievedSalesOrder.getSalesOrderUid());
response = Response.status(Status.FOUND).entity(retrievedSalesOrder).type(MediaType.APPLICATION_JSON).build();
// The following readEntity call results in a Javax.ejb.EJBException ???
// SalesOrder fetched = response.readEntity(SalesOrder.class);
} else {
response = Response.status(Status.NOT_FOUND).header("x-reason", "Order cannot be found").build();
}
System.out.println("Response status: " + response.getStatus());
System.out.println("Response status info: " + response.getStatusInfo());
System.out.println("Response class: " + response.getClass());
System.out.println("Response length: " + response.getLength());
System.out.println("Response media type: " + response.getMediaType());
System.out.println("Response entity: " + response.getEntity());
return response;
}
...which results in the following at runtime:
2015-04-12T18:08:21.803-0600|Info: Response status: 302
2015-04-12T18:08:21.803-0600|Info: Response status info: Found
2015-04-12T18:08:21.803-0600|Info: Response class: class org.glassfish.jersey.message.internal.OutboundJaxrsResponse
2015-04-12T18:08:21.803-0600|Info: Response length: -1
2015-04-12T18:08:21.803-0600|Info: Response media type: application/xml
2015-04-12T18:08:21.803-0600|Info: Response entity: business.salesOrderMgmt.entity.SalesOrder#5e49cadd
The SalesOrder entity is defined as:
#Entity
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
#JsonIgnoreProperties({"subTotal", "userAccount"})
#Table(name="sales_order")
#NamedQuery(name="SalesOrder.findAll", query="SELECT s FROM SalesOrder s")
public class SalesOrder implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="SALES_ORDER_UID")
private int salesOrderUid;
#Column(name="ORDER_NUMBER")
private String orderNumber;
#Column(name="BILL_TO_CITY")
private String billToCity;
#Column(name="BILL_TO_FIRST_NAME")
private String billToFirstName;
#Column(name="BILL_TO_LAST_NAME")
private String billToLastName;
#Column(name="BILL_TO_STATE")
private String billToState;
#Column(name="BILL_TO_STREET_NAME")
private String billToStreetName;
#Column(name="BILL_TO_STREET_NUMBER")
private String billToStreetNumber;
#Column(name="BILL_TO_UNIT_NUMBER")
private String billToUnitNumber;
#Column(name="BILL_TO_ZIP_CODE")
private int billToZipCode;
#Column(name="CREDIT_CARD_CSV")
private int creditCardCsv;
#Temporal(TemporalType.TIMESTAMP)
#Column(name="CREDIT_CARD_EXPIRATION_DATE")
private Date creditCardExpirationDate;
#Column(name="CREDIT_CARD_NUMBER")
private String creditCardNumber;
#Column(name="CREDIT_CARD_TYPE")
private String creditCardType;
#Column(name="EMAIL_ADDRESS")
private String emailAddress;
#Column(name="NAME_ON_CREDIT_CARD")
private String nameOnCreditCard;
#Temporal(TemporalType.TIMESTAMP)
#Column(name="SALES_ORDER_DATE")
private Date salesOrderDate;
#Column(name="SALES_ORDER_STATUS")
private String salesOrderStatus;
#Column(name="SHIP_TO_CITY")
private String shipToCity;
#Column(name="SHIP_TO_STATE")
private String shipToState;
#Column(name="SHIP_TO_STREET_NAME")
private String shipToStreetName;
#Column(name="SHIP_TO_STREET_NUMBER")
private String shipToStreetNumber;
#Column(name="SHIP_TO_UNIT_NUMBER")
private String shipToUnitNumber;
#Column(name="SHIP_TO_ZIP_CODE")
private int shipToZipCode;
#Column(name="PROMO_CODE")
private String promoCode;
//Calculated and persisted for data retrieval performance
#Column(name="SUB_TOTAL")
private BigDecimal subTotal;
#Column(name="DISCOUNT")
private BigDecimal discount;
#Column(name="SALES_TAX")
private BigDecimal salesTax;
#Column(name="SHIPPING")
private BigDecimal shipping;
#Column(name="TOTAL")
private BigDecimal total;
#Version
#Column(name="LAST_UPDATED_TIME")
private Timestamp lastUpdatedTime;
//bi-directional many-to-one association to UserAccount
#ManyToOne
#JoinColumn(name="USER_ACCOUNT_UID")
private UserAccount userAccount;
#OneToMany(targetEntity=SalesOrderLine.class, mappedBy = "salesOrder", cascade = CascadeType.ALL)
private List<SalesOrderLine> lineItems;
public SalesOrder() {
}
...getters and setters
Dependencies in my POM include:
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
<version>2.0.1</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.5.2</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.5.2</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-jaxb-annotations</artifactId>
<version>2.5.2</version>
</dependency>
Not only does a request (http://localhost:8080/[myapp]/resources/salesOrders/13) result in an HTTP 500 Internal Server error but when I have attempted calling response.readEntity(SalesOrder.class) within the resource the Glassfish server log show a javax.ejb.EJBException warning caused by java.lang.IllegalStateException: Method not supported on an outbound message at org.glassfish.jersey.message.internal.OutboundJaxrsResponse.readEntity(OutboundJaxrsResponse.java:145).
I think there is a problem with the JAXB marshalling of the SalesOrder object but I cannot pin down the root cause. If I simply attempt the following I still get an HTTP 500 Internal Server error as well, indicating that neither XML nor JSON marshalling is taking place but I thought this was built into the latest versions (Glassfish 4, JAX-RS 2)?
Any ideas?
I figured out the problem and will post it here for the benefit of others.
1) I added the following to the resource method:
#Consumes(MediaType.TEXT_PLAIN)
2) Step #1 resulted in the following error at runtime:
A cycle is detected in the object graph. This will cause infinitely deep XML
3) The error led me to add #XmlTransient to all entity fields related to other entities in OneToMany, ManyToMany and ManyToOne.
Now I am able to return a response in XML and JSON.
I have had similar problem. To be sure, check if your log shows something like:
SEVERE: MessageBodyWriter not found for media type=application/json,
type=class SalesOrder, genericType=class SalesOrder.
If so, problem is that you did not register Jackson (or another JSON writer provider). See this section of Jersey documentation for instructions:
https://jersey.java.net/documentation/latest/media.html#d0e7857
In my case, I chose Jackson. I added following to my pom.xml.
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.5.2</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-json-provider</artifactId>
<version>2.5.2</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.17</version>
</dependency>
Then I had to register the provider:
public class Application extends ResourceConfig {
public Application() {
packages(<your ws package>);
register(JacksonFeature.class);
}
}
I'm aware that some developer say it's not a unit test to invoke a method of an EJB which requests a web resource. However, please do not argue about that in this thread! I think it is worthwhile to do it.
my Test: testng class --> EJB method --> rest resource
Setup:
Wildfly 8.1
TestNG 6.8.8
jboss-jaxrs-api_1.1_spec, 1.0.1.Final
This is my testing class.
import org.testng.Assert;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import com.doe.webapp.model.general.geoinfo.GeoInfo;
public class GeoIPBeanTest {
#DataProvider(name = "ipAdresses")
public static Object[][] primeNumbers() {
return new Object[][] {
{ "127.0.0.1", true }, // localhost
{ "80.218.114.61", true } }; // real IP
}
#Test(dataProvider = "ipAdresses")
public void getGeoInfoByIp(String ipAddress, boolean isExpectedTrue) {
GeoIPBean geoIpBean = new GeoIPBean();
GeoInfo geoInfo = null;
try {
geoInfo = geoIpBean.getGeoInfoByIp(ipAddress);
} catch (Exception ex) {
Assert.fail(ex.getLocalizedMessage());
}
}
}
This is my class under test.
import javax.ejb.Singleton;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Invocation.Builder;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.MediaType;
import com.doe.webapp.model.general.geoinfo.GeoInfo;
#Singleton
public class GeoIPBean {
private static final String IPV4_PATTERN = "^(([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.){3}([01]?\\d\\d?|2[0-4]\\d|25[0-5])$";
Map<String, GeoInfo> geoInfoCache = new HashMap<String, GeoInfo>();
// Service Description is here http://freegeoip.net/
static final String GEO_SERICE_URL = "http://freegeoip.net/";
static final String FORMAT = "json";
public GeoInfo getGeoInfoByIp(String ipAddress) {
if(!isValidIp(ipAddress)){
//TODO log invalid IP as warning
return null;
}
GeoInfo geoInfo = geoInfoCache.get(ipAddress);
if (geoInfo == null) {
Client client = ClientBuilder.newClient();
// Invoke the service.
WebTarget webTarget = client.target(GEO_SERICE_URL + FORMAT + "/"
+ ipAddress);
//geoInfo
Builder builder = webTarget.request(MediaType.APPLICATION_JSON);
geoInfo = builder.get(GeoInfo.class);
}
return geoInfo;
}
public static boolean isValidIp(String ipAddress) {
if(ipAddress == null)
return false;
Pattern pattern = Pattern.compile(IPV4_PATTERN);
Matcher matcher = pattern.matcher(ipAddress);
return matcher.matches();
}
}
This EJB works when I run it in the container. It does NOT work in a testNG case.
Client client = ClientBuilder.newClient();
This line in the EJB returnS the error.
java.lang.AssertionError: java.lang.ClassNotFoundException: org.glassfish.jersey.client.JerseyClientBuilder
at org.testng.Assert.fail(Assert.java:94)
at com.doe.webapp.service.general.geoinfo.GeoIPBeanTest.getGeoInfoByIp(GeoIPBeanTest.java:25)
I first thought it is because I have annotated the wildfly library with scope provided ...
<!-- JBOSS JAX REST 2.0 FRAMEWORK -->
<dependency>
<groupId>org.jboss.spec.javax.ws.rs</groupId>
<artifactId>jboss-jaxrs-api_1.1_spec</artifactId>
<version>1.0.1.Final</version>
</dependency>
<!-- RS client library -->
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
<version>2.0.1</version>
</dependency>
... but Wildfly is using RestEasy and not Jersey. Then I added ...
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-server</artifactId>
<version>1.18.1</version>
</dependency>
... but did NOT help neither.
In Wildfly, they have been using RESTEasy as the default rest provider. It states,
RESTEasy is bundled with JBoss/Wildfly and completely integrated as per the requirements of Java EE 6.
Therefore you have to remove RESTEasy dependencies defore you use Jersey with Jboss/Wildfly. Eventhough I haven't done that, there can be many resources which guides to do that. (Check these links.)
Or else, as an alternative, you can use RESTEasy instead of Jersey.