How to add synchronization to Atomikos TransactionStateHandler - atomikos

How I can add synchronization to TransactionStateHandler in atomikos ? Default this contains just JdbcRequeueSynchronization which got empty beforeCompletion method
private Throwable notifyBeforeCompletion() {
Throwable cause = null;
Synchronization sync = localPopSynchronization();
while ( sync != null ) {
try {
sync.beforeCompletion ();
} catch ( RuntimeException error ) {
// see case 24246: rollback only
setRollbackOnly();
// see case 115604
// transport the first exception here as return value
if (cause == null) {
cause = error;
} else {
// log the others which may still happen as error - cf. case 115604
LOGGER.logError("Unexpected error in beforeCompletion: ", error);
}
}
sync = localPopSynchronization();
}
return cause;
}

You can do this via the Transaction object (in the JTA API):
UserTransactionManager utm = new UserTransactionManager();
utm.begin(); //optional, skip if you already have a transaction
Transaction tx = utm.getTransaction();
tx.registerSynchronization(...);
...
//commit / rollback per your requirements
Hope that helps
Guy

Related

Exception being thrown and returning status code instead

Regardless of what I do my check for when there is an exception isn't be handled. It's just being thrown in my test. I want to simulate an exception happening during the Db call and to return a 500 status code.
Given("given a db exception return Error 500") {
val expectedException = "Exception while looking up in email opt DB"
every { IDRepo.findById(any()) } throws RuntimeException(expectedException)
When("process db exception") {
val response = IDService.lookupIDValue(testEmail)
then("response server error")
response.statusCode shouldBe HttpStatus.INTERNAL_SERVER_ERROR
}
}
fun lookupIDValue(email: String): ResponseEntity<String> {
Failures.failsafeRun {
IDRepo.findById(email)
}
val IDLookupResult = IDRepo.findById(email)
return when {
IDResult == Exception() -> {
ResponseEntity("Server Error", HttpStatus.INTERNAL_SERVER_ERROR)
}
IDResult.isPresent -> {
ResponseEntity(IDResult.get().optValue.toString(), HttpStatus.OK)
}
else -> {
ResponseEntity(HttpStatus.NO_CONTENT)
}
}
}
I think, there are two issues with your code.
The first one is IDResult == Exception() as #Tenfour04 said.
The second is mockk is throwing an exception without entering code block.
IDResult == Exception() -> {
ResponseEntity("Server Er...
Without knowing about deeply your code, you should try the code below. Because you are testing the behaviour of IDRepo.findById(email) which should return a result of failure.
every { IDRepo.findById(any()) } returns Result.failure(RuntimeException(expectedException)))
Hope, it helps you.

How to make inner transaction rolled back, when the outer transaction failed

I want to create a method thats called createTransaction that will commit the transaction if its success, but roll back all the transaction in some table if its failed. On the other side, I want to save the transaction log into db even if its failed or succeed.
I’ve tried this code, but when I try enter a customerId thats not saved in db, the transaction should be rolled back the transaction, product, and customer entity, but It still commit the transaction in product table. Can someone explain me whats going on and give me the solution for this?
public String createTransactionWithLog(TR_Transaction transaction) {
String message = "";
try {
boolean successTransaction = createTransaction(transaction);
if(successTransaction == true) {
message = "Transaksi sukses";
}else {
message = "Transaksi gagal";
}
}catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}finally {
Activity_Log log = new Activity_Log(LocalDateTime.now(), "DoTransaction", message);
activityLogRepository.save(log);
}
return message;
}
#Transactional
public boolean createTransaction(TR_Transaction transaction) {
long productId = transaction.getProductId();
long customerId = transaction.getCustomer().getCustomerId();
MS_Product product = productRepository.getOne(productId);
MS_Customer customer = customerRepository.getOne(customerId);
if(product == null || customer == null) {
return false;
}else {
transaction.setCustomer(customer);
int newProductStock = product.getProductStock() - transaction.getQuantity();
product.setProductStock(newProductStock);
transaction.setProductPrice(newProductStock);
customer.getTransactions().add(transaction);
TR_Transaction savedTransaction = transactionRepository.save(transaction);
MS_Customer updatedCustomer = customerRepository.save(customer);
MS_Product updatedProduct = productRepository.save(product);
return true;
}
}

