[jboss-jira] [JBoss JIRA] (JBRULES-3687) Provide detailed context information for java.lang.NullPointerException at org.drools.reteoo.RightTuple.unlinkFromRightParent(RightTuple.java:70)

Hendy Irawan (JIRA) jira-events at lists.jboss.org
Sat Nov 17 00:48:21 EST 2012


     [ https://issues.jboss.org/browse/JBRULES-3687?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Hendy Irawan updated JBRULES-3687:
----------------------------------

    Description: 
We're using Drools 5.5.0 in OSGi with: Karaf 2.3.0, Pax Wicket 1.1.1.

We experience several issues and this is one of them. Even if a fix is not in sight, I'd appreciate if a null check with more detailed information can be provided at the exception point, which will be helpful for us to diagnose and for future bug report to Drools team.

Stack:

{code}
java.lang.NullPointerException
     at org.drools.reteoo.RightTuple.unlinkFromRightParent(RightTuple.java:70)
     at org.drools.reteoo.FromNode.unlinkCreatedHandles(FromNode.java:393)
     at org.drools.reteoo.FromNode.retractLeftTuple(FromNode.java:379)
     at org.drools.reteoo.ObjectTypeNode.retractObject(ObjectTypeNode.java:290)
     at org.drools.reteoo.EntryPointNode.retractObject(EntryPointNode.java:354)
     at org.drools.common.NamedEntryPoint.retract(NamedEntryPoint.java:568)
     at org.drools.common.AbstractWorkingMemory.retract(AbstractWorkingMemory.java:936)
     at org.drools.common.AbstractWorkingMemory.retract(AbstractWorkingMemory.java:924)
     at org.drools.impl.StatefulKnowledgeSessionImpl.retract(StatefulKnowledgeSessionImpl.java:273)
     at id.co.bippo.booking.BookingCheckRulesImpl.processBookings(BookingCheckRulesImpl.java:185)
     at id.co.bippo.booking.BookingCheckRulesImpl.processFacts(BookingCheckRulesImpl.java:195)
     at id.co.bippo.booking.BookingCheckRulesImpl.check(BookingCheckRulesImpl.java:147)
     at id.co.bippo.booking.web.ProductBookingPanel.<init>(ProductBookingPanel.java:47)
     at java.lang.reflect.Constructor.newInstance(Constructor.java:525)
     at org.soluvas.web.site.compose.impl.LiveChildContributorImpl$1.create(LiveChildContributorImpl.java:187)
     at org.soluvas.web.site.compose.ComposeUtils.compose(ComposeUtils.java:68)
     at org.soluvas.web.bootstrap.BootstrapPage.onInitialize(BootstrapPage.java:302)
     at org.apache.wicket.Component.fireInitialize(Component.java:933)
     at org.apache.wicket.MarkupContainer.internalInitialize(MarkupContainer.java:960)
     at org.apache.wicket.Page.internalPrepareForRender(Page.java:277)
     at org.apache.wicket.Component.render(Component.java:2313)
     at org.apache.wicket.Page.renderPage(Page.java:1035)
     at org.apache.wicket.request.handler.render.WebPageRenderer.renderPage(WebPageRenderer.java:115)
     at org.apache.wicket.request.handler.render.WebPageRenderer.respond(WebPageRenderer.java:237)
     at org.apache.wicket.request.handler.RenderPageRequestHandler.respond(RenderPageRequestHandler.java:167)
     at org.apache.wicket.request.cycle.RequestCycle$HandlerExecutor.respond(RequestCycle.java:784)
     at org.apache.wicket.request.RequestHandlerStack.execute(RequestHandlerStack.java:64)
     at org.apache.wicket.request.cycle.RequestCycle.execute(RequestCycle.java:255)
     at org.apache.wicket.request.cycle.RequestCycle.processRequest(RequestCycle.java:212)
     at org.apache.wicket.request.cycle.RequestCycle.processRequestAndDetach(RequestCycle.java:283)
     at org.apache.wicket.protocol.http.WicketFilter.processRequest(WicketFilter.java:188)
     at org.apache.wicket.protocol.http.WicketServlet.doGet(WicketServlet.java:137)
     at javax.servlet.http.HttpServlet.service(HttpServlet.java:693)
     at javax.servlet.http.HttpServlet.service(HttpServlet.java:806)
     at org.ops4j.pax.wicket.internal.FilterDelegator$Chain.doFilter(FilterDelegator.java:79)
     at org.apache.shiro.web.servlet.AbstractShiroFilter.executeChain(AbstractShiroFilter.java:449)
     at org.apache.shiro.web.servlet.AbstractShiroFilter$1.call(AbstractShiroFilter.java:365)
     at org.apache.shiro.subject.support.SubjectCallable.doCall(SubjectCallable.java:90)
     at org.apache.shiro.subject.support.SubjectCallable.call(SubjectCallable.java:83)
     at org.apache.shiro.subject.support.DelegatingSubject.execute(DelegatingSubject.java:383)
     at org.apache.shiro.web.servlet.AbstractShiroFilter.doFilterInternal(AbstractShiroFilter.java:362)
     at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125)
     at org.ops4j.pax.wicket.internal.FilterDelegator$Chain.doFilter(FilterDelegator.java:77)
     at org.ops4j.pax.wicket.internal.FilterDelegator.doFilter(FilterDelegator.java:61)
     at org.ops4j.pax.wicket.internal.ServletProxy$ServletInvocationHandler.invoke(ServletProxy.java:72)
     at $Proxy80.service(Unknown Source)
     at java.lang.reflect.Method.invoke(Method.java:601)
     at org.ops4j.pax.web.service.internal.HttpServiceStarted$2.invoke(HttpServiceStarted.java:210)
     at org.ops4j.pax.web.service.internal.$Proxy0.service(Unknown Source)
     at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:652)
     at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:447)
     at org.ops4j.pax.web.service.jetty.internal.HttpServiceServletHandler.doHandle(HttpServiceServletHandler.java:70)
     at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:137)
     at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:559)
     at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:227)
     at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1038)
     at org.ops4j.pax.web.service.jetty.internal.HttpServiceContext.doHandle(HttpServiceContext.java:117)
     at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:374)
     at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:189)
     at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:972)
     at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:135)
     at org.ops4j.pax.web.service.jetty.internal.JettyServerHandlerCollection.handle(JettyServerHandlerCollection.java:74)
     at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:116)
     at org.eclipse.jetty.server.Server.handle(Server.java:363)
     at org.eclipse.jetty.server.AbstractHttpConnection.handleRequest(AbstractHttpConnection.java:483)
     at org.eclipse.jetty.server.BlockingHttpConnection.handleRequest(BlockingHttpConnection.java:53)
     at org.eclipse.jetty.server.AbstractHttpConnection.headerComplete(AbstractHttpConnection.java:920)
     at org.eclipse.jetty.server.AbstractHttpConnection$RequestHandler.headerComplete(AbstractHttpConnection.java:982)
     at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:635)
     at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:235)
     at org.eclipse.jetty.server.BlockingHttpConnection.handle(BlockingHttpConnection.java:72)
     at org.eclipse.jetty.server.nio.BlockingChannelConnector$BlockingChannelEndPoint.run(BlockingChannelConnector.java:298)
     at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:608)
     at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:543)
     at java.lang.Thread.run(Thread.java:722)

Complete stack:

java.lang.RuntimeException: Cannot create component id.co.bippo.booking.web.ProductBookingPanel for contributor id.co.bippo.product.web.pub.ProductView/addToCartRegion from id.co.bippo.booking.web [3478]
     at org.soluvas.web.site.compose.impl.LiveChildContributorImpl$1.create(LiveChildContributorImpl.java:189)
     at org.soluvas.web.site.compose.ComposeUtils.compose(ComposeUtils.java:68)
     at org.soluvas.web.bootstrap.BootstrapPage.onInitialize(BootstrapPage.java:302)
     at org.apache.wicket.Component.fireInitialize(Component.java:933)
     at org.apache.wicket.MarkupContainer.internalInitialize(MarkupContainer.java:960)
     at org.apache.wicket.Page.internalPrepareForRender(Page.java:277)
     at org.apache.wicket.Component.render(Component.java:2313)
     at org.apache.wicket.Page.renderPage(Page.java:1035)
     at org.apache.wicket.request.handler.render.WebPageRenderer.renderPage(WebPageRenderer.java:115)
     at org.apache.wicket.request.handler.render.WebPageRenderer.respond(WebPageRenderer.java:237)
     at org.apache.wicket.request.handler.RenderPageRequestHandler.respond(RenderPageRequestHandler.java:167)
     at org.apache.wicket.request.cycle.RequestCycle$HandlerExecutor.respond(RequestCycle.java:784)
     at org.apache.wicket.request.RequestHandlerStack.execute(RequestHandlerStack.java:64)
     at org.apache.wicket.request.cycle.RequestCycle.execute(RequestCycle.java:255)
     at org.apache.wicket.request.cycle.RequestCycle.processRequest(RequestCycle.java:212)
     at org.apache.wicket.request.cycle.RequestCycle.processRequestAndDetach(RequestCycle.java:283)
     at org.apache.wicket.protocol.http.WicketFilter.processRequest(WicketFilter.java:188)

