[JBoss JIRA] Created: (JBPM-2702) MSSQL throws "Violation of UNIQUE KEY constraint" Exception when using Subprocesses
by Flavio Donzé (JIRA)
MSSQL throws "Violation of UNIQUE KEY constraint" Exception when using Subprocesses
-----------------------------------------------------------------------------------
Key: JBPM-2702
URL: https://jira.jboss.org/jira/browse/JBPM-2702
Project: jBPM
Issue Type: Bug
Security Level: Public (Everyone can see)
Components: Runtime Engine
Reporter: Flavio Donzé
Fix For: jBPM 4.x
We were using Postgresql and did now some tests using MSSQL. All processes containing subprocesses throw the following exception:
java.sql.SQLException: Violation of UNIQUE KEY constraint 'UQ__JBPM4_EX__C4971C0E06B7F65E'. Cannot insert duplicate key in object 'dbo.JBPM4_EXECUTION'.
at net.sourceforge.jtds.jdbc.SQLDiagnostic.addDiagnostic(SQLDiagnostic.java:368)
at net.sourceforge.jtds.jdbc.TdsCore.tdsErrorToken(TdsCore.java:2816)
at net.sourceforge.jtds.jdbc.TdsCore.nextToken(TdsCore.java:2254)
at net.sourceforge.jtds.jdbc.TdsCore.getMoreResults(TdsCore.java:631)
at net.sourceforge.jtds.jdbc.JtdsStatement.processResults(JtdsStatement.java:584)
at net.sourceforge.jtds.jdbc.JtdsStatement.executeSQL(JtdsStatement.java:546)
at net.sourceforge.jtds.jdbc.JtdsPreparedStatement.executeUpdate(JtdsPreparedStatement.java:505)
at org.tranql.connector.jdbc.PreparedStatementHandle.executeUpdate(PreparedStatementHandle.java:103)
at org.hibernate.id.IdentityGenerator$GetGeneratedKeysDelegate.executeAndExtract(IdentityGenerator.java:94)
at org.hibernate.id.insert.AbstractReturningDelegate.performInsert(AbstractReturningDelegate.java:57)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2176)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2656)
at org.hibernate.action.EntityIdentityInsertAction.execute(EntityIdentityInsertAction.java:71)
at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:279)
at org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:321)
at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:204)
at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:130)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:210)
at org.hibernate.event.def.DefaultSaveEventListener.saveWithGeneratedOrRequestedId(DefaultSaveEventListener.java:56)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:195)
at org.hibernate.event.def.DefaultSaveEventListener.performSaveOrUpdate(DefaultSaveEventListener.java:50)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:93)
at org.hibernate.impl.SessionImpl.fireSave(SessionImpl.java:563)
at org.hibernate.impl.SessionImpl.save(SessionImpl.java:551)
at org.hibernate.impl.SessionImpl.save(SessionImpl.java:547)
at org.jbpm.pvm.internal.model.DefaultIdGenerator.createId(DefaultIdGenerator.java:41)
at org.jbpm.pvm.internal.model.ExecutionImpl.initializeProcessInstance(ExecutionImpl.java:184)
at org.jbpm.pvm.internal.model.ProcessDefinitionImpl.createProcessInstance(ProcessDefinitionImpl.java:107)
at org.jbpm.jpdl.internal.activity.SubProcessActivity.execute(SubProcessActivity.java:69)
at org.jbpm.pvm.internal.model.op.ExecuteActivity.perform(ExecuteActivity.java:60)
at org.jbpm.pvm.internal.model.ExecutionImpl.performAtomicOperationSync(ExecutionImpl.java:637)
at org.jbpm.pvm.internal.model.ExecutionImpl.performAtomicOperation(ExecutionImpl.java:597)
at org.jbpm.pvm.internal.model.ExecutionImpl.start(ExecutionImpl.java:201)
at org.jbpm.pvm.internal.cmd.StartProcessInstanceInLatestCmd.execute(StartProcessInstanceInLatestCmd.java:65)
at org.jbpm.pvm.internal.cmd.StartProcessInstanceInLatestCmd.execute(StartProcessInstanceInLatestCmd.java:38)
at org.jbpm.pvm.internal.svc.DefaultCommandService.execute(DefaultCommandService.java:42)
at org.jbpm.pvm.internal.spring.CommandTransactionCallback.doInTransaction(CommandTransactionCallback.java:50)
at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:130)
at org.jbpm.pvm.internal.tx.SpringTransactionInterceptor.execute(SpringTransactionInterceptor.java:77)
at org.jbpm.pvm.internal.svc.EnvironmentInterceptor.execute(EnvironmentInterceptor.java:46)
at org.jbpm.pvm.internal.svc.RetryInterceptor.execute(RetryInterceptor.java:55)
at org.jbpm.pvm.internal.svc.ExecutionServiceImpl.startProcessInstanceByKey(ExecutionServiceImpl.java:78)
at com.softmodeler.service.impl.WorkflowService.start(WorkflowService.java:130)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:307)
at org.springframework.osgi.service.importer.support.internal.aop.ServiceInvoker.doInvoke(ServiceInvoker.java:58)
at org.springframework.osgi.service.importer.support.internal.aop.ServiceInvoker.invoke(ServiceInvoker.java:62)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:131)
at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:119)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.osgi.service.util.internal.aop.ServiceTCCLInterceptor.invokeUnprivileged(ServiceTCCLInterceptor.java:56)
at org.springframework.osgi.service.util.internal.aop.ServiceTCCLInterceptor.invoke(ServiceTCCLInterceptor.java:39)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.osgi.service.importer.support.LocalBundleContextAdvice.invoke(LocalBundleContextAdvice.java:59)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:131)
at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:119)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
at $Proxy68.start(Unknown Source)
at com.softmodeler.service.impl.BasicObjectRefService.createAndStartWorkflow(BasicObjectRefService.java:467)
at com.softmodeler.service.impl.BasicObjectRefService.commit(BasicObjectRefService.java:505)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.eclipse.riena.communication.core.hooks.AbstractHooksProxy.invoke(AbstractHooksProxy.java:69)
at org.eclipse.riena.communication.core.hooks.AbstractHooksProxy.invoke(AbstractHooksProxy.java:38)
at org.eclipse.riena.internal.communication.publisher.ServiceHooksProxy.invoke(ServiceHooksProxy.java:71)
at $Proxy71.commit(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.caucho.hessian.server.HessianSkeleton.invoke(HessianSkeleton.java:180)
at com.caucho.hessian.server.HessianSkeleton.invoke(HessianSkeleton.java:109)
at org.eclipse.riena.communication.publisher.hessian.RienaHessianDispatcherServlet.service(RienaHessianDispatcherServlet.java:148)
at org.eclipse.equinox.http.registry.internal.ServletManager$ServletWrapper.service(ServletManager.java:180)
at org.eclipse.equinox.http.servlet.internal.ServletRegistration.handleRequest(ServletRegistration.java:90)
at org.eclipse.equinox.http.servlet.internal.ProxyServlet.processAlias(ProxyServlet.java:111)
at org.eclipse.equinox.http.servlet.internal.ProxyServlet.service(ProxyServlet.java:67)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:820)
at org.eclipse.equinox.http.jetty.internal.HttpServerManager$InternalHttpServiceServlet.service(HttpServerManager.java:318)
at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:502)
at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:380)
at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:181)
at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765)
at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
at org.mortbay.jetty.Server.handle(Server.java:324)
at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:535)
at org.mortbay.jetty.HttpConnection$RequestHandler.content(HttpConnection.java:880)
at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:835)
at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:213)
at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404)
at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:409)
at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:520)
The exception is thrown in DefaultIdGenerator.createId() when calling session.save() of the ExecutionImpl. At that point ExecutionImpl does not have an ID. We use JTA Transaction types see attachment maybe this is the cause of the issue?
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: https://jira.jboss.org/jira/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
14 years, 6 months
[JBoss JIRA] Created: (JBPM-2694) JTA Transaction - couldn't lookup 'UserTransaction' from jndi
by Philip De Bock (JIRA)
JTA Transaction - couldn't lookup 'UserTransaction' from jndi
-------------------------------------------------------------
Key: JBPM-2694
URL: https://jira.jboss.org/jira/browse/JBPM-2694
Project: jBPM
Issue Type: Feature Request
Security Level: Public (Everyone can see)
Components: Runtime Engine
Affects Versions: jBPM 4.0, jBPM 4.1, jBPM 4.2
Environment: Application Server Oracle Weblogic 10.3
Java 6
DB2 v9
Windows XP Professional
Reporter: Philip De Bock
On Oracle Weblogic 10.3, the JTA transaction feature causes an exception.
org.jbpm.api.JbpmException: couldn't lookup 'UserTransaction' from jndi: Unable to resolve 'UserTransaction'. Resolved '': Unable to resolve 'UserTran
saction'. Resolved ''
at org.jbpm.pvm.internal.tx.jta.JtaTransaction.lookupFromJndi(JtaTransaction.java:137)
at org.jbpm.pvm.internal.tx.jta.JtaTransaction.lookupJeeUserTransaction(JtaTransaction.java:116)
at org.jbpm.pvm.internal.tx.jta.JtaRetryInterceptor.execute(JtaRetryInterceptor.java:42)
at org.jbpm.pvm.internal.svc.EnvironmentInterceptor.executeInNewEnvironment(EnvironmentInterceptor.java:53)
at org.jbpm.pvm.internal.svc.EnvironmentInterceptor.execute(EnvironmentInterceptor.java:40)
at org.jbpm.pvm.internal.svc.SkipInterceptor.execute(SkipInterceptor.java:43)
at org.jbpm.pvm.internal.cfg.ProcessEngineImpl.checkDb(ProcessEngineImpl.java:177)
at org.jbpm.pvm.internal.cfg.ProcessEngineImpl.buildProcessEngine(ProcessEngineImpl.java:170)
...
Default Weblogic JNDI reference = 'javax.transaction.UserTransaction' but jBPM 4.2 only support standard JEE specs ('UserTransaction').
With, jBPM 3.3, it's possible to override the jndi name value as a property in the jbpm hibernate config file (<property name="jta.UserTransaction">java:comp/UserTransaction</property>).
Ref : http://docs.jboss.org/jbpm/v3/userguide/deployment.html
I am not sure that jBPM 4.2 implements that solution.
I also know that "JTA Transactions" is in Incubation and is not documented in Developers Guide and that app-servers ohter than jBOSS are not assumed to be supported.
Does a actual solution or work-around exist for that problem with released 4.2 version ?
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: https://jira.jboss.org/jira/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
14 years, 6 months
[JBoss JIRA] Created: (JBPM-2840) NullPointerException when ExecutionImpl.createVariable() with isHistoryEnabled=true
by Huisheng Xu (JIRA)
NullPointerException when ExecutionImpl.createVariable() with isHistoryEnabled=true
-----------------------------------------------------------------------------------
Key: JBPM-2840
URL: https://jira.jboss.org/jira/browse/JBPM-2840
Project: jBPM
Issue Type: Bug
Security Level: Public (Everyone can see)
Affects Versions: jBPM 4.3
Reporter: Huisheng Xu
When I want to create a history enabled variable, the ProcessInstanceImpl will invoke variable.seValue(), in this method, variable will fire a VariableUpdate command. This command will try to get the HistoryVariableImpl and update it. But at this moment, the HistoryVariableImpl has not been created, so there will be a NullPointerException.
I think we should check whether the HistoryVariableImpl instance exists, then decide to update it or not.
The used code is like this:
ProcessInstance processInstance = executionService.startProcessInstanceByKey("Normal");
EnvironmentImpl environment = ((EnvironmentFactory)processEngine).openEnvironment();
((ExecutionImpl)processInstance).createVariable("test", "valuetest","string",true);
Session session = environment.get(Session.class);
Transaction tx = session.beginTransaction();
session.update(processInstance);
tx.commit();
environment.close();
The exception stack trace is like this:
15:27:28,703 SEV | [BaseJbpmTestCase] TEST THROWS EXCEPTION: null
java.lang.NullPointerException
at org.jbpm.pvm.internal.history.events.VariableUpdate.process(VariableUpdate.java:48)
at org.jbpm.pvm.internal.history.HistorySessionImpl.process(HistorySessionImpl.java:31)
at org.jbpm.pvm.internal.history.HistoryEvent.fire(HistoryEvent.java:62)
at org.jbpm.pvm.internal.history.HistoryEvent.fire(HistoryEvent.java:52)
at org.jbpm.pvm.internal.type.Variable.setValue(Variable.java:97)
at org.jbpm.pvm.internal.model.ScopeInstanceImpl.createVariableObject(ScopeInstanceImpl.java:140)
at org.jbpm.pvm.internal.model.ScopeInstanceImpl.createVariable(ScopeInstanceImpl.java:90)
at com.asset.jupiter.jbpm.processes.Normal.NormalTest.testCreateProcessInstance(NormalTest.java:33)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at junit.framework.TestCase.runTest(TestCase.java:164)
at org.jbpm.test.BaseJbpmTestCase.runTest(BaseJbpmTestCase.java:80)
at junit.framework.TestCase.runBare(TestCase.java:130)
at junit.framework.TestResult$1.protect(TestResult.java:106)
at junit.framework.TestResult.runProtected(TestResult.java:124)
at junit.framework.TestResult.run(TestResult.java:109)
at junit.framework.TestCase.run(TestCase.java:120)
at org.eclipse.jdt.internal.junit.runner.junit3.JUnit3TestReference.run(JUnit3TestReference.java:130)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: https://jira.jboss.org/jira/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
14 years, 6 months
[JBoss JIRA] Created: (JBPM-2584) Command execution problems: org.hibernate.MappingException: Named query not known
by Dominic Umbeer (JIRA)
Command execution problems: org.hibernate.MappingException: Named query not known
---------------------------------------------------------------------------------
Key: JBPM-2584
URL: https://jira.jboss.org/jira/browse/JBPM-2584
Project: jBPM
Issue Type: Bug
Security Level: Public (Everyone can see)
Affects Versions: jBPM 4.1
Environment: - jBPM Version : 4.1
- JBOSS Version: 5.0.0.GA
- Database : Oracle 11g
- JDK : java version "1.6.0_12"
- Configuration : original jbpm.cfg.xml
- Libraries : no additional libs
Reporter: Dominic Umbeer
While executing e.g. a FindProcessInstanceByIdCmd or FindProcessInstanceByKeyCmd it occured a org.hibernate.MappingException: Named query not known: findProcessDefinitionsById or org.hibernate.MappingException: Named query not known: findProcessDefinitionsByKey respectivly.
FindProcessInstanceByIdCmd and FindProcessInstanceByKeyCmd are the known commands with this problem. Maybe other commands are effected too.
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: https://jira.jboss.org/jira/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
14 years, 6 months
[JBoss JIRA] Created: (JBPM-2715) Missing elements in jpdl-4.3.xsd
by Florent Legendre (JIRA)
Missing elements in jpdl-4.3.xsd
--------------------------------
Key: JBPM-2715
URL: https://jira.jboss.org/jira/browse/JBPM-2715
Project: jBPM
Issue Type: Bug
Security Level: Public (Everyone can see)
Affects Versions: jBPM 4.3
Environment: Windows Vista, java 1.6, jboss 4.2.2.GA
Reporter: Florent Legendre
Priority: Critical
The xsd file for the jpdl has created validation errors in 4.0, 4.1, 4.2 and now also 4.3, but the difference is that the parsing of the jpdl has become more efficient in 4.3 and now throws an exception when defining an argument on a constructor element.
The main problem here is that the declaration of arg elements does not allow for any child, which means that you can define the type of the argument, but not its value, making it pretty useless.
Here are the extracts of the various problematic files:
jpdl-4.3.xsd (from line 921):
==========
<complexType name="argType">
<annotation><documentation>The method arguments.
Each 'arg' element should have exactly one child element
that represents the value of the argument.
</documentation></annotation>
<attribute name="type" type="string">
<annotation><documentation>The java class name representing
the type of the method. This is optional and can be used to
indicate the appropriate method in case of method overloading.
</documentation></annotation>
</attribute>
</complexType>
An example jpdl which would trigger the error (as the string element in the arg does is not valid based on the xsd):
=========================================================================================
<?xml version="1.0" encoding="UTF-8"?>
<process name="MyProsess"
version="1"
xmlns="http://jbpm.org/4.3/jpdl">
<start name="start">
<transition name="myTransition"
to="end">
<event-listener class="com.comp.MyEventListener">
<field name="myObjectField">
<object class="com.comp.MyObjectField">
<constructor>
<arg type="java.lang.String"><string value="hello world"/></arg>
</constructor>
</object>
</field>
</event-listener>
</transition>
</start>
<end name="end"/>
</process>
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: https://jira.jboss.org/jira/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
14 years, 6 months
[JBoss JIRA] Created: (JBPM-2746) Broken NON-LATIN characters in project/node names/values during the replication Process Definition to the DB
by Konstantin Kasatkin (JIRA)
Broken NON-LATIN characters in project/node names/values during the replication Process Definition to the DB
------------------------------------------------------------------------------------------------------------
Key: JBPM-2746
URL: https://jira.jboss.org/jira/browse/JBPM-2746
Project: jBPM
Issue Type: Patch
Security Level: Public (Everyone can see)
Components: Runtime Engine
Affects Versions: jBPM 4.1, jBPM 4.2, jBPM 4.3, jBPM 4.x
Reporter: Konstantin Kasatkin
Priority: Critical
Attachments: patch.zip
This issue is continuation of story described here https://jira.jboss.org/jira/browse/GPD-384
Please apply our patch over the source code.
It fixes improper treatment with non-latin character encoding during rooming process definition into DB.
Patch contains 2 modified classed from source code JBPM-4.2
Class StringStreamInput.java fixed by adding explicit encoding of source XML stream "UTF-8"
public InputStream openStream() {
byte[] bytes = string.getBytes();
return new ByteArrayInputStream(bytes);
}
changed to
public InputStream openStream() {
try {
byte[] bytes = string.getBytes("UTF-8");
return new ByteArrayInputStream(bytes);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
throw new RuntimeException("Unsupported encoding UTF-8");
}
}
Method checkKey(...) in Class ProcessDeployer.java fixed by commenting unnecessary replacing of non-latin characters to "_"
processDefinitionKey = processDefinitionName.replaceAll("\\W", "_");
changed to
processDefinitionKey = processDefinitionName;
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: https://jira.jboss.org/jira/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
14 years, 6 months