Spring Boot store data with WebSockets - jpa

I have a simple WebSocket set up and try to save data. Somehow the data gets not persisted. I don't get any error messages and the object gets returned correct to the client. If I try to store the object with a REST controller and a REST request it works.
Here are the dependencies of my build.gradle file:
dependencies {
compile 'org.springframework.boot:spring-boot-starter-web'
compile 'org.springframework.boot:spring-boot-starter-data-jpa'
compile 'org.springframework.boot:spring-boot-starter-websocket'
compile 'org.springframework:spring-messaging'
compile 'com.google.code.gson:gson:1.7.2'
compile 'org.postgresql:postgresql:9.4-1200-jdbc41'
compile 'commons-dbcp:commons-dbcp:1.4'
testCompile('org.springframework.boot:spring-boot-startet-test')
}
PersonController
#Controller
public class PersonController {
#Autowired
PersonRepository personRepository;
#MessageMapping("/test")
#SendTo("/response/test")
public Person test() throws Exception {
Person person = new Person();
person.setName("John Doe");
return personRepository.save(person);
}
}
Configuration for STOMP messaging
#Configuration
#EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
#Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/response");
config.setApplicationDestinationPrefixes("/app");
}
#Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/websocket")
.setAllowedOrigins("*")
.withSockJS();
}
Person entity
#Entity
public class Person {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String name;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return getName;
}
public void setName(String name) {
this.name = name;
}
}
Base Repository
#NoRepositoryBean
public interface BaseRepository<T, ID extends Serializable> extends Repository<T, ID> {
void delete(T deleted);
void delete(ID id);
Iterable<T> findAll();
T findOne(ID id);
T save(T persisted);
Iterable<T> save(Iterable<T> persited);
}
Person Repository
public interface PersonRepository extends
BaseRepository<Person, Serializable> {
}
Is there a problem in my code?
Is there an issue with caching? Do I have to force flushing?
Is storing data with WebSockets supported by SpringBoot?
Do you know any examples with storing data? I could only find basic examples without storing data.

The problem was in my persistence configuration. I changed the configuration from a Java implementation to the application.properties file. I think there was a problem with my transaction manager.
To be complete, here is my current application.properties file:
spring.datasource.url = jdbc:postgresql://localhost:5432/test
spring.datasource.username = test
spring.datasource.password = test
spring.datasource.testWhileIdle = true
spring.datasource.validationQuery = SELECT 1
spring.jpa.show-sql = true
spring.jpa.hibernate.ddl-auto = create
spring.jpa.hibernate.naming-strategy = org.hibernate.cfg.ImprovedNamingStrategy
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect

Related

Spring Boot Cassandra Error connecting to Node(endPoint=localhost:1234, hostId=null, hashCode=37hfeouh3),

In my Spring Boot Cassandra build I am getting the following error: s0-admin-1] c.d.o.d.i.c.control.ControlConnection : [s0] Error connecting to Node(endPoint=localhost:1234, hostId=null, hashCode=37hfeouh3), trying next node (ConnectionInitException: [s0|control|connecting...] Protocol initialization request, step 1 (OPTIONS): failed to send request (io.netty.channel.StacklessClosedChannelException))
Entity type of
#Data
#Builder
#Table
public class Class1 {
#Id
private String id;
private String data;
private Class2 data2;
private Integer data3;
...
}
public class2 Class2 {
#Id
#JasonProperty
private String id;
#Indexed
#JasonProperty
private String data;
#JasonProperty
private String data2;
#JasonProperty
private Integer data3;
...
}
#Configuration
#EnableCassandraRepositories
#ConfigurationProperties(prefix = "DBProperties")
public class ApplicationConfig extends AbstractCassandraConfiguration {
private String DBKEYSPACE;
#Override
protected String getKeyspaceName() {
return DBKEYSPACE;
}
public String[] getEntityBasePackages() {
return new String[] { "com.oreilly.springdata.cassandra" };
}
}
#ConfigurationProperties(prefix = "DBPROPERTIES")
#Slf4j
public class FactoryBeanAppConfig {
private String contactPoints;
private String keySpace;
private Integer port;
private String password;
private String username;
private String dataCenter;
/*
* Factory bean that creates the com.datastax.oss.driver.api.core.CqlSession instance
*/
#Bean
public CqlSessionFactoryBean session() {
//log it we made it.
log.info("I made it to CqlSessionFactoryBean");
CqlSessionFactoryBean session = new CqlSessionFactoryBean();
session.setContactPoints(URLINFO);
log.info("Contact Points: " +URLINFO);
session.setKeyspaceName(DBKEYSPACE);
//session.setPort(OURPORT);
session.setUsername(username);
session.setPassword(password);
session.setLocalDatacenter(LOCALDCENTER INFORMATION);
return session;
}
}
I am unable to find a good example or even a get it to work correctly. Looking at this documentation: https://docs.spring.io/spring-data/cassandra/docs/current/reference/html/#cassandra.core thats the only thing I should have to do to implement example 55
For the spring boot run your application, it need to load the DB when your server application (the tomcat for example) is starting. So, your schema should be created first. If it is ok, you could change the "localhost" to "127.0.0.1" in your cassandra.yaml file.
Important: "[s0] Error connecting to Node(endPoint=localhost:1234,..." please check the cassandra's port. The correct is 9042.
It will solve your problem. However, others errors can be happen, because the others classes.
Then, you could correct the classes below:
#SpringBootApplication
#EnableCassandraRepositories(basePackages = { "<package's path>" })
#EntityScan(basePackages = { "<package's path>" })
#ComponentScan(basePackages = { "<package's path>" })
public class ApplicationConfig extends SpringBootServletInitializer
{
SpringApplication.run(ApplicationConfig.class, args);
}
Entity:
#Table("<table name>")
public class Class1 {
#PrimaryKeyColumn(name = "<field name id>", type = PrimaryKeyType.PARTITIONED)
private String id;
#Column("<field name data>")
private String data;
private Class2 data2; //I think this declaretion can cause error
#Column("<field name data3>")
private Integer data3;
...
}
This FactoryBeanAppConfig's class is not sound good. I created a class to read the application.properties and inject this class to connect with the db datas like keyspace's name, port, and so one. This link will help you to creat this class: https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.external-config . And then, you use this class in your FactoryBeanAppConfig's class to get DBKEYSPACE, OURPORT, ... .
This is a example to helps you to understand what I'm saying: https://www.baeldung.com/spring-data-cassandra-tutorial .