java.lang.reflect.InvocationTargetException
     at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
     at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
     at java.lang.reflect.Constructor.newInstance(Constructor.java:525)
     at org.soluvas.web.site.compose.impl.LiveChildContributorImpl$1.create(LiveChildContributorImpl.java:187)
     at org.soluvas.web.site.compose.ComposeUtils.compose(ComposeUtils.java:68)
     at org.soluvas.web.bootstrap.BootstrapPage.onInitialize(BootstrapPage.java:302)
     at org.apache.wicket.Component.fireInitialize(Component.java:933)
     at org.apache.wicket.MarkupContainer.internalInitialize(MarkupContainer.java:960)
     at org.apache.wicket.Page.internalPrepareForRender(Page.java:277)
     at org.apache.wicket.Component.render(Component.java:2313)
     at org.apache.wicket.Page.renderPage(Page.java:1035)
     at org.apache.wicket.request.handler.render.WebPageRenderer.renderPage(WebPageRenderer.java:115)
     at org.apache.wicket.request.handler.render.WebPageRenderer.respond(WebPageRenderer.java:237)
     at org.apache.wicket.request.handler.RenderPageRequestHandler.respond(RenderPageRequestHandler.java:167)
     at org.apache.wicket.request.cycle.RequestCycle$HandlerExecutor.respond(RequestCycle.java:784)
     at org.apache.wicket.request.RequestHandlerStack.execute(RequestHandlerStack.java:64)
     at org.apache.wicket.request.cycle.RequestCycle.execute(RequestCycle.java:255)
     at org.apache.wicket.request.cycle.RequestCycle.processRequest(RequestCycle.java:212)
     at org.apache.wicket.request.cycle.RequestCycle.processRequestAndDetach(RequestCycle.java:283)
     at org.apache.wicket.protocol.http.WicketFilter.processRequest(WicketFilter.java:188)

java.lang.RuntimeException: Error during booking check CheckProduct [bookability=OUT_OF_STOCK, confirmability=OUT_OF_STOCK, message=Maaf, produk zibalabel_t05 tidak tersedia saat ini, getPersonId()=arum_puspita, getProductId()=zibalabel_t05, getQty()=1.0]
     at id.co.bippo.booking.BookingCheckRulesImpl.check(BookingCheckRulesImpl.java:151)
     at id.co.bippo.booking.web.ProductBookingPanel.<init>(ProductBookingPanel.java:47)
     at java.lang.reflect.Constructor.newInstance(Constructor.java:525)
     at org.soluvas.web.site.compose.impl.LiveChildContributorImpl$1.create(LiveChildContributorImpl.java:187)
     at org.soluvas.web.site.compose.ComposeUtils.compose(ComposeUtils.java:68)
     at org.soluvas.web.bootstrap.BootstrapPage.onInitialize(BootstrapPage.java:302)
     at org.apache.wicket.Component.fireInitialize(Component.java:933)
     at org.apache.wicket.MarkupContainer.internalInitialize(MarkupContainer.java:960)
     at org.apache.wicket.Page.internalPrepareForRender(Page.java:277)
     at org.apache.wicket.Component.render(Component.java:2313)
     at org.apache.wicket.Page.renderPage(Page.java:1035)
     at org.apache.wicket.request.handler.render.WebPageRenderer.renderPage(WebPageRenderer.java:115)
     at org.apache.wicket.request.handler.render.WebPageRenderer.respond(WebPageRenderer.java:237)
     at org.apache.wicket.request.handler.RenderPageRequestHandler.respond(RenderPageRequestHandler.java:167)
     at org.apache.wicket.request.cycle.RequestCycle$HandlerExecutor.respond(RequestCycle.java:784)
     at org.apache.wicket.request.RequestHandlerStack.execute(RequestHandlerStack.java:64)
     at org.apache.wicket.request.cycle.RequestCycle.execute(RequestCycle.java:255)
     at org.apache.wicket.request.cycle.RequestCycle.processRequest(RequestCycle.java:212)
     at org.apache.wicket.request.cycle.RequestCycle.processRequestAndDetach(RequestCycle.java:283)
     at org.apache.wicket.protocol.http.WicketFilter.processRequest(WicketFilter.java:188)
{code}

Bundles:

{code}
[3016] [Active     ] [            ] [       ] [   80] id.co.bippo.booking.rs (5.0.0.SNAPSHOT)
[3017] [Active     ] [            ] [       ] [   80] id.co.bippo.booking (5.0.0.SNAPSHOT)
[3173] [Active     ] [            ] [Started] [   80] berbatik_booking.xml (0.0.0)
[3192] [Active     ] [            ] [Started] [   80] berbatik_booking.rs.xml (0.0.0)
[3295] [Active     ] [            ] [       ] [   50] org.drools.api (5.5.0.Final)
[3296] [Active     ] [            ] [       ] [   50] org.drools.internalapi (5.5.0.Final)
[3297] [Active     ] [            ] [       ] [   50] org.drools.core (5.5.0.Final)
[3298] [Active     ] [            ] [       ] [   50] org.drools.compiler (5.5.0.Final)
[3299] [Active     ] [            ] [       ] [   50] org.drools.templates (5.5.0.Final)
[3478] [Active     ] [Created     ] [       ] [   80] id.co.bippo.booking.web (5.0.0.SNAPSHOT)
{code}

DRL:

{code}
package id.co.bippo.booking
dialect "mvel"

import org.slf4j.Logger;
import org.joda.time.*;
import id.co.bippo.booking.*;
import id.co.bippo.booking.CheckProduct.Bookability;
import id.co.bippo.booking.CheckProduct.Confirmability;
import id.co.bippo.person.*;
import id.co.bippo.product.util.ProductUtils;

global Logger log;
global BookingDao bookingDao;
global ProductUtils productUtils;
global PersonUtils personUtils;

rule "Cek booking produk dengan qty 1, stock ada"
activation-group "Check"
	when
		$action       : CheckProduct( $personId : personId, $productId : productId, $qty : qty == 1.0,
							bookability == Bookability.NEW,
							confirmability == Confirmability.NEW)
		$bookedQty    : Double() from bookingDao.findBookedQty($productId)
		$availableQty : Double(this - $bookedQty >= $qty) from productUtils.getQtyByProductId($productId)
		$countBook 	  : Long(this < 100) from bookingDao.getBookCountByPersonIdToday($personId)
	then
		log.info("{} boleh booking {} sebanyak {} (stok tersedia: {}, sudah dibooking: {})",
			{$personId, $productId, $qty, $availableQty, $bookedQty});
		modify($action) {
			setBookability(CheckProduct$Bookability.AVAILABLE),
			setConfirmability(CheckProduct$Confirmability.AVAILABLE),
			setMessage("Anda boleh melakukan booking untuk produk "+ $productId +", Terima Kasih")
		}
end

rule "Check booking yang melebihi batas yang telah ditentukan, batas booking 3 per 24 jam" 
activation-group "Check"
	when
		$action 	   : CheckProduct( $personId : personId, $productId : productId, $qty : qty == 1.0,
							bookability == Bookability.NEW,
							confirmability == Confirmability.NEW)
		$countBook     : Long(this >= 100) from bookingDao.getBookCountByPersonIdToday($personId)
	then
		log.info("Person ID {} telah melakukan booking product sebanyak {}", {$personId, $countBook});
		modify($action) {
			setBookability(CheckProduct$Bookability.QUOTA_EXCEEDED), 
			setConfirmability(CheckProduct$Confirmability.QUOTA_EXCEEDED),
			setMessage("Sorry, Cannot book product currently, you have too many bookings today");
		}
end

rule "Check if product is already booked by himself (BookingDetail status: open/pending/waiting)."
activation-group "Check"
salience 15
    when
    	$action			: CheckProduct( $personId : personId, $productId: productId, $qty: qty == 1.0,
    						bookability == Bookability.NEW,
							confirmability == Confirmability.NEW)
    	$bookingDetail  : BookingDetail(booking.personId == $personId, productId == $productId, qty == $qty,
    						/*status in (BookingDetail$Status.OPEN, BookingDetail$Status.PENDING_WAITING) )*/ 
    						status == BookingDetail$Status.OPEN)
    then
		log.info("{} sudah booking {} sebanyak {}, tinggal diorder",
			{$personId, $productId, $qty});
		modify($action) {
			setBookability(CheckProduct$Bookability.ALREADY_SELF),
			setConfirmability(CheckProduct$Confirmability.PLEASE_PAY_TO_ORDER),
			setBooker(personUtils.getPersonRefById($bookingDetail.booking.personId)),
			setMessage($personId + " sudah booking " + $productId " sebanyak " + $qty + ", tinggal diorder")
		}
end

rule "Check if product is already confimed by himself (BookingDetail status: pending_waiting)."
activation-group "Check"
salience 15
    when
    	$action			: CheckProduct( $personId : personId, $productId: productId, $qty: qty == 1.0,
    						bookability == Bookability.NEW,
							confirmability == Confirmability.NEW)
    	$bookingDetail  : BookingDetail(booking.personId == $personId, productId == $productId, qty == $qty,
    						status == BookingDetail$Status.PENDING_WAITING)
    then
		log.info("{} sudah booking {} sebanyak {}, tinggal diorder",
			{$personId, $productId, $qty});
		modify($action) {
			setBookability(CheckProduct$Bookability.ALREADY_SELF),
			setConfirmability(CheckProduct$Confirmability.PLEASE_PAY_TO_WAIT),
			setBooker(personUtils.getPersonRefById($bookingDetail.booking.personId)),
			setMessage($personId + " sudah booking " + $productId " sebanyak " + $qty + ", tinggal diorder")
		}
