How can I create payment in jBilling programmatically from scheduled plugin? The problem is I want to create a payment which is not linked to any invoice, so I try to use
applyPayment(PaymentDTOEx payment, Integer invoiceId, Integer executorUserId)
with invoiceId=null, but it leads to an error:
org.hibernate.LazyInitializationException: could not initialize proxy - no Session
Initially I try:
IPaymentSessionBean psb = Context.getBean(Context.Name.PAYMENT_SESSION);
psb.applyPayment(new PaymentDTOEx(paymentWS), null, userID);
Later I added "userbl.webServicesAuthenticate(user, pass)" before, but result is the same.
I think I missed something important and maybe doing it completely wrong.
I've never used jBilling before, but after a bit of googling it seems like it uses Spring to manage transactions etc.
From the error you've quoted it looks like you don't have a Hibernate session open. If you were using a web framework (like Spring MVC, for example), the Hibernate session lifecycle is usually managed for you transparently using a servlet filter.
If you're executing a payment from a scheduled service, then you may need to open and close the Hibernate session yourself in your service. There's some documentation here that describes how to do this programmatically using Spring.
Also take a look at the #Transactional annotation. It might be as simple as annotating your scheduled job method with this.
Thanks to rcgeorge23!
The problem was there were no active Hibernate session opened. Here is working code:
IPaymentSessionBean psb = Context.getBean(Context.Name.PAYMENT_SESSION);
//transaction manager is available in jBilling like that:
PlatformTransactionManager txManager = Context.getBean(Context.Name.TRANSACTION_MANAGER);
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
def.setName("CreatePaymentTransaction");
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED); //not sure which strategy is best in this case
TransactionStatus status = txManager.getTransaction(def);
String ret;
try {
ret =Integer.toString(psb.applyPayment(new PaymentDTOEx(paymentWS), null, userID));
}
catch (Exception ex) {
txManager.rollback(status);
throw ex;
}
txManager.commit(status);
You can also create plug-in for user.
for example when user will created or added then the default amount should be paid.
for that you have to write a plug-in and it will occure when user will created.
Related
I have a Spring Boot webapp connected to a Postgres 9.6 database.
I use Spring's JdbcTemplate for executing SQL statements.
Each table in my database has triggers for INSERT, CREATE and DELETE statments. These triggers copy the affected rows into a history table.
I want the triggers to also save the application user ID of the user who made the change.
According to https://stackoverflow.com/a/13172964/2591231 I can achieve my goal by having the application insert the current user id into a temporary table at the start of each transaction and having the triggers read from the temporary table.
A similar method, mentioned in several other places, is executing:
SET LOCAL application_name = "my_application_user", then reading application_name inside the triggers. Again, this has to be done at the start of each transaction.
I'm looking for way, which is orthogonal to business code (I don't want each DAO to explicitly set user ID), to hook into the start of each transaction in order to run a specific SQL statement before any other statement in the same transaction.
I need this to work for both implicit transactions (single invocations of JdbcTemplate) and transactions demarcated declaratively with Spring's #Transactional annotation.
First of all, JdbcTemplate does not provide transaction support out-of-the-box (see here). So, in order to intercept all #Transaction annotated code AND every call to JdbcTemplate, this could be done at DataSource level, as commented earlier by Serge Bogatyrev.
I have a Spring Web project where I tested this approach. I defined a replacement DataSource #Bean called MyDataSource that extends BasicDataSource, and overwrites its getConnection() method so that it creates the temp table and insert the user_id before returning the connection.
It worked for #Transaction calls and pure JdbcTemplate calls.
If you want to strictly tie this temp table update at the start of each transaction, do this same strategy for defining the PlatformTransactionManager #Bean. You only need to overwrite the doBegin() method. And don't forget to annotate with #Transaction all methods calling JdbcTemplate.
PS1: Make sure to call DROP TABLE IF EXISTS temp_table_name prior creating the temp table, in order to replace the DISCARD ALL on connection returning to pool, as mentioned here.
PS2: This whole solution of creating a temp table doesn't smell well. I wouldn't implement it myself. I would prefer to take a deep breath and add created_by and updated_by columns to all my tables.
You can take advantage of Spring AOP for setting up the user. The aspect will make a call to the database to set up the application user.
In my example, a stored procedure is used to set up the application user responsible for creating, modifying, or deleting a record . You can customize it according to your requirements. Here is the example aspect which retrieves the user from the HTTP request and then makes a call to the stored procedure,
#Component
#Aspect
#Slf4j
public class SetUserAspect {
private final JdbcTemplate jdbcTemplate;
#Autowired
public SetUserAspect(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
#Before("execution(* com.basaki.example.service.BookService.*(..) )")
public void setUser(JoinPoint jp) {
log.info("In class: " + jp.getSignature().getDeclaringTypeName() +
" - before method: " + jp.getSignature().getName());
HttpServletRequest request =
((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
if (request != null) {
String user = request.getHeader("user");
if (user != null) {
log.info("Setting user " + user);
SimpleJdbcCall
jdbcCall = new SimpleJdbcCall(jdbcTemplate)
.withSchemaName("example_book_schema")
.withFunctionName("set_user");
SqlParameterSource
in =
new MapSqlParameterSource().addValue("audit_user",
user);
jdbcCall.executeFunction(String.class, in);
}
}
}
}
All the CRUD operations are performed in BookService, essentially a DAO.
Here is the stored procedure used for setting up the user,
CREATE OR REPLACE FUNCTION example_book_schema.set_user(
audit_user TEXT
) RETURNS BOOLEAN STABLE LANGUAGE SQL AS $$
SELECT set_config('book.audit_user', audit_user, true);
SELECT TRUE;
Restricting Pointcuts to Only Transactional Methods
You can restrict the points cuts to only transactional methods in BookService by adding an additional clause in the Before advice.
#Before("execution(* com.basaki.example.service.BookService.*(..) ) " +
"&& #annotation(annotation)")
public void setUser(final JoinPoint jp, final Transactional annotation) {
...
}
You can use #EntityListeners to listen change of entity in application context, then collect whatever information (entity value, authentication user, etc...) and then insert to your history table. Example you can follow here: http://www.baeldung.com/database-auditing-jpa
You can create view, add user id column, and use your triggers to deal with updates. So that is yet another way to code it at DB side. That way you are supposed to pass it every time, so no other changes are needed.
Going to Java/Spring side.
A bit oldish style: TransactionTemplate - that way you have full control, but your dao needs more code, since transaction management needs to be done there.
Other option is to create proxy on
org.springframework.jdbc.datasource.DataSourceTransactionManager and do your job at doBegin, then your proxy needs to be passed to transaction manager. And that is the way to go for me.
I'm creating a hibernate Session and try to start a new [Jta]Transaction. Though, the transaction cannot be started because the JtaTransaction that is used in the background seems to be rolled back.
Here is what I'm doing.
Session session = sessionFactory.openSession();
CustomSessionWrapper dpSession = new CustomSessionWrapper(session, this);
if (!session.isClosed() && !session.getTransaction().isActive()) {
session.beginTransaction();
}
Nevertheless the transaction is still not active after the beginTransaction is called. When I debug the beginTransaction method I come to the doBegin method of the JtaTransaction (I do not override this method, I'm just posting the original code of this method).
#Override
protected void doBegin() {
LOG.debug( "begin" );
userTransaction = locateUserTransaction();
try {
if ( userTransaction.getStatus() == Status.STATUS_NO_TRANSACTION ) {
userTransaction.begin();
isInitiator = true;
LOG.debug( "Began a new JTA transaction" );
}
}
catch ( Exception e ) {
throw new TransactionException( "JTA transaction begin failed", e );
}
}
The userTransaction.getStatus() returns Status.STATUS_ROLLEDBACK and no transaction is started. Does anyone know how I can fix that?
UPDATE 1 (you can skip that since that was a mistake, see UPDATE 2)
I found out that there are two threads, one using the main session and another using smaller sessions for logging. The main session (and transaction) is open for a longer period of time, so basically until the operation is finished. It seems that locateUserTransaction always returns the same userTransaction. This means that the main session opens this userTransaction and one of the side transactions commit/rollback that transaction. Does anyone know what to do so that different transactions are retrieved?
UPDATE 2
I found out that I don't have two threads, it is only one threads that opens two sessions in parallel. Each session should then open their own transaction, though both get the same UserTransaction. How can I tell hibernate that each session should get its own [User]Transaction?
Hibernate abstracts both local as JTA transactions behind its own abstraction layer, so I don't see why you'd have to write such low level transaction handling code.
In Java EE you have the app server to manage transactions, in stand alone apps Bitronix + Spring do a job too.
Although you can manage to write your own transaction management logic, I always advice people to reuse what they have already available. Xa/JTA and Hibernate require extensive knowledge to work seamlessly.
Update 1
Two different threads shouldn't use the same user transaction, you should use different transactions for each thread.
I am using Jackrabbit with datastore and a separate database for the rest of my data. I have deployed Jackrabbit JCA to JBoss 7.1.1. I have debugged the application and I see that the session instance is of type XASessionImpl.
I am currently getting a session like this:
final Credentials credentials = new SimpleCredentials("admin", "admin".toCharArray());
try {
final Session session = repository.login(credentials);
return session;
} catch (RepositoryException e) {
throw new RuntimeException(e);
}
I invoke session.save(); and then session.logout() when I am done each time I access it. Is this correct when it is part of a global transaction. I do not have much knowledge about distributed transactions etc so please correct me if I am wrong. I tried to throw a runtime exception inside one of my methods that is annotated with #Transactional (using Spring 3.2), but the data in the datastore is not removed. Is this correct? Doesn't data that is being added in the data store removed if the transaction is rolled back? My "testing" enviroment for this was: add content to Jackrabbit, then to database and then throw runtime exception. Or isn't Jackrabbit configured correctly?
Jackrabbit is probably running its own transaction, assuming the Spring-managed transaction is rolled back but the content in the datastore remains. How does your Spring/JBoss resource configuration look like?
Some quick Googling (with keywords JTA Jackrabbit Spring JBoss) reveals that setting up XA transactions with Jackrabbit and an XA JDBC DataSource might be easier said than done. Old mailing list entries report being able to use a JTA transaction manager called Jencks to do this, but Jencks' development appears since to have been discontinued.
Also have a look (though with a grain of salt) at section 1.2.3 in this JBoss community wiki page that states that "jackrabbit implements the XA protocol internally and requires a non-XA datasource underneath", which implies the behavior you're seeing.
Also, as an option to XA, have you considered emulating XA like this (mind the pseudo-code)?:
#Transactional
public void addContent() {
try {
storeContentInJcrRepo();
saveMetadataInDatabase();
catch (DataAccessException e) {
deleteNewlyStoredContentFromJcrRepo();
// Rethrow to ensure DB transaction is rolled back
throw e;
}
}
I'm currently working on a java application. It's a standalone client with Spring and Hibernate. Also C3P0.
In the previous version we used a standard user(hardcoded in the configuration file) for the database connection but now we changed it so that every user has to provide his own credentials.
The beans with the code for the database are basically created on-demand.
I changed the XML-files and added a postprocessor which sets the credentials as well as some connection settings. It looks similar to this now:
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext();
configurer = new PropertyPlaceholderConfigurer();
// properties are retrieved from a private method
configurer.setProperties(getProperties());
context.addBeanFactoryPostProcessor(configurer);
context.setConfigLocations(new String[] { "first.xml","second.xml" });
context.refresh();
return context.getBean("myClass", MyClass.class);
This all works as expected but now we reach the part where I'm currently stuck.
I want to provide a test functionality for the connection, so that the user can click a button and then is told if his credentials were accepted or not.
My first idea was to do a simple select on the database. Sifting through the logs however, I noticed that Spring tries to connect to the database during the refresh() (or rather the instantiation of the bean) anyway. I can see exceptions in the logs, for example: java.sql.SQLException: Connections could not be acquired from the underlying database!
Unfortunately, Spring doesn't seem to actually care. The exceptions are logged away but refresh() finishes and is not throwing any exceptions because of this. I had hoped that I could simply catch the exception and then I would know that the connection failed.
I could just do the select as planned, but I want to limit the connection attempts as much as possible, because the database server will block the user after several attempts. Even permanently if there are to many attempts(already had some fun with that, before I changed the settings for the connection pool).
My searches regarding this problem came up with practically nothing. Is there a way to get the exception somehow? Or does Spring provide an API of sorts that would tell me about the connection error during the instantiation/refresh?
Failing that, any ideas for an alternative approach? Preferably one that needs only a single attempt to determine if a connection is possible.
Edit: For anyone interested: I went with the suggestion from Santosh and implemented a connection test in JDBC.
Unfortunately there seems to be no easy way to make use of the database errors/exceptions encountered during the bean instantiation.
The kind of functionality you are looking for would be very tricky to accomplish using spring+hibernate.
The connection properties are set at the session-factory level and if credentials are incorrect, the session-factory is not instantiated.
Quoting #Bozo from his answer here.
What you can do is extend LocalSessionFactoryBean and override the
getObject() method, and make it return a proxy (via
java.lang.reflect.Proxy or CGLIB / javassist), in case the
sessionFactory is null. That way a SessionFactory will be injected.
The proxy should hold a reference to a bare SessionFactory, which
would initially be null. Whenever the proxy is asked to connect, if
the sessionFacotry is still null, you call the buildSessionFactory()
(of the LocalSessionFactoryBean) and delegate to it. Otherwise throw
an exception. (Then of course map your new factory bean instead of the
current)
There is also a simple and rudimentary approach wherein before creating ClassPathXmlApplicationContext, simply try to obtain a connection using raw JDBC calls. If that succeed then proceed or else give use appropriate message.
You can limit the connection attempts here as you are in full control.
I've set up a Spring ROO application, set persistence to OpenJPA and created some entities.
Then I replaced Spring MVC with Apache Wicket. Stuff seems to be working fine and I've successfully displayed a list of Customer entities.
Next up was the editing view for the customer. For now I've made a Wicket form that uses the OpenJPA entity directly as the form model, and thus I had to make the entity class implement Serializable.
Now, I'm not sure how to correctly implement the OpenJPA persistence, what I've got now is this:
#Override
protected void onSubmit() {
try {
if (customer.getId()!=null) {
customer.merge();
}
else {
customer.persist();
}
}
catch (Exception e) {
throw new Error(e);
}
super.onSubmit();
}
That works, but only once per Customer object. Somehow.
That is, I submit my form once and it works both with a new customer (.persist()) and a existing customer (.merge()). However, I submit the form again for the same customer I get this error (I added some linebreaks here):
<openjpa-2.0.0-r422266:935683 nonfatal store error>
org.apache.openjpa.persistence.OptimisticLockException:
An optimistic lock violation was detected when flushing object instance "no.magge.iumb.domain.crm.PrivateCustomer-379" to the data store.
This indicates that the object was concurrently modified in another transaction.
My question is, what is the correct way to persist with OpenJPA and why am I getting that error ?
Wicket-wise: Should I have created a separate Wicket IModel with a detachable Customer model and could that be the reason that I have these problems?
Thanks a bunch for any advice!
Do yourself a favor and separate your application layers. Code in a view should not ever access a Database.
Create a Service layer and / or a Dao layer, unit test the code of those layers to see that they are working and then inject a dao or service object into the wicket component. (I'd recommend you to use spring for that, but you can also do it manually)
With your scenario, there are so many different things that can fail in one spot, and it's nearly impossible to separate them.
Here are some pointers:
Dao (J2ee patterns)
Business logic (wikipedia)
Wicket / Spring / Hibernate
Configuration (it's very similar for JPA)
JPA using Spring