Implement `Process.waitFor(long timeout, TimeUnit unit)` in Java 6

I am working on a legacy (Java 6/7) project that uses ProcessBuilder to request a UUID from the machine in an OS-agnostic way. I would like to use the Process.waitFor(long timeout, TimeUnit unit) method from Java 8, but this isn't implemented in Java 6. Instead, I can use waitFor(), which blocks until completion or an error.
I would like to avoid upgrading the version of Java used to 8 if possible as this necessitates a lot of other changes (migrating code away from removed internal APIs and upgrading a production Tomcat server, for example).
How can I best implement the code for executing the process, with a timeout? I was thinking of somehow implementing a schedule that checks if the process is still running and cancelling/destroying it if it is and the timeout has been reached.
My current (Java 8) code looks like this:
/** USE WMIC on Windows */
private static String getSystemProductUUID() {
String uuid = null;
String line;
List<String> cmd = new ArrayList<String>() {{
add("WMIC.exe"); add("csproduct"); add("get"); add("UUID");
}};
BufferedReader br = null;
Process p = null;
SimpleLogger.debug("Attempting to retrieve Windows System UUID through WMIC ...");
try {
ProcessBuilder pb = new ProcessBuilder().directory(getExecDir());
p = pb.command(cmd).start();
if (!p.waitFor(TIMEOUT, SECONDS)) { // No timeout in Java 6
throw new IOException("Timeout reached while waiting for UUID from WMIC!");
}
br = new BufferedReader(new InputStreamReader(p.getInputStream()));
while ((line = br.readLine()) != null) {
if (null != line) {
line = line.replace("\t", "").replace(" ", "");
if (!line.isEmpty() && !line.equalsIgnoreCase("UUID")) {
uuid = line.replace("-", "");
}
}
}
} catch (IOException | InterruptedException ex) {
uuid = null;
SimpleLogger.error(
"Failed to retrieve machine UUID from WMIC!" + SimpleLogger.getPrependedStackTrace(ex)
);
// ex.printStackTrace(System.err);
} finally {
if (null != br) {
try {
br.close();
} catch (IOException ex) {
SimpleLogger.warn(
"Failed to close buffered reader while retrieving machine UUID!"
);
}
if (null != p) {
p.destroy();
}
}
}
return uuid;
}
You can use the following code which only uses features available under Java 6:
public static boolean waitFor(Process p, long t, TimeUnit u) {
ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor();
final AtomicReference<Thread> me = new AtomicReference<Thread>(Thread.currentThread());
ScheduledFuture<?> f = ses.schedule(new Runnable() {
#Override public void run() {
Thread t = me.getAndSet(null);
if(t != null) {
t.interrupt();
me.set(t);
}
}
}, t, u);
try {
p.waitFor();
return true;
}
catch(InterruptedException ex) {
return false;
}
finally {
f.cancel(true);
ses.shutdown();
// ensure that the caller doesn't get a spurious interrupt in case of bad timing
while(!me.compareAndSet(Thread.currentThread(), null)) Thread.yield();
Thread.interrupted();
}
}
Note that unlike other solutions you can find somewhere, this will perform the Process.waitFor() call within the caller’s thread, which is what you would expect when looking at the application with a monitoring tool. It also helps the performance for short running sub-processes, as the caller thread will not do much more than the Process.waitFor(), i.e. does not need to wait for the completion of background threads. Instead, what will happen in the background thead, is the interruption of the initiating thread if the timeout elapsed.

How to update a record using nhibernate