end

rule "Check: Product already booked by other, AND already confirmed by yet another."
activation-group "Check"
salience 20
    when
    	$action			: CheckProduct( $personId : personId, $productId: productId, $qty: qty == 1.0,
    						bookability == Bookability.NEW,
							confirmability == Confirmability.NEW)
		$bookedQty      : Double(this >= 1.0) from bookingDao.findBookedQty($productId)
    	$bookingDetail  : BookingDetail(booking.personId != $personId, productId == $productId, qty == $qty, 
    						status == BookingDetail$Status.OPEN)
    	$bookingDetail2 : BookingDetail(booking.personId != $personId, productId == $productId, qty == $qty, 
    						status == BookingDetail$Status.PENDING_WAITING)
    then
		log.info("{} ingin booking {} sebanyak {} tapi sudah dibooking dan diconfirm 2 orang",
			{$personId, $productId, $qty});
		modify($action) {
			setBookability(CheckProduct$Bookability.BOOKED_BY_OTHER),
			setConfirmability(CheckProduct$Confirmability.CONFIRMED_BY_OTHER),
			setBooker(personUtils.getPersonRefById($bookingDetail.booking.personId)),
			setMessage($productId + " sudah dibooking dan diconfirm 2 orang customer lain.")
		}
end

rule "Check the product, but the product was booked by other."
activation-group "Check"
salience 10
    when
    	$action			: CheckProduct( $personId : personId, $productId: productId, $qty: qty == 1.0,
    						bookability == Bookability.NEW,
							confirmability == Confirmability.NEW)
		$bookedQty      : Double(this >= 1.0) from bookingDao.findBookedQty($productId)
    	$bookingDetail  : BookingDetail(booking.personId != $personId, productId == $productId, qty == $qty, 
    						status == BookingDetail$Status.OPEN)
    then
		log.info("{} ingin booking {} sebanyak {} tapi sudah dibooking orang, mau confirm dan nunggu ngga?",
			{$personId, $productId, $qty});
		modify($action) {
			setBookability(CheckProduct$Bookability.BOOKED_BY_OTHER),
			setConfirmability(CheckProduct$Confirmability.MUST_CONFIRM_WAITING),
			setBooker(personUtils.getPersonRefById($bookingDetail.booking.personId)),
			setMessage($productId + " sudah dibooking customer lain, silahkan untuk confirm waiting list.")
		}
end

rule "Cek booking produk dengan qty 1, stock habis"
activation-group "Check"
	when
		$action       : CheckProduct( $personId : personId, $productId : productId, $qty : qty == 1.0,
							bookability == Bookability.NEW,
							confirmability == Confirmability.NEW)
		$bookedQty    : Double() from bookingDao.findBookedQty($productId)
		$availableQty : Double(this - $bookedQty < $qty) from productUtils.getQtyByProductId($productId)
	then
		log.info("{} tidak bisa booking {} sebanyak {} karena stok tidak cukup. Stok sekarang: {}, sudah dibooking orang: {}",
			{$personId, $productId, $qty, $availableQty, $bookedQty});
		modify($action) {
			setBookability(CheckProduct$Bookability.OUT_OF_STOCK),
			setConfirmability(CheckProduct$Confirmability.OUT_OF_STOCK),
			setMessage("Maaf, produk "+ $productId + " tidak tersedia saat ini")
		}
end

rule "Check booking produk dengan qty bukan 1"
activation-group "Check"
	when
		$action : CheckProduct( $personId : personId, $productId : productId, $qty : qty != 1.0,
							bookability == Bookability.NEW,
							confirmability == Confirmability.NEW)
	then
		log.info("{} booking {} sebanyak {}. Tidak boleh! Qty harus 1",
			{$personId, $productId, $qty});
		modify($action) {
			setBookability(CheckProduct$Bookability.INVALID),
			setConfirmability(CheckProduct$Confirmability.INVALID),
			setMessage("Booking qty harus 1") 
		}
end
 /*
rule "Minta booking produk, tapi tidak ada ada stock"
activation-group "Check"
salience -10
	when
		$action 	   : CheckProduct( $personId : personId, $productId : productId, $qty : qty,
							bookability == Bookability.NEW,
							confirmability == Confirmability.NEW)
		Double(this == null) from stockSvc.getAvailableQtyByProductId($productId)
	then
		log.info("{} booking {} sebanyak {}. Maaf stock tidak terdaftar!",
			{$personId, $productId, $qty});
		modify($action) {
			setMessage("Stock produk " + $productId + " tidak terdaftar"),
			setBookability(Bookability.NO_STOCK_DATA),
			setConfirmability(Confirmability.NO_STOCK_DATA)
		}
end
*/
rule "Minta booking produk... tak ada kriteria lain yang matching (unhandled case)"
activation-group "Check"
salience -100
	when
		$action       : CheckProduct( $personId : personId, $productId : productId, $qty : qty,
							bookability == Bookability.NEW,
							confirmability == Confirmability.NEW)
	then
		log.warn("{} minta booking {} sebanyak {}, tapi tidak ada rule yang matching",
			{$personId, $productId, $qty});
		modify($action) {
			setMessage("Internal error: " + $personId + " check booking " + $productId +
				" sebanyak " + $qty + " namun tidak ada rule yang match. " +
				" Mohon laporkan ke customer support."),
			setBookability(CheckProduct$Bookability.ERROR),
			setConfirmability(CheckProduct$Confirmability.ERROR)
		}
end
{code}

  was:
We're using Drools 5.5.0 in OSGi with: Karaf 2.3.0, Pax Wicket 1.1.1.

We experience several issues and this is one of them. Even if a fix is not in sight, I'd appreciate if a null check with more detailed information can be provided at the exception point, which will be helpful for us to diagnose and for future bug report to Drools team.

Stack:

{code}
java.lang.NullPointerException
     at org.drools.reteoo.RightTuple.unlinkFromRightParent(RightTuple.java:70)
     at org.drools.reteoo.FromNode.unlinkCreatedHandles(FromNode.java:393)
     at org.drools.reteoo.FromNode.retractLeftTuple(FromNode.java:379)
     at org.drools.reteoo.ObjectTypeNode.retractObject(ObjectTypeNode.java:290)
     at org.drools.reteoo.EntryPointNode.retractObject(EntryPointNode.java:354)
     at org.drools.common.NamedEntryPoint.retract(NamedEntryPoint.java:568)
     at org.drools.common.AbstractWorkingMemory.retract(AbstractWorkingMemory.java:936)
     at org.drools.common.AbstractWorkingMemory.retract(AbstractWorkingMemory.java:924)
     at org.drools.impl.StatefulKnowledgeSessionImpl.retract(StatefulKnowledgeSessionImpl.java:273)
     at id.co.bippo.booking.BookingCheckRulesImpl.processBookings(BookingCheckRulesImpl.java:185)
     at id.co.bippo.booking.BookingCheckRulesImpl.processFacts(BookingCheckRulesImpl.java:195)
     at id.co.bippo.booking.BookingCheckRulesImpl.check(BookingCheckRulesImpl.java:147)
     at id.co.bippo.booking.web.ProductBookingPanel.<init>(ProductBookingPanel.java:47)
     at java.lang.reflect.Constructor.newInstance(Constructor.java:525)
     at org.soluvas.web.site.compose.impl.LiveChildContributorImpl$1.create(LiveChildContributorImpl.java:187)
     at org.soluvas.web.site.compose.ComposeUtils.compose(ComposeUtils.java:68)
     at org.soluvas.web.bootstrap.BootstrapPage.onInitialize(BootstrapPage.java:302)
     at org.apache.wicket.Component.fireInitialize(Component.java:933)
     at org.apache.wicket.MarkupContainer.internalInitialize(MarkupContainer.java:960)
     at org.apache.wicket.Page.internalPrepareForRender(Page.java:277)
     at org.apache.wicket.Component.render(Component.java:2313)
     at org.apache.wicket.Page.renderPage(Page.java:1035)
     at org.apache.wicket.request.handler.render.WebPageRenderer.renderPage(WebPageRenderer.java:115)
     at org.apache.wicket.request.handler.render.WebPageRenderer.respond(WebPageRenderer.java:237)
     at org.apache.wicket.request.handler.RenderPageRequestHandler.respond(RenderPageRequestHandler.java:167)
     at org.apache.wicket.request.cycle.RequestCycle$HandlerExecutor.respond(RequestCycle.java:784)
     at org.apache.wicket.request.RequestHandlerStack.execute(RequestHandlerStack.java:64)
     at org.apache.wicket.request.cycle.RequestCycle.execute(RequestCycle.java:255)
     at org.apache.wicket.request.cycle.RequestCycle.processRequest(RequestCycle.java:212)
     at org.apache.wicket.request.cycle.RequestCycle.processRequestAndDetach(RequestCycle.java:283)
     at org.apache.wicket.protocol.http.WicketFilter.processRequest(WicketFilter.java:188)
     at org.apache.wicket.protocol.http.WicketServlet.doGet(WicketServlet.java:137)
     at javax.servlet.http.HttpServlet.service(HttpServlet.java:693)
     at javax.servlet.http.HttpServlet.service(HttpServlet.java:806)
     at org.ops4j.pax.wicket.internal.FilterDelegator$Chain.doFilter(FilterDelegator.java:79)
     at org.apache.shiro.web.servlet.AbstractShiroFilter.executeChain(AbstractShiroFilter.java:449)
     at org.apache.shiro.web.servlet.AbstractShiroFilter$1.call(AbstractShiroFilter.java:365)
     at org.apache.shiro.subject.support.SubjectCallable.doCall(SubjectCallable.java:90)
     at org.apache.shiro.subject.support.SubjectCallable.call(SubjectCallable.java:83)
     at org.apache.shiro.subject.support.DelegatingSubject.execute(DelegatingSubject.java:383)
     at org.apache.shiro.web.servlet.AbstractShiroFilter.doFilterInternal(AbstractShiroFilter.java:362)
     at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125)
     at org.ops4j.pax.wicket.internal.FilterDelegator$Chain.doFilter(FilterDelegator.java:77)
     at org.ops4j.pax.wicket.internal.FilterDelegator.doFilter(FilterDelegator.java:61)
     at org.ops4j.pax.wicket.internal.ServletProxy$ServletInvocationHandler.invoke(ServletProxy.java:72)
     at $Proxy80.service(Unknown Source)
     at java.lang.reflect.Method.invoke(Method.java:601)
     at org.ops4j.pax.web.service.internal.HttpServiceStarted$2.invoke(HttpServiceStarted.java:210)
     at org.ops4j.pax.web.service.internal.$Proxy0.service(Unknown Source)
     at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:652)
     at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:447)
     at org.ops4j.pax.web.service.jetty.internal.HttpServiceServletHandler.doHandle(HttpServiceServletHandler.java:70)
     at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:137)
     at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:559)
     at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:227)
     at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1038)
     at org.ops4j.pax.web.service.jetty.internal.HttpServiceContext.doHandle(HttpServiceContext.java:117)
     at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:374)
     at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:189)
     at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:972)
     at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:135)
     at org.ops4j.pax.web.service.jetty.internal.JettyServerHandlerCollection.handle(JettyServerHandlerCollection.java:74)
     at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:116)
     at org.eclipse.jetty.server.Server.handle(Server.java:363)
     at org.eclipse.jetty.server.AbstractHttpConnection.handleRequest(AbstractHttpConnection.java:483)
     at org.eclipse.jetty.server.BlockingHttpConnection.handleRequest(BlockingHttpConnection.java:53)
     at org.eclipse.jetty.server.AbstractHttpConnection.headerComplete(AbstractHttpConnection.java:920)
     at org.eclipse.jetty.server.AbstractHttpConnection$RequestHandler.headerComplete(AbstractHttpConnection.java:982)
     at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:635)
     at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:235)
     at org.eclipse.jetty.server.BlockingHttpConnection.handle(BlockingHttpConnection.java:72)
     at org.eclipse.jetty.server.nio.BlockingChannelConnector$BlockingChannelEndPoint.run(BlockingChannelConnector.java:298)
     at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:608)
     at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:543)
     at java.lang.Thread.run(Thread.java:722)

Complete stack:

java.lang.RuntimeException: Cannot create component id.co.bippo.booking.web.ProductBookingPanel for contributor id.co.bippo.product.web.pub.ProductView/addToCartRegion from id.co.bippo.booking.web [3478]
     at org.soluvas.web.site.compose.impl.LiveChildContributorImpl$1.create(LiveChildContributorImpl.java:189)
     at org.soluvas.web.site.compose.ComposeUtils.compose(ComposeUtils.java:68)
     at org.soluvas.web.bootstrap.BootstrapPage.onInitialize(BootstrapPage.java:302)
     at org.apache.wicket.Component.fireInitialize(Component.java:933)
     at org.apache.wicket.MarkupContainer.internalInitialize(MarkupContainer.java:960)
     at org.apache.wicket.Page.internalPrepareForRender(Page.java:277)
     at org.apache.wicket.Component.render(Component.java:2313)
     at org.apache.wicket.Page.renderPage(Page.java:1035)
     at org.apache.wicket.request.handler.render.WebPageRenderer.renderPage(WebPageRenderer.java:115)
     at org.apache.wicket.request.handler.render.WebPageRenderer.respond(WebPageRenderer.java:237)
     at org.apache.wicket.request.handler.RenderPageRequestHandler.respond(RenderPageRequestHandler.java:167)
     at org.apache.wicket.request.cycle.RequestCycle$HandlerExecutor.respond(RequestCycle.java:784)
     at org.apache.wicket.request.RequestHandlerStack.execute(RequestHandlerStack.java:64)
     at org.apache.wicket.request.cycle.RequestCycle.execute(RequestCycle.java:255)
     at org.apache.wicket.request.cycle.RequestCycle.processRequest(RequestCycle.java:212)
     at org.apache.wicket.request.cycle.RequestCycle.processRequestAndDetach(RequestCycle.java:283)
     at org.apache.wicket.protocol.http.WicketFilter.processRequest(WicketFilter.java:188)

java.lang.reflect.InvocationTargetException
     at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
     at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
     at java.lang.reflect.Constructor.newInstance(Constructor.java:525)
     at org.soluvas.web.site.compose.impl.LiveChildContributorImpl$1.create(LiveChildContributorImpl.java:187)
     at org.soluvas.web.site.compose.ComposeUtils.compose(ComposeUtils.java:68)
     at org.soluvas.web.bootstrap.BootstrapPage.onInitialize(BootstrapPage.java:302)
     at org.apache.wicket.Component.fireInitialize(Component.java:933)
     at org.apache.wicket.MarkupContainer.internalInitialize(MarkupContainer.java:960)
     at org.apache.wicket.Page.internalPrepareForRender(Page.java:277)
     at org.apache.wicket.Component.render(Component.java:2313)
     at org.apache.wicket.Page.renderPage(Page.java:1035)
     at org.apache.wicket.request.handler.render.WebPageRenderer.renderPage(WebPageRenderer.java:115)
     at org.apache.wicket.request.handler.render.WebPageRenderer.respond(WebPageRenderer.java:237)
     at org.apache.wicket.request.handler.RenderPageRequestHandler.respond(RenderPageRequestHandler.java:167)
     at org.apache.wicket.request.cycle.RequestCycle$HandlerExecutor.respond(RequestCycle.java:784)
     at org.apache.wicket.request.RequestHandlerStack.execute(RequestHandlerStack.java:64)
     at org.apache.wicket.request.cycle.RequestCycle.execute(RequestCycle.java:255)
     at org.apache.wicket.request.cycle.RequestCycle.processRequest(RequestCycle.java:212)
     at org.apache.wicket.request.cycle.RequestCycle.processRequestAndDetach(RequestCycle.java:283)
     at org.apache.wicket.protocol.http.WicketFilter.processRequest(WicketFilter.java:188)

java.lang.RuntimeException: Error during booking check CheckProduct [bookability=OUT_OF_STOCK, confirmability=OUT_OF_STOCK, message=Maaf, produk zibalabel_t05 tidak tersedia saat ini, getPersonId()=arum_puspita, getProductId()=zibalabel_t05, getQty()=1.0]
     at id.co.bippo.booking.BookingCheckRulesImpl.check(BookingCheckRulesImpl.java:151)
     at id.co.bippo.booking.web.ProductBookingPanel.<init>(ProductBookingPanel.java:47)
     at java.lang.reflect.Constructor.newInstance(Constructor.java:525)
     at org.soluvas.web.site.compose.impl.LiveChildContributorImpl$1.create(LiveChildContributorImpl.java:187)
     at org.soluvas.web.site.compose.ComposeUtils.compose(ComposeUtils.java:68)
     at org.soluvas.web.bootstrap.BootstrapPage.onInitialize(BootstrapPage.java:302)
     at org.apache.wicket.Component.fireInitialize(Component.java:933)
     at org.apache.wicket.MarkupContainer.internalInitialize(MarkupContainer.java:960)
     at org.apache.wicket.Page.internalPrepareForRender(Page.java:277)
     at org.apache.wicket.Component.render(Component.java:2313)
     at org.apache.wicket.Page.renderPage(Page.java:1035)
     at org.apache.wicket.request.handler.render.WebPageRenderer.renderPage(WebPageRenderer.java:115)
     at org.apache.wicket.request.handler.render.WebPageRenderer.respond(WebPageRenderer.java:237)
     at org.apache.wicket.request.handler.RenderPageRequestHandler.respond(RenderPageRequestHandler.java:167)
     at org.apache.wicket.request.cycle.RequestCycle$HandlerExecutor.respond(RequestCycle.java:784)
     at org.apache.wicket.request.RequestHandlerStack.execute(RequestHandlerStack.java:64)
     at org.apache.wicket.request.cycle.RequestCycle.execute(RequestCycle.java:255)
     at org.apache.wicket.request.cycle.RequestCycle.processRequest(RequestCycle.java:212)
     at org.apache.wicket.request.cycle.RequestCycle.processRequestAndDetach(RequestCycle.java:283)
     at org.apache.wicket.protocol.http.WicketFilter.processRequest(WicketFilter.java:188)
{code}

