diff --git a/.gitignore b/.gitignore index 29937ae..b879e54 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ -out -logs -lib -*.iml -.idea +/out +/logs +/lib +/*.iml +/.idea +/.*.db \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..b698fae --- /dev/null +++ b/LICENSE @@ -0,0 +1,15 @@ +Based on Simple Public License (SimPL) 2.0 +The SimPL applies to the software's source and object code and comes with any rights that I have in it (other than trademarks). +You agree to the SimPL by copying, distributing, or making a derivative work of the software. + +You get the royalty free right to: +- Use the software for any purpose; +- Make derivative works of it (this is called a "Derived Work"); +- Copy and distribute it and any Derived Work. + +There are some things that you must shoulder: +- You get NO WARRANTIES. None of any kind; +- If the software damages you in any way, you may only recover direct damages up to the amount you paid for it + (that is zero if you did not pay anything). You may not recover any other damages, including those called + "consequential damages." (The state or country where you live may not allow you to limit your liability in + this way, so this may not apply to you); diff --git a/README b/README index 7e2e73c..a266a9a 100644 --- a/README +++ b/README @@ -1 +1,41 @@ -This project has some branches that can be merged into your project to add skeleton stuff. +This is a skeleton project for a Java webapp, done right. + +It includes: +- Ant & Ivy for dependency management +- Jersey for handling of http requests in a RESTful way +- Spring for dependency injection in the code +- H2 database (Windows users may need to edit jetty-web.xml) +- Liquibase for DB migration +- Hibernate for working with the DB +- JUnit & Mockito for unit testing + +After cloning, run src/Launcher.java to start. Everything is preconfigured. + +Small amount of code it contains implements a simple database of good Photo Spots, +which uses google maps to browse and edit them. + +Or you can follow how this all have been created by pulling various branches +into your own branch in this order: +- start - empty project +- ivy - add ivy for dependency management +- launcher - adds Jetty launcher to run the app without any external application servers +- map - adds html with Google Map +- web.xml - first step for Java web app +- logging - adds good logging, useful for any web app +- jersey - adds Jersey (JAX-RS implementation) for handling HTTP REST requests +- map-with-spots - adds dummy photo spots to the Google Map +- add-spot - possibility to add new spots to the map +- spring - adds Spring for dependency injection +- db - adds H2 database +- hibernate - adds Hibernate for persisting of objects without hand-coded JDBC code +- tests - adds some unit tests (in real life these should be added on every step) +- db-testing - adds plain JDBC implementation for persistence as well as more tests, see 2nd presentation below + +By following these branches in this order you can also get an idea how to build an app step-by-step, +following Just Enough Design principle. + +See related talk from GOTOCon and Devclub here - "How to get Java back": +http://www.slideshare.net/antonkeks/simplicity-8971441 + +And another one about DB testing from Topconf - "3 tales of testing of DB-enabled apps": +http://prezi.com/kq0ghszq6e-j/3-tales-of-testing-db-enabled-apps/ diff --git a/build.xml b/build.xml index 9dab332..d918a07 100644 --- a/build.xml +++ b/build.xml @@ -2,12 +2,8 @@ - - - - - + diff --git a/db-test/dbunit.pkb b/db-test/dbunit.pkb new file mode 100644 index 0000000..142c99e --- /dev/null +++ b/db-test/dbunit.pkb @@ -0,0 +1,45 @@ +create or replace package body dbunit +is + procedure fail(message varchar2) is + begin + raise_application_error(-20000, 'Assertion failed' || chr(10) || message); + end; + + procedure fail(expected varchar2, actual varchar2) is + begin + fail('Expected: ' || expected || chr(10) || 'Actual: ' || actual); + end; + + procedure expect_exception is + begin + fail('Exception expected'); + end; + + procedure assert_equals(expected number, actual number) is + begin + if expected is null or actual is null or expected != actual then + fail(expected, actual); + end if; + end; + + procedure assert_equals(expected varchar2, actual varchar2) is + begin + if expected is null or actual is null or expected != actual then + fail(expected, actual); + end if; + end; + + procedure assert_null(actual varchar2) is + begin + if actual is not null then + fail(actual || ' is not null'); + end if; + end; + + procedure assert_not_null(actual varchar2) is + begin + if actual is null then + fail('argument is null'); + end if; + end; +end; diff --git a/db-test/dbunit.pkh b/db-test/dbunit.pkh new file mode 100644 index 0000000..c49373e --- /dev/null +++ b/db-test/dbunit.pkh @@ -0,0 +1,9 @@ +create or replace package dbunit +is + procedure fail(message varchar2 default ''); + procedure expect_exception; + procedure assert_equals(expected number, actual number); + procedure assert_equals(expected varchar2, actual varchar2); + procedure assert_null(actual varchar2); + procedure assert_not_null(actual varchar2); +end; diff --git a/db-test/liquibase.xml b/db-test/liquibase.xml new file mode 100644 index 0000000..6c2b590 --- /dev/null +++ b/db-test/liquibase.xml @@ -0,0 +1,23 @@ + + + + + + + + + create or replace public synonym dbunit for dbunit; + grant execute on dbunit to public; + + + + + + + + + + + + diff --git a/db-test/photo_spots_test.sql b/db-test/photo_spots_test.sql new file mode 100644 index 0000000..a56c78b --- /dev/null +++ b/db-test/photo_spots_test.sql @@ -0,0 +1,32 @@ +declare + spot_id number; + spot photospot%rowtype; +begin + -- Can add photo spots + spot_id := photo_spots.add('Teletorn', 'Tallinn TV Tower', 59.47111, 24.8875); + dbunit.assert_not_null(spot_id); + + select * into spot from photospot where id = spot_id; + dbunit.assert_equals('Teletorn', spot.name); + dbunit.assert_equals('Tallinn TV Tower', spot.description); + dbunit.assert_equals(59.47111, spot.latitude); + dbunit.assert_equals(24.8875, spot.longitude); + + -- Cannot insert illegal latitude + begin + spot_id := photo_spots.add('A', 'B', 91.0, 24.0); + dbunit.expect_exception; + exception + when photo_spots.illegal_coordinates then null; + end; + + -- Cannot insert illegal longitude + begin + spot_id := photo_spots.add('A', 'B', 59.0, -181); + dbunit.expect_exception; + exception + when photo_spots.illegal_coordinates then null; + end; + + rollback; +end; diff --git a/db/liquibase.xml b/db/liquibase.xml new file mode 100644 index 0000000..13ee553 --- /dev/null +++ b/db/liquibase.xml @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + begin dbms_utility.compile_schema('demo'); end; + + + + diff --git a/db/photo_spots.pkb b/db/photo_spots.pkb new file mode 100644 index 0000000..3205cbb --- /dev/null +++ b/db/photo_spots.pkb @@ -0,0 +1,14 @@ +create or replace package body photo_spots is + function add(name varchar2, description varchar2, lat float, lon float) return number is + id number; + begin + if lat < -90 or lat > 90 or lon < -180 or lon > 180 then + raise illegal_coordinates; + end if; + + select hibernate_sequence.nextval into id from dual; + insert into photospot (id, name, description, latitude, longitude) + values (id, name, description, lat, lon); + return id; + end; +end; \ No newline at end of file diff --git a/db/photo_spots.pkh b/db/photo_spots.pkh new file mode 100644 index 0000000..cbb050c --- /dev/null +++ b/db/photo_spots.pkh @@ -0,0 +1,5 @@ +create or replace package photo_spots is + illegal_coordinates exception; + + function add(name varchar2, description varchar2, lat float, lon float) return number; +end; diff --git a/src/ee/devclub/model/HibernatePhotoSpotRepository.java b/src/ee/devclub/model/HibernatePhotoSpotRepository.java new file mode 100644 index 0000000..424dc38 --- /dev/null +++ b/src/ee/devclub/model/HibernatePhotoSpotRepository.java @@ -0,0 +1,23 @@ +package ee.devclub.model; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.orm.hibernate3.HibernateOperations; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository +public class HibernatePhotoSpotRepository implements PhotoSpotRepository { + @Autowired HibernateOperations hibernate; + + @Override + public List getAllSpots() { + return hibernate.loadAll(PhotoSpot.class); + } + + @Override + public PhotoSpot persist(PhotoSpot spot) { + hibernate.saveOrUpdate(spot); + return spot; + } +} diff --git a/src/ee/devclub/model/JDBCPhotoSpotRepository.java b/src/ee/devclub/model/JDBCPhotoSpotRepository.java new file mode 100644 index 0000000..e3d674b --- /dev/null +++ b/src/ee/devclub/model/JDBCPhotoSpotRepository.java @@ -0,0 +1,63 @@ +package ee.devclub.model; + +import org.springframework.beans.factory.annotation.Autowired; + +import javax.sql.DataSource; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; + +public class JDBCPhotoSpotRepository implements PhotoSpotRepository { + @Autowired DataSource dataSource; + + public List getAllSpots() { + Connection conn = null; + try { + List spots = new ArrayList(); + conn = dataSource.getConnection(); + ResultSet rs = conn.prepareStatement("select * from PhotoSpot").executeQuery(); + while (rs.next()) { + spots.add(new PhotoSpot(rs.getString("name"), rs.getString("description"), + new Location(rs.getFloat("latitude"), rs.getFloat("longitude")))); + } + return spots; + } + catch (SQLException e) { + throw new RuntimeException(e); + } + finally { + closeSilently(conn); + } + } + + public PhotoSpot persist(PhotoSpot spot) { + Connection conn = null; + try { + conn = dataSource.getConnection(); + PreparedStatement stmt = conn.prepareStatement("insert into PhotoSpot (name, description, latitude, longitude) values (?, ?, ?, ?)"); + stmt.setString(1, spot.name); + stmt.setString(2, spot.description); + stmt.setFloat(3, spot.location.latitude); + stmt.setFloat(4, spot.location.longitude); + stmt.execute(); + return spot; + } + catch (SQLException e) { + throw new RuntimeException(e); + } + finally { + closeSilently(conn); + } + } + + private void closeSilently(Connection conn) { + try { + if (conn != null) conn.close(); + } + catch (SQLException ignore) { + } + } +} diff --git a/src/ee/devclub/model/Location.java b/src/ee/devclub/model/Location.java index 1f79f3f..b8bba2c 100644 --- a/src/ee/devclub/model/Location.java +++ b/src/ee/devclub/model/Location.java @@ -5,8 +5,8 @@ @Embeddable public class Location implements Serializable { - private float latitude; - private float longitude; + float latitude; + float longitude; public Location() { } diff --git a/src/ee/devclub/model/PhotoSpot.java b/src/ee/devclub/model/PhotoSpot.java index 34729c8..f2a6b78 100644 --- a/src/ee/devclub/model/PhotoSpot.java +++ b/src/ee/devclub/model/PhotoSpot.java @@ -1,10 +1,16 @@ package ee.devclub.model; -import javax.persistence.*; +import javax.persistence.Access; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; -@Entity @Access(AccessType.FIELD) +import static javax.persistence.AccessType.FIELD; +import static javax.persistence.GenerationType.AUTO; + +@Entity @Access(FIELD) public class PhotoSpot { - @GeneratedValue(strategy = GenerationType.IDENTITY) + @GeneratedValue(strategy = AUTO) @Id Long id; String name; @@ -31,4 +37,20 @@ public String getDescription() { public Location getLocation() { return location; } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + PhotoSpot photoSpot = (PhotoSpot) o; + return !(description != null ? !description.equals(photoSpot.description) : photoSpot.description != null) && !(id != null ? !id.equals(photoSpot.id) : photoSpot.id != null) && !(location != null ? !location.equals(photoSpot.location) : photoSpot.location != null) && !(name != null ? !name.equals(photoSpot.name) : photoSpot.name != null); + } + + @Override + public int hashCode() { + int result = id != null ? id.hashCode() : 0; + result = 31 * result + (name != null ? name.hashCode() : 0); + return result; + } } diff --git a/src/ee/devclub/model/PhotoSpotRepository.java b/src/ee/devclub/model/PhotoSpotRepository.java index 2ba89a6..e1e6af8 100644 --- a/src/ee/devclub/model/PhotoSpotRepository.java +++ b/src/ee/devclub/model/PhotoSpotRepository.java @@ -1,21 +1,9 @@ package ee.devclub.model; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.orm.hibernate3.HibernateOperations; -import org.springframework.stereotype.Repository; - import java.util.List; -@Repository -public class PhotoSpotRepository { - @Autowired HibernateOperations hibernate; - - public List getAllSpots() { - return hibernate.loadAll(PhotoSpot.class); - } +public interface PhotoSpotRepository { + List getAllSpots(); - public PhotoSpot persist(PhotoSpot spot) { - hibernate.saveOrUpdate(spot); - return spot; - } + PhotoSpot persist(PhotoSpot spot); } diff --git a/src/ee/devclub/rest/PhotoSpotResource.java b/src/ee/devclub/rest/PhotoSpotResource.java index f54111f..c499042 100644 --- a/src/ee/devclub/rest/PhotoSpotResource.java +++ b/src/ee/devclub/rest/PhotoSpotResource.java @@ -12,10 +12,12 @@ @Produces("application/json") public class PhotoSpotResource extends SpringAwareResource { @Autowired PhotoSpotRepository repo; + int maxSpots = 1000; @GET public List getAllSpots() { - return repo.getAllSpots(); + List allSpots = repo.getAllSpots(); + return allSpots.subList(0, Math.min(maxSpots, allSpots.size())); } @POST diff --git a/test/ee/devclub/model/HibernatePhotoSpotRepositoryIntegrationTest.java b/test/ee/devclub/model/HibernatePhotoSpotRepositoryIntegrationTest.java new file mode 100644 index 0000000..7ec878a --- /dev/null +++ b/test/ee/devclub/model/HibernatePhotoSpotRepositoryIntegrationTest.java @@ -0,0 +1,58 @@ +package ee.devclub.model; + +import org.hibernate.dialect.H2Dialect; +import org.junit.Before; +import org.junit.Test; +import org.springframework.jdbc.datasource.DriverManagerDataSource; +import org.springframework.orm.hibernate3.HibernateTemplate; +import org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean; + +import javax.sql.DataSource; +import java.util.List; + +import static org.hamcrest.CoreMatchers.*; +import static org.junit.Assert.assertThat; + +public class HibernatePhotoSpotRepositoryIntegrationTest { + DataSource dataSource; + HibernatePhotoSpotRepository repo = new HibernatePhotoSpotRepository(); + + @Before + public void setUp() throws Exception { + dataSource = new DriverManagerDataSource("jdbc:h2:mem:hibernate;DB_CLOSE_DELAY=-1", "sa", "sa"); + + System.setProperty("hibernate.dialect", H2Dialect.class.getName()); + System.setProperty("hibernate.hbm2ddl.auto", "create-drop"); + AnnotationSessionFactoryBean sessionFactory = new AnnotationSessionFactoryBean(); + sessionFactory.setDataSource(dataSource); + sessionFactory.setAnnotatedClasses(new Class[] {PhotoSpot.class}); + sessionFactory.afterPropertiesSet(); + + repo.hibernate = new HibernateTemplate(sessionFactory.getObject()); + } + + @Test + public void loading() throws Exception { + dataSource.getConnection().createStatement() + .execute("insert into PhotoSpot (id, name, description, latitude, longitude) values (1, 'Kohtuotsa', 'Mega place!', 59.437755, 24.74209)"); + + List spots = repo.getAllSpots(); + assertThat(spots.size(), is(1)); + + PhotoSpot spot = spots.get(0); + assertThat(spot.name, is("Kohtuotsa")); + assertThat(spot.description, is("Mega place!")); + assertThat(spot.location, is(new Location(59.437755f, 24.74209f))); + } + + @Test + public void fullCycle() throws Exception { + PhotoSpot spot = new PhotoSpot("Teletorn", "Tallinn TV Tower", new Location(59.47111f, 24.8875f)); + repo.persist(spot); + repo.hibernate.clear(); + + PhotoSpot spot2 = repo.getAllSpots().get(0); + assertThat(spot2, not(sameInstance(spot))); + assertThat(spot2, equalTo(spot)); + } +} diff --git a/test/ee/devclub/model/HibernatePhotoSpotRepositoryTest.java b/test/ee/devclub/model/HibernatePhotoSpotRepositoryTest.java new file mode 100644 index 0000000..7ed20fa --- /dev/null +++ b/test/ee/devclub/model/HibernatePhotoSpotRepositoryTest.java @@ -0,0 +1,31 @@ +package ee.devclub.model; + +import org.junit.Before; +import org.junit.Test; +import org.springframework.orm.hibernate3.HibernateOperations; + +import java.util.List; + +import static java.util.Arrays.asList; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class HibernatePhotoSpotRepositoryTest { + HibernatePhotoSpotRepository repo = new HibernatePhotoSpotRepository(); + + @Before + public void initMocks() throws Exception { + repo.hibernate = mock(HibernateOperations.class); + } + + @Test + public void allPhotoSpotsComeFromDB() throws Exception { + when(repo.hibernate.loadAll(PhotoSpot.class)).thenReturn(asList(new PhotoSpot("Kohtuotsa", "", new Location(59.437755f, 24.74209f)))); + + List spots = repo.getAllSpots(); + assertThat(spots.size(), is(1)); + assertThat(spots.get(0).name, is("Kohtuotsa")); + } +} diff --git a/test/ee/devclub/model/JDBCPhotoSpotRepositoryIntegrationTest.java b/test/ee/devclub/model/JDBCPhotoSpotRepositoryIntegrationTest.java new file mode 100644 index 0000000..fc9e2e1 --- /dev/null +++ b/test/ee/devclub/model/JDBCPhotoSpotRepositoryIntegrationTest.java @@ -0,0 +1,53 @@ +package ee.devclub.model; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.springframework.jdbc.datasource.DriverManagerDataSource; + +import java.sql.Connection; +import java.util.List; + +import static org.hamcrest.CoreMatchers.*; +import static org.junit.Assert.*; + +public class JDBCPhotoSpotRepositoryIntegrationTest { + Connection conn; + JDBCPhotoSpotRepository repo = new JDBCPhotoSpotRepository(); + + @Before + public void initMockDB() throws Exception { + repo.dataSource = new DriverManagerDataSource("jdbc:h2:mem:test", "sa", "sa"); + conn = repo.dataSource.getConnection(); + + conn.createStatement().execute("create table PhotoSpot (id int auto_increment primary key, name varchar, description varchar, latitude float, longitude float)"); + } + + @After + public void destroyMockDB() throws Exception { + conn.close(); + } + + @Test + public void loading() throws Exception { + conn.createStatement().execute("insert into PhotoSpot values (1, 'Kohtuotsa', 'Mega place!', 59.437755, 24.74209)"); + + List spots = repo.getAllSpots(); + assertThat(spots.size(), is(1)); + + PhotoSpot spot = spots.get(0); + assertThat(spot.name, is("Kohtuotsa")); + assertThat(spot.description, is("Mega place!")); + assertThat(spot.location, is(new Location(59.437755f, 24.74209f))); + } + + @Test + public void fullCycle() throws Exception { + PhotoSpot spot = new PhotoSpot("Teletorn", "Tallinn TV Tower", new Location(59.47111f, 24.8875f)); + repo.persist(spot); + + PhotoSpot spot2 = repo.getAllSpots().get(0); + assertThat(spot2, not(sameInstance(spot))); + assertThat(spot2, equalTo(spot)); + } +} diff --git a/test/ee/devclub/model/JDBCPhotoSpotRepositoryTest.java b/test/ee/devclub/model/JDBCPhotoSpotRepositoryTest.java new file mode 100644 index 0000000..bd6fc32 --- /dev/null +++ b/test/ee/devclub/model/JDBCPhotoSpotRepositoryTest.java @@ -0,0 +1,51 @@ +package ee.devclub.model; + +import org.junit.Before; +import org.junit.Test; + +import javax.sql.DataSource; +import java.sql.ResultSet; +import java.util.List; + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; +import static org.mockito.Mockito.*; + +public class JDBCPhotoSpotRepositoryTest { + JDBCPhotoSpotRepository repo = new JDBCPhotoSpotRepository(); + + @Before + public void setUp() throws Exception { + repo.dataSource = mock(DataSource.class, RETURNS_DEEP_STUBS); + } + + @Test + public void spotFieldsAreCorrectlyMappedToDBColumns() throws Exception { + ResultSet rs = repo.dataSource.getConnection().prepareStatement("select * from PhotoSpot").executeQuery(); + when(rs.next()).thenReturn(true, false); + + when(rs.getString("name")).thenReturn("Kohtuotsa"); + when(rs.getString("description")).thenReturn("Mega place!"); + when(rs.getFloat("latitude")).thenReturn(59.437755f); + when(rs.getFloat("longitude")).thenReturn(24.74209f); + + List spots = repo.getAllSpots(); + + assertEquals(1, spots.size()); + PhotoSpot spot = spots.get(0); + + assertThat(spot.name, is("Kohtuotsa")); + assertThat(spot.description, is("Mega place!")); + assertThat(spot.location, is(new Location(59.437755f, 24.74209f))); + + verify(repo.dataSource.getConnection()).close(); + } + + @Test + public void manySpotFieldsCanBeLoaded() throws Exception { + ResultSet rs = repo.dataSource.getConnection().prepareStatement("select * from PhotoSpot").executeQuery(); + when(rs.next()).thenReturn(true, true, true, false); + assertThat(repo.getAllSpots().size(), is(3)); + } +} diff --git a/test/ee/devclub/rest/PhotoSpotResourceTest.java b/test/ee/devclub/rest/PhotoSpotResourceTest.java new file mode 100644 index 0000000..3cbef6a --- /dev/null +++ b/test/ee/devclub/rest/PhotoSpotResourceTest.java @@ -0,0 +1,44 @@ +package ee.devclub.rest; + +import ee.devclub.model.Location; +import ee.devclub.model.PhotoSpot; +import ee.devclub.model.PhotoSpotRepository; +import org.junit.Before; +import org.junit.Test; +import org.mockito.ArgumentCaptor; + +import static java.util.Collections.*; +import static org.hamcrest.CoreMatchers.*; +import static org.junit.Assert.*; +import static org.mockito.Mockito.*; + +public class PhotoSpotResourceTest { + PhotoSpotResource resource = new PhotoSpotResource(); + + @Before + public void initMocks() throws Exception { + resource.repo = mock(PhotoSpotRepository.class, RETURNS_DEEP_STUBS); + } + + @Test + public void resourceLimitedNumberOfSpotsInRepo() throws Exception { + resource.maxSpots = 10; + PhotoSpot photoSpot = mock(PhotoSpot.class); + when(resource.repo.getAllSpots()).thenReturn(nCopies(15, photoSpot)); + + assertEquals(10, resource.getAllSpots().size()); + } + + @Test + public void newPhotoSpotsArePersisted() throws Exception { + resource.newPhotoSpot("Aegna island", "WWI defence structures", 59.583771f, 24.749720f); + + ArgumentCaptor captor = ArgumentCaptor.forClass(PhotoSpot.class); + verify(resource.repo).persist(captor.capture()); + + PhotoSpot spot = captor.getValue(); + assertThat(spot.getName(), is("Aegna island")); + assertThat(spot.getDescription(), is("WWI defence structures")); + assertThat(spot.getLocation(), is(new Location(59.583771f, 24.749720f))); + } +} diff --git a/webapp/WEB-INF/jetty-web.xml b/webapp/WEB-INF/jetty-web.xml index 4505ef3..c202260 100644 --- a/webapp/WEB-INF/jetty-web.xml +++ b/webapp/WEB-INF/jetty-web.xml @@ -9,6 +9,7 @@ true jdbc:h2:.simple-java;AUTO_SERVER=TRUE;USER=sa;PASSWORD=sa + 5 5 true diff --git a/webapp/WEB-INF/liquibase.xml b/webapp/WEB-INF/liquibase.xml deleted file mode 100644 index 4aec211..0000000 --- a/webapp/WEB-INF/liquibase.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/webapp/WEB-INF/spring.xml b/webapp/WEB-INF/spring.xml index e307ab5..e0f02a3 100644 --- a/webapp/WEB-INF/spring.xml +++ b/webapp/WEB-INF/spring.xml @@ -2,7 +2,7 @@ + xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> @@ -13,11 +13,15 @@ - - + - + + + + + +