I have a problem when making a select to a table in a database, the data resulting from it is incorrect. Can there be some kind of Spring cache to update?
#Service
public class CronogramaService {
#Autowired
private CronogramaRepository cronogramaRepository;
#Autowired
private EntityManager entityManager;
public List<Cronograma> findAll() {
QCronograma cronograma = QCronograma.cronograma;
return new JPAQuery(entityManager)
.from(cronograma)
.list(cronograma);
}
}
Test main
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring_config.xml");
CronogramaService cronoService = context.getBean(CronogramaService.class);
List<Cronograma> crono = cronoService.findAll();
for (Cronograma cronograma : crono) {
System.out.println(cronograma.getDia());
System.out.println(cronograma.getIdCronograma());
}
System.out.println();
((ClassPathXmlApplicationContext)context).close();
}
The application has 365 days of the year 2018. But the result in id 1 returns me the day 2017-12-31. In the database the data of id 1 is 01-01-2018, and I do not understand what the problem is.
We had a similar issue which boiled down to different timezones between application server and database server. Assuming you're using MySQL, try connecting to your database with the serverTimezone parameter set like jdbc:mysql://server:3306/database?serverTimezone=Europe/London
Related
I am using a timer to send out emails on a schedule based on a JPA query but I am getting an error that the driver doesn't support XA. I am unable to switch over to an XA driver and whilst I know I can set some options on the data source I am thinking I am not handling transactions correctly.
There is nothing being persisted and the pseudocode of the time would be
Get list of emails to send from DB (from an EntityManager)
Get email addresses (from a CDI bean)
Send emails
So I don't actually need a two phase commit and I was wondering what the correct way of handling this should be?
The code looks like
#Startup
#Singleton
public class EmailTimer {
#PersistenceContext(unitName = "xyz")
private EntityManager em;
#Inject
private EmailLookup emailLookup;
#Resource
TimerService timerService;
#PostConstruct
public void initTimer() {
// define schedule
timerService.createCalendarTimer(schedExpr, timertConfig);
}
#Timeout
private void sendEmails() {
List<Email> emailsToSend = listEmailsToSend();
For (Email e : emailsToSend) {
sendMail(emailLookup.getEmail(e.userName), "Some Text");
}
}
private List<Email> listEmailsToSend() {
String sql = "select ..."; //moderately long select query
TypedQuery<EmailResults> emailResultsQuery = em.createQuery(sql, EmailResults.class);
return emailResultsQuery.getResultList();
}
}
As nothing has been set explicitly everything should be set to TransactionAttributeType.REQUIRED and TransactionManagementType.CONTAINER? so currently everything will be running in the same transaction (hence the need for the two phase commit?
Do I want to mark the #Timeout method as TransactionAttributeType.NOT_SUPPORTED or should I mark the DB method as TransactionAttributeType.REQUIRES_NEW or should I be handling this in a different way?
I have a service class like this.
#Service
public class ServiceAImpl implements ServiceA {
#Autowired
private ServiceARepository repo;
#Autowired
private Publisher publisher;
#Transactional
public String save(Model model) {
//entity list creation code goes here
List<EntityA> entityList = repo.save(entityList);
repo.flush();
...
//savedIdList is comma separated list of entityList EntityA.id
publisher.publish(savedIdList);
return responseObject.toString();
}
}
When controller call to this service its create the Entity list and save. After that its call to publish method in another class with the saved ids. This save method annotated with #Transactional.
#Service
public class Publisher {
#Autowired
private AsyncPublisher asyPublisher;
#Autowired
PublishedDataRepository repo;
public void publish(String savedIdList) throws Exception {
savePublishData(..., savedIdList);
}
#Transactional
private void savePublishData(..., String savedIdList) throws Exception {
SearchPublishedData publishData = new SearchPublishedData();
...
publishData.setIdList(savedIdList);
publishData = repo.saveAndFlush(publishData);
asyPublisher.callPublisher(..., savedIdList, publishData.getId());
}
}
In publisher class its save a record to the publisher table and again it call to the async publisher class. In this class there is a method with #Async and its implemented with ThreadPoolTaskExecutor. In this async method what it going to do is get the previously saved data from its ids using EntityManager native query.
This is a sample java class code. Actually in this native query there are few tables join with this previously saved table and getting the data.
#Service
public class AsyncPublisher {
#PersistenceContext
private EntityManager entityManager;
#Async("threadPoolTaskExecutor") //This is created as ThreadPoolTaskExecutor
public void callPublisher(..., String ids, Long savedId) {
try {
String query = getQuery(ids);
List<Object[]> results = entityManager.createNativeQuery(query).getResultList();
... ///Other codes goes here, but results is empty
} catch (Exception e) {
logg error
}
}
private String getQuery(String ids) throws Exception {
StringBuilder query = new StringBuilder();
query.append("SELECT * FROM EntityA_table WHERE id IN (").append(ids).append(" ) ");
//This is a sample query, actually in this query there are 2 or more tables joined
return query.toString();
}
}
My problem is when I retrieve data from EntityManager native query time to time its not getting the data. But when I check the database with those ids those data available in database.
Anyone can give me the reason for this.
I think this saving block is annotated with #Transactional and it going to commit data to the Database at the end of the method execution and but before it save to the database EntityManager native query execution happens in another thread and its execute before the data commit. Is this correct? If not please explain someone what is happening here.
Also is there any way to avoid this data not retrieve scenario?
Thank you.
I have a web services with too many method, before now I "test it" manually with soap, but now I want to do that with Junit and other framework to interact with database and use #EJB annotation.
The first example that I found, was to use DBunit and so I connected to the database and put a row into a table(and it works). But when I try to reuse this connection, and try to directly invoke my #Stateless method I have too many Error such NullPointer exception on the EJB or on the entity manager, so I tried a complet different logic and use Mockito, like this:
public class ReportBeanTest {
//This is my Stateless class
private ReportFc reportBean = new ReportFc();
#Before
public void injectMockEntityManager() throws Exception {
EntityManager entityManager = mock(EntityManager.class);
reportBean.emReport = entityManager;
DateFc dateF= mock(DateFc.class);
reportBean.dateF =dateF;
QuerysFc queryF= mock(QuerysFc .class);
reportBean.queryF =queryF;
reportBean.getReport("myReportA", new Date(), new Date());
}
}
And here my ReportFc.java :
#Stateless
public class ReportFc {
#PersistenceContext(unitName="myDb")
public
EntityManager emReport;
#EJB
public
DateFc dateF;
#EJB
public
QuerysFc queryF;
public List<MyList> getReport(String myReport,
Date from_date,
Date to_date
) throws WSException {
try{
List<WsMap_v3> resultList = new LinkedList<WsMap_v3>();
Date start= dataF.parserDateFormat(from_date,0,"noTime");
Date end= dataF.parserDateFormat(to_date,0,"noTime");
dateF.verifyTimeInterval(start,end);
Query qC=queryF.queryGetReportBetweenDate(start, end, myReportA);
...///
}
I have see that every variable that use external EJB is null, as in my case :
Date start, Date end, Query qC an so on.... What I am doing wrong? there is other way to test this function that use EJB or entitymanager?
I am using maven so if there is other framework to use I have no problem to import it.
Other thing: all my bean of my db are in jar that I import with maven dependecy
I'm currently having the issue that the #Transactional annotation doesn't seem to start a transaction for Neo4j, yet (it doesn't work with any of my #Transactional annotated methods, not just with the following example).
Example:
I have this method (UserService.createUser), which creates a user node in the Neo4j graph first and then creates the user (with additional information) in a MongoDB. (MongoDB doesn't support transactions, thus create the user-node first, then insert the entity into MongoDB and commit the Neo4j-transaction afterwards).
The method is annotated with #Transactional yet a org.neo4j.graphdb.NotInTransactionException is thrown when it comes to creating the user in Neo4j.
Here is about my configuration and coding, respectively:
Code based SDN-Neo4j configuration:
#Configuration
#EnableTransactionManagement // mode = proxy
#EnableNeo4jRepositories(basePackages = "graph.repository")
public class Neo4jConfig extends Neo4jConfiguration {
private static final String DB_PATH = "path_to.db";
private static final String CONFIG_PATH = "path_to.properties";
#Bean(destroyMethod = "shutdown")
public GraphDatabaseService graphDatabaseService() {
return new GraphDatabaseFactory().newEmbeddedDatabaseBuilder(DB_PATH)
.loadPropertiesFromFile(CONFIG_PATH).newGraphDatabase();
}
}
Service for creating the user in Neo4j and the MongoDB:
#Service
public class UserService {
#Inject
private UserMdbRepository mdbUserRepository; // MongoRepository
#Inject
private Neo4jTemplate neo4jTemplate;
#Transactional
public User createUser(User user) {
// Create the graph-node first, because if this fails the user
// shall not be created in the MongoDB
this.neo4jTemplate.save(user); // NotInTransactionException is thrown here
// Then create the MongoDB-user. This can't be rolled back, but
// if this fails, the Neo4j-modification shall be rolled back too
return this.mdbUserRepository.save(user);
}
...
}
Side-notes:
I'm using spring version 3.2.3.RELEASE and spring-data-neo4j version 2.3.0.M1
UserService and Neo4jConfig are in separate Maven artifacts
Starting the server and SDN reading operations work so far, I'm just having troubles with writing operations
I'm currently migrating our project from the tinkerpop-framework to SDN-Neo4j. This user creation-process has worked before (with tinkerpop), I just have to make it work again with SDN-Neo4j.
I'm running the application in Jetty
Does anyone have any clue why this is not working (yet)?
I hope, this information is sufficient. If anything is missing, please let me know and I'll add it.
Edit:
I forgot to mention that manual transaction-handling works, but of course I'd like to implement it the way "as it's meant to be".
public User createUser(User user) throws ServiceException {
Transaction tx = this.graphDatabaseService.beginTx();
try {
this.neo4jTemplate.save(user);
User persistantUser = this.mdbUserRepository.save(user);
tx.success();
return persistantUser;
} catch (Exception e) {
tx.failure();
throw new ServiceException(e);
} finally {
tx.finish();
}
}
Thanks to m-deinum I finally found the issue. The problem was that I scanned for those components / services in a different spring-configuration-file, than where I configured SDN-Neo4j. I moved the component-scan for those packages which might require transactions to my Neo4jConfig and now it works
#Configuration
#EnableTransactionManagement // mode = proxy
#EnableNeo4jRepositories(basePackages = "graph.repository")
#ComponentScan({
"graph.component",
"graph.service",
"core.service"
})
public class Neo4jConfig extends Neo4jConfiguration {
private static final String DB_PATH = "path_to.db";
private static final String CONFIG_PATH = "path_to.properties";
#Bean(destroyMethod = "shutdown")
public GraphDatabaseService graphDatabaseService() {
return new GraphDatabaseFactory().newEmbeddedDatabaseBuilder(DB_PATH)
.loadPropertiesFromFile(CONFIG_PATH).newGraphDatabase();
}
}
I still will have to separate those components / services which require transactions from those which don't, though. However, this works for now.
I assume that the issue was that the other spring-configuration-file (which included the component-scan) was loaded before Neo4jConfig, since neo4j:repositories has to be put before context:component-scan. (See Note in Example 20.26. Composing repositories http://static.springsource.org/spring-data/data-neo4j/docs/current/reference/html/programming-model.html#d0e2948)
I am making an updating native query within my Spring Data JPA Repository.
#Query(nativeQuery=true, value="update t_table set change = 0 where id = ?1")
#Modifying(clearAutomatically=false)
void disableChange(int id);
The value is updated in a correct way as I can see with my database client but next transactions are not recognizing the change until the server is redeployed.
My service looks like this:
#Service("my.service.class.service")
public final class MyServiceClassImpl implements MyServiceClass
{
#Autowired
private ClientRepository clientRepository;
#Override
#Secured("MY_ROLE")
#Transactional(propagation=Propagation.REQUIRES_NEW, rollbackFor=MyException.class)
public void myMethod() throws PlayTheGuruException
{
//
myMethod();
//
}
private void myMethod() throws MyException {
//
clientRepository.disableChange(22);
//
}
}
May I need to annotate myMethod with transactional and mandatory propagation or something like that?
Is the native query the problem?
This issue appears only with updating queries.
Looks like a stale value from L2 cache, if L2 cache is enabled for the entity in question.
Try to remove affected entity from L2 cache manually:
#Autowired EntityManagerFactory emf;
...
clientRepository.disableChange(22);
emf.getCache().evict(..., 22);