DRL:

{code}
package id.co.bippo.booking
dialect "mvel"

import org.slf4j.Logger;
import org.joda.time.*;
import id.co.bippo.booking.*;
import id.co.bippo.booking.CheckProduct.Bookability;
import id.co.bippo.booking.CheckProduct.Confirmability;
import id.co.bippo.person.*;
import id.co.bippo.product.util.ProductUtils;

global Logger log;
global BookingDao bookingDao;
global ProductUtils productUtils;
global PersonUtils personUtils;

rule "Cek booking produk dengan qty 1, stock ada"
activation-group "Check"
	when
		$action       : CheckProduct( $personId : personId, $productId : productId, $qty : qty == 1.0,
							bookability == Bookability.NEW,
							confirmability == Confirmability.NEW)
		$bookedQty    : Double() from bookingDao.findBookedQty($productId)
		$availableQty : Double(this - $bookedQty >= $qty) from productUtils.getQtyByProductId($productId)
		$countBook 	  : Long(this < 100) from bookingDao.getBookCountByPersonIdToday($personId)
	then
		log.info("{} boleh booking {} sebanyak {} (stok tersedia: {}, sudah dibooking: {})",
			{$personId, $productId, $qty, $availableQty, $bookedQty});
		modify($action) {
			setBookability(CheckProduct$Bookability.AVAILABLE),
			setConfirmability(CheckProduct$Confirmability.AVAILABLE),
			setMessage("Anda boleh melakukan booking untuk produk "+ $productId +", Terima Kasih")
		}
end

rule "Check booking yang melebihi batas yang telah ditentukan, batas booking 3 per 24 jam" 
activation-group "Check"
	when
		$action 	   : CheckProduct( $personId : personId, $productId : productId, $qty : qty == 1.0,
							bookability == Bookability.NEW,
							confirmability == Confirmability.NEW)
		$countBook     : Long(this >= 100) from bookingDao.getBookCountByPersonIdToday($personId)
	then
		log.info("Person ID {} telah melakukan booking product sebanyak {}", {$personId, $countBook});
		modify($action) {
			setBookability(CheckProduct$Bookability.QUOTA_EXCEEDED), 
			setConfirmability(CheckProduct$Confirmability.QUOTA_EXCEEDED),
			setMessage("Sorry, Cannot book product currently, you have too many bookings today");
		}
end

rule "Check if product is already booked by himself (BookingDetail status: open/pending/waiting)."
activation-group "Check"
salience 15
    when
    	$action			: CheckProduct( $personId : personId, $productId: productId, $qty: qty == 1.0,
    						bookability == Bookability.NEW,
							confirmability == Confirmability.NEW)
    	$bookingDetail  : BookingDetail(booking.personId == $personId, productId == $productId, qty == $qty,
    						/*status in (BookingDetail$Status.OPEN, BookingDetail$Status.PENDING_WAITING) )*/ 
    						status == BookingDetail$Status.OPEN)
    then
		log.info("{} sudah booking {} sebanyak {}, tinggal diorder",
			{$personId, $productId, $qty});
		modify($action) {
			setBookability(CheckProduct$Bookability.ALREADY_SELF),
			setConfirmability(CheckProduct$Confirmability.PLEASE_PAY_TO_ORDER),
			setBooker(personUtils.getPersonRefById($bookingDetail.booking.personId)),
			setMessage($personId + " sudah booking " + $productId " sebanyak " + $qty + ", tinggal diorder")
		}
end

rule "Check if product is already confimed by himself (BookingDetail status: pending_waiting)."
activation-group "Check"
salience 15
    when
    	$action			: CheckProduct( $personId : personId, $productId: productId, $qty: qty == 1.0,
    						bookability == Bookability.NEW,
							confirmability == Confirmability.NEW)
    	$bookingDetail  : BookingDetail(booking.personId == $personId, productId == $productId, qty == $qty,
    						status == BookingDetail$Status.PENDING_WAITING)
    then
		log.info("{} sudah booking {} sebanyak {}, tinggal diorder",
			{$personId, $productId, $qty});
		modify($action) {
			setBookability(CheckProduct$Bookability.ALREADY_SELF),
			setConfirmability(CheckProduct$Confirmability.PLEASE_PAY_TO_WAIT),
			setBooker(personUtils.getPersonRefById($bookingDetail.booking.personId)),
			setMessage($personId + " sudah booking " + $productId " sebanyak " + $qty + ", tinggal diorder")
		}
end

rule "Check: Product already booked by other, AND already confirmed by yet another."
activation-group "Check"
salience 20
    when
    	$action			: CheckProduct( $personId : personId, $productId: productId, $qty: qty == 1.0,
    						bookability == Bookability.NEW,
							confirmability == Confirmability.NEW)
		$bookedQty      : Double(this >= 1.0) from bookingDao.findBookedQty($productId)
    	$bookingDetail  : BookingDetail(booking.personId != $personId, productId == $productId, qty == $qty, 
    						status == BookingDetail$Status.OPEN)
    	$bookingDetail2 : BookingDetail(booking.personId != $personId, productId == $productId, qty == $qty, 
    						status == BookingDetail$Status.PENDING_WAITING)
    then
		log.info("{} ingin booking {} sebanyak {} tapi sudah dibooking dan diconfirm 2 orang",
			{$personId, $productId, $qty});
		modify($action) {
			setBookability(CheckProduct$Bookability.BOOKED_BY_OTHER),
			setConfirmability(CheckProduct$Confirmability.CONFIRMED_BY_OTHER),
			setBooker(personUtils.getPersonRefById($bookingDetail.booking.personId)),
			setMessage($productId + " sudah dibooking dan diconfirm 2 orang customer lain.")
		}
end

rule "Check the product, but the product was booked by other."
activation-group "Check"
salience 10
    when
    	$action			: CheckProduct( $personId : personId, $productId: productId, $qty: qty == 1.0,
    						bookability == Bookability.NEW,
							confirmability == Confirmability.NEW)
		$bookedQty      : Double(this >= 1.0) from bookingDao.findBookedQty($productId)
    	$bookingDetail  : BookingDetail(booking.personId != $personId, productId == $productId, qty == $qty, 
    						status == BookingDetail$Status.OPEN)
    then
		log.info("{} ingin booking {} sebanyak {} tapi sudah dibooking orang, mau confirm dan nunggu ngga?",
			{$personId, $productId, $qty});
		modify($action) {
			setBookability(CheckProduct$Bookability.BOOKED_BY_OTHER),
			setConfirmability(CheckProduct$Confirmability.MUST_CONFIRM_WAITING),
			setBooker(personUtils.getPersonRefById($bookingDetail.booking.personId)),
			setMessage($productId + " sudah dibooking customer lain, silahkan untuk confirm waiting list.")
		}
end

rule "Cek booking produk dengan qty 1, stock habis"
activation-group "Check"
	when
		$action       : CheckProduct( $personId : personId, $productId : productId, $qty : qty == 1.0,
							bookability == Bookability.NEW,
							confirmability == Confirmability.NEW)
		$bookedQty    : Double() from bookingDao.findBookedQty($productId)
		$availableQty : Double(this - $bookedQty < $qty) from productUtils.getQtyByProductId($productId)
	then
		log.info("{} tidak bisa booking {} sebanyak {} karena stok tidak cukup. Stok sekarang: {}, sudah dibooking orang: {}",
			{$personId, $productId, $qty, $availableQty, $bookedQty});
		modify($action) {
			setBookability(CheckProduct$Bookability.OUT_OF_STOCK),
			setConfirmability(CheckProduct$Confirmability.OUT_OF_STOCK),
			setMessage("Maaf, produk "+ $productId + " tidak tersedia saat ini")
		}
end

rule "Check booking produk dengan qty bukan 1"
activation-group "Check"
	when
		$action : CheckProduct( $personId : personId, $productId : productId, $qty : qty != 1.0,
							bookability == Bookability.NEW,
							confirmability == Confirmability.NEW)
	then
		log.info("{} booking {} sebanyak {}. Tidak boleh! Qty harus 1",
			{$personId, $productId, $qty});
		modify($action) {
			setBookability(CheckProduct$Bookability.INVALID),
			setConfirmability(CheckProduct$Confirmability.INVALID),
			setMessage("Booking qty harus 1") 
		}