Hi i am working in MVC3 and for database communication i am using NHIBERNATE
I am getting a problem in updating a record.
Firstly session.SaveorUpdate does not work
Then i tried the following thing but this also does not work:(
public bool EditParentStudent(ParentStudent parentstudent)
{
log.Debug("Start");
if (parentstudent == null)
{
throw new ArgumentNullException("parentstudent");
}
ISession session = DataAccessLayerHelper.OpenWriterSession();
ITransaction transaction = session.BeginTransaction();
bool saved = false;
try
{
session.SaveOrUpdate(parentstudent);
transaction.Commit();
saved = true;
}
catch (SessionException ex)
{
if (transaction != null && transaction.IsActive)
transaction.Rollback();
log.Error(ex);
}
finally
{
if (transaction != null)
transaction.Dispose();
if (session != null && session.IsConnected)
session.Close();
}
log.Debug("End");
return saved;
}
If your entity is persistent you don't need to update it explicitly.
using (var session = sessionFactory.OpenSesion())
using (var tx = session.BeginTransaction())
{
// perform your insert here
tx.Commit();
}
Assuming that your mapping is ok, if you are using mvc3 then you should put code inside controller, for example
public ActionResult Edit(ParentStudent parentstudent)
{
//open session
// open transaction
//found existing data
var data = session.Query<ParentStudent>().Where(x=>x.Id == parentstudent.Id).FirstOrDefault();
session.SaveOrUpdate(data);
transaction.Commit();
//close transaction
//close session
return View();
}
maybe is better to put this code inside try catch block and to catch possible exception, but I was trying to make it simple as possible.
Hope this helps.

OWSM custom security policy for JAX-WS, GenericFault

I tried creating custom security and policy as given here:
http://download.oracle.com/docs/cd/E15523_01/relnotes.1111/e10132/owsm.htm#CIADFGGC
when I run the service client custom assertion is executed, returning successfully.
public IResult execute(IContext context) throws WSMException {
try {
System.out.println("public execute");
IAssertionBindings bindings =
((SimpleAssertion)(this.assertion)).getBindings();
IConfig config = bindings.getConfigs().get(0);
IPropertySet propertyset = config.getPropertySets().get(0);
String valid_ips =
propertyset.getPropertyByName("valid_ips").getValue();
String ipAddr = ((IMessageContext)context).getRemoteAddr();
IResult result = new Result();
System.out.println("valid_ips "+valid_ips);
if (valid_ips != null && valid_ips.trim().length() > 0) {
String[] valid_ips_array = valid_ips.split(",");
boolean isPresent = false;
for (String valid_ip : valid_ips_array) {
if (ipAddr.equals(valid_ip.trim())) {
isPresent = true;
}
}
System.out.println("isPresent "+isPresent);
if (isPresent) {
result.setStatus(IResult.SUCCEEDED);
} else {
result.setStatus(IResult.FAILED);
result.setFault(new WSMException(WSMException.FAULT_FAILED_CHECK));
}
} else {
result.setStatus(IResult.SUCCEEDED);
}
System.out.println("result "+result);
System.out.println("public execute complete");
return result;
} catch (Exception e) {
System.out.println("Exception e");
e.printStackTrace();
throw new WSMException(WSMException.FAULT_FAILED_CHECK, e);
}
}
Console output is:
public execute valid_ips
127.0.0.1,192.168.1.1 isPresent true result Succeeded public execute
complete
but, webservice throws GenericFault .
Arguments: [void]
Fault: GenericFault : generic error
I have no clue what could be wrong, any ideas?
here is the full stack trace:
Exception in thread "main"
javax.xml.ws.soap.SOAPFaultException:
GenericFault : generic error at
com.sun.xml.internal.ws.fault.SOAP12Fault.getProtocolException(SOAP12Fault.java:210)
at
com.sun.xml.internal.ws.fault.SOAPFaultBuilder.createException(SOAPFaultBuilder.java:119)
at
com.sun.xml.internal.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:108)
at
com.sun.xml.internal.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:78)
at
com.sun.xml.internal.ws.client.sei.SEIStub.invoke(SEIStub.java:107)
at $Proxy30.sayHello(Unknown Source)
at
creditproxy.CreditRatingSoap12HttpPortClient.main(CreditRatingSoap12HttpPortClient.java:21)
Caused by:
javax.xml.ws.soap.SOAPFaultException:
GenericFault : generic error at
weblogic.wsee.jaxws.framework.jaxrpc.TubeFactory$JAXRPCTube.processRequest(TubeFactory.java:203)
at
weblogic.wsee.jaxws.tubeline.FlowControlTube.processRequest(FlowControlTube.java:99)
at
com.sun.xml.ws.api.pipe.Fiber.__doRun(Fiber.java:604)
at
com.sun.xml.ws.api.pipe.Fiber._doRun(Fiber.java:563)
at
com.sun.xml.ws.api.pipe.Fiber.doRun(Fiber.java:548)
at
com.sun.xml.ws.api.pipe.Fiber.runSync(Fiber.java:445)
at
com.sun.xml.ws.server.WSEndpointImpl$2.process(WSEndpointImpl.java:275)
at
com.sun.xml.ws.transport.http.HttpAdapter$HttpToolkit.handle(HttpAdapter.java:454)
at
com.sun.xml.ws.transport.http.HttpAdapter.handle(HttpAdapter.java:250)
at
com.sun.xml.ws.transport.http.servlet.ServletAdapter.handle(ServletAdapter.java:140)
at
weblogic.wsee.jaxws.HttpServletAdapter$AuthorizedInvoke.run(HttpServletAdapter.java:319)
at
weblogic.wsee.jaxws.HttpServletAdapter.post(HttpServletAdapter.java:232)
at
weblogic.wsee.jaxws.JAXWSServlet.doPost(JAXWSServlet.java:310)
at
javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
at
weblogic.wsee.jaxws.JAXWSServlet.service(JAXWSServlet.java:87)
at
javax.servlet.http.HttpServlet.service(HttpServlet.java:820)
at
weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:227)
at
weblogic.servlet.internal.StubSecurityHelper.invokeServlet(StubSecurityHelper.java:125)
at
weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:292)
at
weblogic.servlet.internal.TailFilter.doFilter(TailFilter.java:26)
at
weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:56)
at
oracle.dms.wls.DMSServletFilter.doFilter(DMSServletFilter.java:326)
at
weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:56)
at
weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.run(WebAppServletContext.java:3592)
at
weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:321)
at
weblogic.security.service.SecurityManager.runAs(SecurityManager.java:121)
at
weblogic.servlet.internal.WebAppServletContext.securedExecute(WebAppServletContext.java:2202)
at
weblogic.servlet.internal.WebAppServletContext.execute(WebAppServletContext.java:2108)
at
weblogic.servlet.internal.ServletRequestImpl.run(ServletRequestImpl.java:1432)
at
weblogic.work.ExecuteThread.execute(ExecuteThread.java:201)
at
weblogic.work.ExecuteThread.run(ExecuteThread.java:173)
Process exited with exit code 1.
I had the same problem but they have a solution on Metalink (if you not already seen it). This will fix the problem:
public IResult execute(IContext context) throws WSMException {
IResult result = new Result();
try {
oracle.wsm.common.sdk.IMessageContext.STAGE stage = ((oracle.wsm.common.sdk.IMessageContext)context).getStage();
if (stage == IMessageContext.STAGE.request) {
javax.security.auth.Subject subject = oracle.security.jps.util.SubjectUtil.getAnonymousSubject();
context.setProperty(oracle.wsm.common.sdk.IMessageContext.SECURITY_SUBJECT, subject);
IAssertionBindings bindings = ((SimpleAssertion)(this.assertion)).getBindings();
IConfig config = bindings.getConfigs().get(0);
IPropertySet propertyset = config.getPropertySets().get(0);
String valid_ips = propertyset.getPropertyByName("valid_ips").getValue();
String ipAddr = ((IMessageContext)context).getRemoteAddr();
if (valid_ips != null && valid_ips.trim().length() > 0) {
String[] valid_ips_array = valid_ips.split(",");
boolean isPresent = false;
for (String valid_ip : valid_ips_array) {
if (ipAddr.equals(valid_ip.trim())) {
isPresent = true;
}
}
if (isPresent) {
result.setStatus(IResult.SUCCEEDED);
} else {
result.setStatus(IResult.FAILED);
result.setFault(new WSMException(WSMException.FAULT_FAILED_CHECK));
}
} else {
result.setStatus(IResult.SUCCEEDED);
}
return result;
}
} catch (Exception e) {
throw new WSMException(WSMException.FAULT_FAILED_CHECK, e);
}
return result;
}
I've met the same issue. Looking deeper in the wls classes i've found that WSMMessageContext does not contain right principal in the Subject. and in fact IllegalArgumentExeception is thrown, unfortunately this real exception is wrapped wrapped and wrapped a lot of times and we may see "GenericFault : generic error" that is the last wrapped in WSMAgentHook class that performs output in console. Unfortunately I could not move forward there and seems nobody use Custom Security Assert. So nobody may help us seems
result.setFault(null);
where you are setting status to success. It uses the fault value regardless of the setting of the status.

Resources