Eclipse cannot see beyond Beans' models' fields from AbstractBean/AbstractEntity in Facelets

I am running jee-2019-06 version of Eclipse. Here is my Model-Bean-Facade structure:
I am not including getters/setters for brevity.
My Identifiable:
/** Identifiable interface for Entities; used for DAO - Service transitions. */
public interface Identifiable<T extends Serializable> extends Serializable {
public T getId(); // identifiable field
public String getTitle(); // user friendly name (maybe different from actual entity's name)
public String getName(); // every entity has a name
public String getDescription(); // every entity should have a description
}
My Abstract Bean:
public abstract class AbstractBean<T extends Identifiable<?>> {
protected final transient Logger log = Logger.getLogger(this.getClass());
private final Class<T> clazz;
private T model;
public AbstractBean(final Class<T> clazz) {
this.clazz = clazz;
}
protected T createInstance() {
try {
return this.clazz.newInstance();
} catch (InstantiationException | IllegalAccessException e) {
this.log.error("[" + this.getClass().getSimpleName() + ".createInstance()] : Error : {} {}", e.getMessage(), e);
return null;
}
}
protected AbstractFacade<T> getFacade() {
return null;
}
}
My Abstract Facade:
#Transactional
public abstract class AbstractFacade<T extends Identifiable<?>> {
protected final transient Logger log = Logger.getLogger(this.getClass());
protected final Class<T> clazz;
public AbstractFacade(final Class<T> clazz) {
this.clazz = clazz;
}
}
My Bean:
#Named
#ViewScoped
public class CarBean extends AbstractBean<Car> {
#Inject
private CarFacade facade;
public CarBean(){
super(Car.class);
}
#Override
public CarFacade getFacade() {
return this.facade;
}
}
My AbstractEntity:
#MappedSuperclass
public abstract class AbstractEntity implements Identifiable<Integer> {
private Integer id;
private String name;
private String description;
public AbstractEntity() {
}
}
My Entity:
public class Car extends AbstractEntity {
public Car() {
}
}
I have no problems in showing the value to the user.
I have problems in validation and hyperlink in Eclipse:
<h:outputText value="#{carBean.model.name}" />
Facelet validator cannot validate name of model. It yellow underlines name. Also, I cannot Ctrl + click to activate hyperlink on name.
I saw on another developer's eclipse that both of my problems were not issues at all. I compared all the tools installed in both Eclipses and could not find anything relevant.
My question: what tools do I have to install or what settings/adjustments am I missing?
Please note: I do not want to disable the validator and I want to be able to hyperlink fields in facelet so that I will access the field using Ctrl + click.
Thank you.

#TransactionalEventListener annotated method not invoked in #Transactional test