end
 /*
rule "Minta booking produk, tapi tidak ada ada stock"
activation-group "Check"
salience -10
	when
		$action 	   : CheckProduct( $personId : personId, $productId : productId, $qty : qty,
							bookability == Bookability.NEW,
							confirmability == Confirmability.NEW)
		Double(this == null) from stockSvc.getAvailableQtyByProductId($productId)
	then
		log.info("{} booking {} sebanyak {}. Maaf stock tidak terdaftar!",
			{$personId, $productId, $qty});
		modify($action) {
			setMessage("Stock produk " + $productId + " tidak terdaftar"),
			setBookability(Bookability.NO_STOCK_DATA),
			setConfirmability(Confirmability.NO_STOCK_DATA)
		}
end
*/
rule "Minta booking produk... tak ada kriteria lain yang matching (unhandled case)"
activation-group "Check"
salience -100
	when
		$action       : CheckProduct( $personId : personId, $productId : productId, $qty : qty,
							bookability == Bookability.NEW,
							confirmability == Confirmability.NEW)
	then
		log.warn("{} minta booking {} sebanyak {}, tapi tidak ada rule yang matching",
			{$personId, $productId, $qty});
		modify($action) {
			setMessage("Internal error: " + $personId + " check booking " + $productId +
				" sebanyak " + $qty + " namun tidak ada rule yang match. " +
				" Mohon laporkan ke customer support."),
			setBookability(CheckProduct$Bookability.ERROR),
			setConfirmability(CheckProduct$Confirmability.ERROR)
		}
end
{code}


    
> Provide detailed context information for java.lang.NullPointerException at org.drools.reteoo.RightTuple.unlinkFromRightParent(RightTuple.java:70)
> -------------------------------------------------------------------------------------------------------------------------------------------------
>
>                 Key: JBRULES-3687
>                 URL: https://issues.jboss.org/browse/JBRULES-3687
>             Project: Drools
>          Issue Type: Bug
>      Security Level: Public(Everyone can see) 
>          Components: drools-core
>    Affects Versions: 5.5.0.Final
>         Environment: Karaf
>   Karaf version               2.3.0
>   Karaf home                  /home/ceefour/git/bippo-commerce5/karaf
>   Karaf base                  /home/ceefour/git/bippo-commerce5/karaf
>   OSGi Framework              org.apache.felix.framework - 4.0.3
> JVM
>   Java Virtual Machine        OpenJDK 64-Bit Server VM version 23.2-b09
>   Version                     1.7.0_07
>   Vendor                      Oracle Corporation
>   Uptime                      8 minutes
>   Total compile time          44.295 seconds
> Threads
>   Live threads                107
>   Daemon threads              92
>   Peak                        140
>   Total started               322
> Memory
>   Current heap size           203,385 kbytes
>   Maximum heap size           466,048 kbytes
>   Committed heap size         283,072 kbytes
>   Pending objects             0
>   Garbage collector           Name = 'PS Scavenge', Collections = 73, Time = 0.654 seconds
>   Garbage collector           Name = 'PS MarkSweep', Collections = 2, Time = 0.366 seconds
> Classes
>   Current classes loaded      15,546
>   Total classes loaded        15,547
>   Total classes unloaded      1
> Operating system
>   Name                        Linux version 3.2.0-32-generic
>   Architecture                amd64
>   Processors                  8
>            Reporter: Hendy Irawan
>            Assignee: Mark Proctor
>
> We're using Drools 5.5.0 in OSGi with: Karaf 2.3.0, Pax Wicket 1.1.1.
> We experience several issues and this is one of them. Even if a fix is not in sight, I'd appreciate if a null check with more detailed information can be provided at the exception point, which will be helpful for us to diagnose and for future bug report to Drools team.
> Stack:
> {code}
> java.lang.NullPointerException
>      at org.drools.reteoo.RightTuple.unlinkFromRightParent(RightTuple.java:70)
>      at org.drools.reteoo.FromNode.unlinkCreatedHandles(FromNode.java:393)
>      at org.drools.reteoo.FromNode.retractLeftTuple(FromNode.java:379)
>      at org.drools.reteoo.ObjectTypeNode.retractObject(ObjectTypeNode.java:290)
>      at org.drools.reteoo.EntryPointNode.retractObject(EntryPointNode.java:354)
>      at org.drools.common.NamedEntryPoint.retract(NamedEntryPoint.java:568)
>      at org.drools.common.AbstractWorkingMemory.retract(AbstractWorkingMemory.java:936)
>      at org.drools.common.AbstractWorkingMemory.retract(AbstractWorkingMemory.java:924)
>      at org.drools.impl.StatefulKnowledgeSessionImpl.retract(StatefulKnowledgeSessionImpl.java:273)
>      at id.co.bippo.booking.BookingCheckRulesImpl.processBookings(BookingCheckRulesImpl.java:185)
>      at id.co.bippo.booking.BookingCheckRulesImpl.processFacts(BookingCheckRulesImpl.java:195)
>      at id.co.bippo.booking.BookingCheckRulesImpl.check(BookingCheckRulesImpl.java:147)
>      at id.co.bippo.booking.web.ProductBookingPanel.<init>(ProductBookingPanel.java:47)
>      at java.lang.reflect.Constructor.newInstance(Constructor.java:525)
>      at org.soluvas.web.site.compose.impl.LiveChildContributorImpl$1.create(LiveChildContributorImpl.java:187)
>      at org.soluvas.web.site.compose.ComposeUtils.compose(ComposeUtils.java:68)
>      at org.soluvas.web.bootstrap.BootstrapPage.onInitialize(BootstrapPage.java:302)
>      at org.apache.wicket.Component.fireInitialize(Component.java:933)
>      at org.apache.wicket.MarkupContainer.internalInitialize(MarkupContainer.java:960)
>      at org.apache.wicket.Page.internalPrepareForRender(Page.java:277)
>      at org.apache.wicket.Component.render(Component.java:2313)
>      at org.apache.wicket.Page.renderPage(Page.java:1035)
>      at org.apache.wicket.request.handler.render.WebPageRenderer.renderPage(WebPageRenderer.java:115)
>      at org.apache.wicket.request.handler.render.WebPageRenderer.respond(WebPageRenderer.java:237)
>      at org.apache.wicket.request.handler.RenderPageRequestHandler.respond(RenderPageRequestHandler.java:167)
>      at org.apache.wicket.request.cycle.RequestCycle$HandlerExecutor.respond(RequestCycle.java:784)
>      at org.apache.wicket.request.RequestHandlerStack.execute(RequestHandlerStack.java:64)
>      at org.apache.wicket.request.cycle.RequestCycle.execute(RequestCycle.java:255)
>      at org.apache.wicket.request.cycle.RequestCycle.processRequest(RequestCycle.java:212)
>      at org.apache.wicket.request.cycle.RequestCycle.processRequestAndDetach(RequestCycle.java:283)
>      at org.apache.wicket.protocol.http.WicketFilter.processRequest(WicketFilter.java:188)
>      at org.apache.wicket.protocol.http.WicketServlet.doGet(WicketServlet.java:137)
>      at javax.servlet.http.HttpServlet.service(HttpServlet.java:693)
>      at javax.servlet.http.HttpServlet.service(HttpServlet.java:806)
>      at org.ops4j.pax.wicket.internal.FilterDelegator$Chain.doFilter(FilterDelegator.java:79)
>      at org.apache.shiro.web.servlet.AbstractShiroFilter.executeChain(AbstractShiroFilter.java:449)
>      at org.apache.shiro.web.servlet.AbstractShiroFilter$1.call(AbstractShiroFilter.java:365)
>      at org.apache.shiro.subject.support.SubjectCallable.doCall(SubjectCallable.java:90)
>      at org.apache.shiro.subject.support.SubjectCallable.call(SubjectCallable.java:83)
>      at org.apache.shiro.subject.support.DelegatingSubject.execute(DelegatingSubject.java:383)
>      at org.apache.shiro.web.servlet.AbstractShiroFilter.doFilterInternal(AbstractShiroFilter.java:362)
>      at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125)
>      at org.ops4j.pax.wicket.internal.FilterDelegator$Chain.doFilter(FilterDelegator.java:77)
>      at org.ops4j.pax.wicket.internal.FilterDelegator.doFilter(FilterDelegator.java:61)
>      at org.ops4j.pax.wicket.internal.ServletProxy$ServletInvocationHandler.invoke(ServletProxy.java:72)
>      at $Proxy80.service(Unknown Source)
>      at java.lang.reflect.Method.invoke(Method.java:601)
>      at org.ops4j.pax.web.service.internal.HttpServiceStarted$2.invoke(HttpServiceStarted.java:210)
>      at org.ops4j.pax.web.service.internal.$Proxy0.service(Unknown Source)
>      at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:652)
>      at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:447)
>      at org.ops4j.pax.web.service.jetty.internal.HttpServiceServletHandler.doHandle(HttpServiceServletHandler.java:70)
>      at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:137)
>      at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:559)
>      at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:227)
>      at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1038)
>      at org.ops4j.pax.web.service.jetty.internal.HttpServiceContext.doHandle(HttpServiceContext.java:117)
>      at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:374)
>      at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:189)
>      at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:972)
>      at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:135)
>      at org.ops4j.pax.web.service.jetty.internal.JettyServerHandlerCollection.handle(JettyServerHandlerCollection.java:74)
>      at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:116)
>      at org.eclipse.jetty.server.Server.handle(Server.java:363)
>      at org.eclipse.jetty.server.AbstractHttpConnection.handleRequest(AbstractHttpConnection.java:483)
>      at org.eclipse.jetty.server.BlockingHttpConnection.handleRequest(BlockingHttpConnection.java:53)
>      at org.eclipse.jetty.server.AbstractHttpConnection.headerComplete(AbstractHttpConnection.java:920)
>      at org.eclipse.jetty.server.AbstractHttpConnection$RequestHandler.headerComplete(AbstractHttpConnection.java:982)
>      at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:635)
>      at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:235)
>      at org.eclipse.jetty.server.BlockingHttpConnection.handle(BlockingHttpConnection.java:72)
>      at org.eclipse.jetty.server.nio.BlockingChannelConnector$BlockingChannelEndPoint.run(BlockingChannelConnector.java:298)
>      at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:608)
>      at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:543)
>      at java.lang.Thread.run(Thread.java:722)
> Complete stack:
> java.lang.RuntimeException: Cannot create component id.co.bippo.booking.web.ProductBookingPanel for contributor id.co.bippo.product.web.pub.ProductView/addToCartRegion from id.co.bippo.booking.web [3478]
>      at org.soluvas.web.site.compose.impl.LiveChildContributorImpl$1.create(LiveChildContributorImpl.java:189)
>      at org.soluvas.web.site.compose.ComposeUtils.compose(ComposeUtils.java:68)
>      at org.soluvas.web.bootstrap.BootstrapPage.onInitialize(BootstrapPage.java:302)
>      at org.apache.wicket.Component.fireInitialize(Component.java:933)
>      at org.apache.wicket.MarkupContainer.internalInitialize(MarkupContainer.java:960)
>      at org.apache.wicket.Page.internalPrepareForRender(Page.java:277)
>      at org.apache.wicket.Component.render(Component.java:2313)
>      at org.apache.wicket.Page.renderPage(Page.java:1035)
>      at org.apache.wicket.request.handler.render.WebPageRenderer.renderPage(WebPageRenderer.java:115)
>      at org.apache.wicket.request.handler.render.WebPageRenderer.respond(WebPageRenderer.java:237)
>      at org.apache.wicket.request.handler.RenderPageRequestHandler.respond(RenderPageRequestHandler.java:167)
>      at org.apache.wicket.request.cycle.RequestCycle$HandlerExecutor.respond(RequestCycle.java:784)
>      at org.apache.wicket.request.RequestHandlerStack.execute(RequestHandlerStack.java:64)
>      at org.apache.wicket.request.cycle.RequestCycle.execute(RequestCycle.java:255)
>      at org.apache.wicket.request.cycle.RequestCycle.processRequest(RequestCycle.java:212)
>      at org.apache.wicket.request.cycle.RequestCycle.processRequestAndDetach(RequestCycle.java:283)
>      at org.apache.wicket.protocol.http.WicketFilter.processRequest(WicketFilter.java:188)
> java.lang.reflect.InvocationTargetException
>      at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
>      at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
>      at java.lang.reflect.Constructor.newInstance(Constructor.java:525)
>      at org.soluvas.web.site.compose.impl.LiveChildContributorImpl$1.create(LiveChildContributorImpl.java:187)
>      at org.soluvas.web.site.compose.ComposeUtils.compose(ComposeUtils.java:68)
>      at org.soluvas.web.bootstrap.BootstrapPage.onInitialize(BootstrapPage.java:302)
>      at org.apache.wicket.Component.fireInitialize(Component.java:933)
>      at org.apache.wicket.MarkupContainer.internalInitialize(MarkupContainer.java:960)
>      at org.apache.wicket.Page.internalPrepareForRender(Page.java:277)
>      at org.apache.wicket.Component.render(Component.java:2313)
>      at org.apache.wicket.Page.renderPage(Page.java:1035)
>      at org.apache.wicket.request.handler.render.WebPageRenderer.renderPage(WebPageRenderer.java:115)
>      at org.apache.wicket.request.handler.render.WebPageRenderer.respond(WebPageRenderer.java:237)
>      at org.apache.wicket.request.handler.RenderPageRequestHandler.respond(RenderPageRequestHandler.java:167)
>      at org.apache.wicket.request.cycle.RequestCycle$HandlerExecutor.respond(RequestCycle.java:784)
>      at org.apache.wicket.request.RequestHandlerStack.execute(RequestHandlerStack.java:64)
>      at org.apache.wicket.request.cycle.RequestCycle.execute(RequestCycle.java:255)
>      at org.apache.wicket.request.cycle.RequestCycle.processRequest(RequestCycle.java:212)
>      at org.apache.wicket.request.cycle.RequestCycle.processRequestAndDetach(RequestCycle.java:283)
>      at org.apache.wicket.protocol.http.WicketFilter.processRequest(WicketFilter.java:188)
> java.lang.RuntimeException: Error during booking check CheckProduct [bookability=OUT_OF_STOCK, confirmability=OUT_OF_STOCK, message=Maaf, produk zibalabel_t05 tidak tersedia saat ini, getPersonId()=arum_puspita, getProductId()=zibalabel_t05, getQty()=1.0]
>      at id.co.bippo.booking.BookingCheckRulesImpl.check(BookingCheckRulesImpl.java:151)
>      at id.co.bippo.booking.web.ProductBookingPanel.<init>(ProductBookingPanel.java:47)
>      at java.lang.reflect.Constructor.newInstance(Constructor.java:525)
>      at org.soluvas.web.site.compose.impl.LiveChildContributorImpl$1.create(LiveChildContributorImpl.java:187)
>      at org.soluvas.web.site.compose.ComposeUtils.compose(ComposeUtils.java:68)
>      at org.soluvas.web.bootstrap.BootstrapPage.onInitialize(BootstrapPage.java:302)
>      at org.apache.wicket.Component.fireInitialize(Component.java:933)
>      at org.apache.wicket.MarkupContainer.internalInitialize(MarkupContainer.java:960)
>      at org.apache.wicket.Page.internalPrepareForRender(Page.java:277)
>      at org.apache.wicket.Component.render(Component.java:2313)
>      at org.apache.wicket.Page.renderPage(Page.java:1035)
>      at org.apache.wicket.request.handler.render.WebPageRenderer.renderPage(WebPageRenderer.java:115)
>      at org.apache.wicket.request.handler.render.WebPageRenderer.respond(WebPageRenderer.java:237)
>      at org.apache.wicket.request.handler.RenderPageRequestHandler.respond(RenderPageRequestHandler.java:167)
>      at org.apache.wicket.request.cycle.RequestCycle$HandlerExecutor.respond(RequestCycle.java:784)
>      at org.apache.wicket.request.RequestHandlerStack.execute(RequestHandlerStack.java:64)
>      at org.apache.wicket.request.cycle.RequestCycle.execute(RequestCycle.java:255)
>      at org.apache.wicket.request.cycle.RequestCycle.processRequest(RequestCycle.java:212)
>      at org.apache.wicket.request.cycle.RequestCycle.processRequestAndDetach(RequestCycle.java:283)
>      at org.apache.wicket.protocol.http.WicketFilter.processRequest(WicketFilter.java:188)
> {code}
> Bundles:
> {code}
> [3016] [Active     ] [            ] [       ] [   80] id.co.bippo.booking.rs (5.0.0.SNAPSHOT)
> [3017] [Active     ] [            ] [       ] [   80] id.co.bippo.booking (5.0.0.SNAPSHOT)
> [3173] [Active     ] [            ] [Started] [   80] berbatik_booking.xml (0.0.0)
> [3192] [Active     ] [            ] [Started] [   80] berbatik_booking.rs.xml (0.0.0)
> [3295] [Active     ] [            ] [       ] [   50] org.drools.api (5.5.0.Final)
> [3296] [Active     ] [            ] [       ] [   50] org.drools.internalapi (5.5.0.Final)
> [3297] [Active     ] [            ] [       ] [   50] org.drools.core (5.5.0.Final)
> [3298] [Active     ] [            ] [       ] [   50] org.drools.compiler (5.5.0.Final)
> [3299] [Active     ] [            ] [       ] [   50] org.drools.templates (5.5.0.Final)
> [3478] [Active     ] [Created     ] [       ] [   80] id.co.bippo.booking.web (5.0.0.SNAPSHOT)
> {code}
> DRL:
> {code}
> package id.co.bippo.booking
> dialect "mvel"
> import org.slf4j.Logger;
> import org.joda.time.*;
> import id.co.bippo.booking.*;
> import id.co.bippo.booking.CheckProduct.Bookability;
> import id.co.bippo.booking.CheckProduct.Confirmability;
> import id.co.bippo.person.*;
> import id.co.bippo.product.util.ProductUtils;
> global Logger log;
> global BookingDao bookingDao;
> global ProductUtils productUtils;
> global PersonUtils personUtils;
> rule "Cek booking produk dengan qty 1, stock ada"
> activation-group "Check"
> 	when
> 		$action       : CheckProduct( $personId : personId, $productId : productId, $qty : qty == 1.0,
> 							bookability == Bookability.NEW,
> 							confirmability == Confirmability.NEW)
> 		$bookedQty    : Double() from bookingDao.findBookedQty($productId)
> 		$availableQty : Double(this - $bookedQty >= $qty) from productUtils.getQtyByProductId($productId)
> 		$countBook 	  : Long(this < 100) from bookingDao.getBookCountByPersonIdToday($personId)
> 	then
> 		log.info("{} boleh booking {} sebanyak {} (stok tersedia: {}, sudah dibooking: {})",
> 			{$personId, $productId, $qty, $availableQty, $bookedQty});
> 		modify($action) {
> 			setBookability(CheckProduct$Bookability.AVAILABLE),
> 			setConfirmability(CheckProduct$Confirmability.AVAILABLE),
> 			setMessage("Anda boleh melakukan booking untuk produk "+ $productId +", Terima Kasih")
> 		}
> end
> rule "Check booking yang melebihi batas yang telah ditentukan, batas booking 3 per 24 jam" 
> activation-group "Check"
> 	when
> 		$action 	   : CheckProduct( $personId : personId, $productId : productId, $qty : qty == 1.0,
> 							bookability == Bookability.NEW,
> 							confirmability == Confirmability.NEW)
> 		$countBook     : Long(this >= 100) from bookingDao.getBookCountByPersonIdToday($personId)
> 	then
> 		log.info("Person ID {} telah melakukan booking product sebanyak {}", {$personId, $countBook});
> 		modify($action) {
> 			setBookability(CheckProduct$Bookability.QUOTA_EXCEEDED), 
> 			setConfirmability(CheckProduct$Confirmability.QUOTA_EXCEEDED),
> 			setMessage("Sorry, Cannot book product currently, you have too many bookings today");
> 		}
> end
> rule "Check if product is already booked by himself (BookingDetail status: open/pending/waiting)."
> activation-group "Check"
> salience 15
>     when
>     	$action			: CheckProduct( $personId : personId, $productId: productId, $qty: qty == 1.0,
>     						bookability == Bookability.NEW,
> 							confirmability == Confirmability.NEW)
>     	$bookingDetail  : BookingDetail(booking.personId == $personId, productId == $productId, qty == $qty,
>     						/*status in (BookingDetail$Status.OPEN, BookingDetail$Status.PENDING_WAITING) )*/ 
>     						status == BookingDetail$Status.OPEN)
>     then
> 		log.info("{} sudah booking {} sebanyak {}, tinggal diorder",
> 			{$personId, $productId, $qty});
> 		modify($action) {
> 			setBookability(CheckProduct$Bookability.ALREADY_SELF),
> 			setConfirmability(CheckProduct$Confirmability.PLEASE_PAY_TO_ORDER),
> 			setBooker(personUtils.getPersonRefById($bookingDetail.booking.personId)),
> 			setMessage($personId + " sudah booking " + $productId " sebanyak " + $qty + ", tinggal diorder")
> 		}
> end
> rule "Check if product is already confimed by himself (BookingDetail status: pending_waiting)."
> activation-group "Check"
> salience 15
>     when
>     	$action			: CheckProduct( $personId : personId, $productId: productId, $qty: qty == 1.0,
>     						bookability == Bookability.NEW,
> 							confirmability == Confirmability.NEW)
>     	$bookingDetail  : BookingDetail(booking.personId == $personId, productId == $productId, qty == $qty,
>     						status == BookingDetail$Status.PENDING_WAITING)
>     then
> 		log.info("{} sudah booking {} sebanyak {}, tinggal diorder",
> 			{$personId, $productId, $qty});
> 		modify($action) {
> 			setBookability(CheckProduct$Bookability.ALREADY_SELF),
> 			setConfirmability(CheckProduct$Confirmability.PLEASE_PAY_TO_WAIT),
> 			setBooker(personUtils.getPersonRefById($bookingDetail.booking.personId)),
> 			setMessage($personId + " sudah booking " + $productId " sebanyak " + $qty + ", tinggal diorder")
> 		}
> end
> rule "Check: Product already booked by other, AND already confirmed by yet another."
> activation-group "Check"
> salience 20
>     when
>     	$action			: CheckProduct( $personId : personId, $productId: productId, $qty: qty == 1.0,
>     						bookability == Bookability.NEW,
> 							confirmability == Confirmability.NEW)
> 		$bookedQty      : Double(this >= 1.0) from bookingDao.findBookedQty($productId)
>     	$bookingDetail  : BookingDetail(booking.personId != $personId, productId == $productId, qty == $qty, 
>     						status == BookingDetail$Status.OPEN)
>     	$bookingDetail2 : BookingDetail(booking.personId != $personId, productId == $productId, qty == $qty, 
>     						status == BookingDetail$Status.PENDING_WAITING)
>     then
> 		log.info("{} ingin booking {} sebanyak {} tapi sudah dibooking dan diconfirm 2 orang",
> 			{$personId, $productId, $qty});
> 		modify($action) {
> 			setBookability(CheckProduct$Bookability.BOOKED_BY_OTHER),
> 			setConfirmability(CheckProduct$Confirmability.CONFIRMED_BY_OTHER),
> 			setBooker(personUtils.getPersonRefById($bookingDetail.booking.personId)),
> 			setMessage($productId + " sudah dibooking dan diconfirm 2 orang customer lain.")
> 		}
> end
> rule "Check the product, but the product was booked by other."
> activation-group "Check"
> salience 10
>     when
>     	$action			: CheckProduct( $personId : personId, $productId: productId, $qty: qty == 1.0,
>     						bookability == Bookability.NEW,
> 							confirmability == Confirmability.NEW)
> 		$bookedQty      : Double(this >= 1.0) from bookingDao.findBookedQty($productId)
>     	$bookingDetail  : BookingDetail(booking.personId != $personId, productId == $productId, qty == $qty, 
>     						status == BookingDetail$Status.OPEN)
>     then
> 		log.info("{} ingin booking {} sebanyak {} tapi sudah dibooking orang, mau confirm dan nunggu ngga?",
> 			{$personId, $productId, $qty});
> 		modify($action) {
> 			setBookability(CheckProduct$Bookability.BOOKED_BY_OTHER),
> 			setConfirmability(CheckProduct$Confirmability.MUST_CONFIRM_WAITING),
> 			setBooker(personUtils.getPersonRefById($bookingDetail.booking.personId)),
> 			setMessage($productId + " sudah dibooking customer lain, silahkan untuk confirm waiting list.")
> 		}
> end
> rule "Cek booking produk dengan qty 1, stock habis"
> activation-group "Check"
> 	when
> 		$action       : CheckProduct( $personId : personId, $productId : productId, $qty : qty == 1.0,
> 							bookability == Bookability.NEW,
> 							confirmability == Confirmability.NEW)
> 		$bookedQty    : Double() from bookingDao.findBookedQty($productId)
> 		$availableQty : Double(this - $bookedQty < $qty) from productUtils.getQtyByProductId($productId)
> 	then
> 		log.info("{} tidak bisa booking {} sebanyak {} karena stok tidak cukup. Stok sekarang: {}, sudah dibooking orang: {}",
> 			{$personId, $productId, $qty, $availableQty, $bookedQty});
> 		modify($action) {
> 			setBookability(CheckProduct$Bookability.OUT_OF_STOCK),
> 			setConfirmability(CheckProduct$Confirmability.OUT_OF_STOCK),
> 			setMessage("Maaf, produk "+ $productId + " tidak tersedia saat ini")
> 		}
> end
> rule "Check booking produk dengan qty bukan 1"
> activation-group "Check"
> 	when
> 		$action : CheckProduct( $personId : personId, $productId : productId, $qty : qty != 1.0,
> 							bookability == Bookability.NEW,
> 							confirmability == Confirmability.NEW)
> 	then
> 		log.info("{} booking {} sebanyak {}. Tidak boleh! Qty harus 1",
> 			{$personId, $productId, $qty});
> 		modify($action) {
> 			setBookability(CheckProduct$Bookability.INVALID),
> 			setConfirmability(CheckProduct$Confirmability.INVALID),
> 			setMessage("Booking qty harus 1") 
> 		}
> end
>  /*
> rule "Minta booking produk, tapi tidak ada ada stock"
> activation-group "Check"
> salience -10
> 	when
> 		$action 	   : CheckProduct( $personId : personId, $productId : productId, $qty : qty,
> 							bookability == Bookability.NEW,
> 							confirmability == Confirmability.NEW)
> 		Double(this == null) from stockSvc.getAvailableQtyByProductId($productId)
> 	then
> 		log.info("{} booking {} sebanyak {}. Maaf stock tidak terdaftar!",
> 			{$personId, $productId, $qty});
> 		modify($action) {
> 			setMessage("Stock produk " + $productId + " tidak terdaftar"),
> 			setBookability(Bookability.NO_STOCK_DATA),
> 			setConfirmability(Confirmability.NO_STOCK_DATA)
> 		}
> end
> */
> rule "Minta booking produk... tak ada kriteria lain yang matching (unhandled case)"
> activation-group "Check"
> salience -100
> 	when
> 		$action       : CheckProduct( $personId : personId, $productId : productId, $qty : qty,
> 							bookability == Bookability.NEW,
> 							confirmability == Confirmability.NEW)
> 	then
> 		log.warn("{} minta booking {} sebanyak {}, tapi tidak ada rule yang matching",
> 			{$personId, $productId, $qty});
> 		modify($action) {
> 			setMessage("Internal error: " + $personId + " check booking " + $productId +
> 				" sebanyak " + $qty + " namun tidak ada rule yang match. " +
> 				" Mohon laporkan ke customer support."),
> 			setBookability(CheckProduct$Bookability.ERROR),
> 			setConfirmability(CheckProduct$Confirmability.ERROR)
> 		}
> end
> {code}

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see: http://www.atlassian.com/software/jira


More information about the jboss-jira mailing list