I'm trying to implement domain event publishing from an entity by following the examples mentioned on the post below:
Example for #DomainEvents and #AfterDomainEventsPublication
However I haven't managed to have Spring calling my method annotated with #TransactionalEventListener.
See below the entity, service, event listener and test code:
#Entity
public class Book extends AbstractAggregateRoot<Book>
{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#Column(unique = true)
private String isbn;
#Column
private String name;
public Book(String isbn, String name)
{
this.isbn = isbn;
this.name = name;
}
public void purchase()
{
registerEvent(new BookPurchasedEvent(id));
}
// getters omitted for brevity
}
Service:
#Service
#Transactional
public class BookService
{
private final BookRepository bookRepository;
public BookService(BookRepository bookRepository)
{
this.bookRepository = bookRepository;
}
public void purchaseBook(Integer bookId)
{
Book book = bookRepository.findById(bookId)
.orElseThrow(NoSuchElementException::new);
book.purchase();
bookRepository.save(book);
}
}
Listener:
#Service
public class EventListener
{
private final Logger logger = LoggerFactory.getLogger(this.getClass());
#TransactionalEventListener
public void handleEvent(BookPurchasedEvent event)
{
logger.info("Received event {}", event);
}
}
Test:
#RunWith(SpringRunner.class)
#SpringBootTest
#Transactional
public class BookEventsTest
{
#Autowired
private BookService bookService;
#Autowired
private EntityManager entityManager;
#Test
public void test()
{
Book book = new Book("abcd-efgh", "El Quijote");
book = entityManager.merge(book);
bookService.purchaseBook(book.getId());
}
}
The log message from the listener is not logged. It works though when deployed as a REST service and invoked e.g. via Postman
Got it. Since my test is annotated with #Transactional, the transaction wrapping the test method will be rolled back. Therefore the method annotated with #TransactionalEventListener won't be called, since by default it triggers at the phase TransactionPhase.AFTER_COMMIT (and I'm not interested in having it called unless the transaction is successful). So the working version of the test looks as follows:
#RunWith(SpringRunner.class)
#SpringBootTest
public class BookEventsTest
{
#Autowired
private BookService bookService;
#Autowired
private BookRepository bookRepository;
#MockBean
private EventListener eventListener;
private Book book;
#Before
public void init() {
book = bookRepository.save(new Book("abcd-efgh", "El Quijote"));
}
#After
public void clean() {
bookRepository.deleteAll();
}
#Test
public void testService()
{
bookService.purchaseBook(book.getId());
then(eventListener)
.should()
.handleEvent(any(BookPurchasedEvent.class));
}
}

Rest API with Spring Data MongoDB - Repository method not working

I am reading and learning Spring Boot data with MongoDB. I have about 10 records in my database in the following format:
{
"_id" : ObjectId("5910c7fed6df5322243c36cd"),
name: "car"
}
When I open the url:
http://localhost:8090/items
I get an exhaustive list of all items. However, I want to use the methods of MongoRepository such as findById, count etc. When I use them as such:
http://localhost:8090/items/count
http://localhost:8090/items/findById/5910c7fed6df5322243c36cd
http://localhost:8090/items/findById?id=5910c7fed6df5322243c36cd
I get a 404.
My setup is as so:
#SpringBootApplication
public class Application {
public static void main(String[] args) throws IOException {
SpringApplication.run(Application.class, args);
}
}
#Document
public class Item implements Serializable {
private static final long serialVersionUID = -4343106526681673638L;
#Id
private String id;
private String name;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
#RepositoryRestResource(collectionResourceRel = "item", path = "items")
public interface ItemRepository<T, ID extends Serializable> extends MongoRepository<Item, String>, ItemRepositoryCustom {
}
What am I doing wrong? Do I need to implement the methods as defined by MongoRepository or will they be automatically implemented? I am lost and have been trying to figure this out for so long. I do not have any methods in my controller, its empty.
You have to declare the findById method in order for it to be exposed.
Item findById(String id);
Item findByName(String name);
Note that you don't need to implement the methods. SpringBoot will analyse the method name and provide the proper implementation
I had same issue,
After removing #Configuration,#ComponentScan everything worked fine.

Spring 3 and JAXB

I have implemented a basic mvc app using Spring, i annotated my class as follows
I have added Spring oxm to my pom, but not added jaxb or json handlers.
My configuration is pretty much empty.
So my question is how is spring producing xml output when i call a GET in my controller and returning the following object in xml.
Where is it finding the xml marshaller, is it in the spring-oxm? is there default?
Is this the httpmessageconverters? i set my controller tot he following:
#RequestMapping(value= "/state", method = RequestMethod.GET, produces={MediaType.TEXT_XML_VALUE })
public ResponseEntity<GameState> getGameState(.. response,... request) {..}
my object :
#XmlRootElement(name = "door")
public class GameState {
private int id;
private String state;
public GameState() {
super();
}
public GameState(int id, String state) {
this.id = id;
this.state = state;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
}
Java 6 has JAXB built into the distro, you are specifying the container that ur looking by the
#XmlRootElement(name = "door")
If you will need more information on JAXB bundling here is the API documentation .