Gemini Community Support Site

This Gemini community support site can be used to find solutions to product issues. You can log in using Open Id, Google Profile and even Facebook. Feel free to ask a question or browse FAQs and documentation. Product tour videos are also available along with how-to videos demonstrating key Gemini capabilities.




Gemini Web services and PHP

api

Hi,

I'm trying to get PHP to consume the gemini web services but not having much look; Every corner I turn is a new challenge and I've gotten to the point where I need help :-p

When we were trialing Gemini it was on my local machine with no https or ssl and all of the web service intergration using PHP's SoapClient class worked perfectly.

Now the server is on a secure box over https using NTLM, it's a completely different story :-p. Basically the built in SoapClient in PHP doesn't work over HTTPS; After hacking Nusoap for 2 hours I realised I wasn't going to get anywhere with that either; Nusoap worked up to the point where it started whining about not using "wse:To" in the headers - I'm not a soap expert and have no idea what this means.

I've checked the URLs directly and I can access the WSDL through the browser but I must first authenticate using NTLM; Looking at the javascript example you have on the Authentication page in the seperate API section (http://api.countersoft.com/Authentication.aspx) I managed to get the basic result with the project listings and managed to figure out the ones over GET, however I'm having a little bit of trouble getting anything working over POST.

All I get is the "Welcome to the Gemini Projects REST API" response; I guess the XML i passed wan't correct but I'm not sure where I'd find that out? Is there somewhere that details what the structures should look like?

Many thanks, Chris

light2
· 1
light2
Replies (23)
helpful
0
not helpful

I'm not sure if our box is set up wrong as well; It appears in the http responses the URL is different to the one we called from (namely :8444 appearing after the domain); It appears IIS is running SSL/HTTPS over this port but I'm not sure why it keeps putting it in the url;

I had to change the gemini settings to force the correct URL to make the rest of the site work but during Soap requests all of the clients get confused as they try to post back to the wrong URL :-p

I'm no IIS guru so I've no idea what's going on...


light2
· 1
light2
helpful
0
not helpful

Which version of Gemini are you running?


Mark Wing
· 9108
Mark Wing
helpful
0
not helpful

I'd originally developed for 3.0 or 3.1 (can't remember), but the version we have is 3.5 - it appars there's a new api version of the web services :-p.

I started reverse engineering the Java classes into PHP classes and using the php versions of the http methods; So far I have it building XML requests and setting what I think are the correct headers but am getting a new error:

{"Exception":null,"Message":"The enclosed object does not appear to be a valid CounterSoft.Gemini.Commons.IssueEN","Type":400}

With the request being:

11111112TestMy Java test112

I've not started debugging this yet but it's a lot further than I had yesterday :-p


light2
· 1
light2
helpful
0
not helpful

Xml didn't work, lets try...

<?xml version="1.0" encoding="UTF8"?> <IssueEN><issueId/><projectId>1</projectId><projectCode/><issueTypeDesc/><issuePriorityDesc/><issueSeverityDesc/><issueStatusDesc/><issueResolutionDesc/><reportedByUsername/><fixedInVersionName/><issueType>1</issueType><issuePriority>1</issuePriority><issueSeverity>1</issueSeverity><issuePrioritySequence/><issueSeveritySequence/><issueStatusSequence/><issueStatus>1</issueStatus><issueResolution>1</issueResolution><reportedBy>1</reportedBy><fixedInVersion>2</fixedInVersion><issueSummary>Test</issueSummary><issueLongDesc>My Java test</issueLongDesc><dateRevised/><issueKey/><fixedInVersionNumber/><fixedInVersionDesc/><fixedInVersionOrder/><fixedInVersionArchived/><fixedInVersionReleased/><startDate/><dueDate/><resolvedDate/><closedDate/><riskLevel>1</riskLevel><votes/><estimateHours/><estimateMinutes/><riskLevelDesc/><visibility>1</visibility><visibilityMemberType>2</visibilityMemberType><parentIssueId/><issueComments/><issueCustomFieldData/><issueTimeEntries/><affectedVersions/><issueResources/><issueComponents/><componentsName/><componentsDesc/><componentsId/><issueTypeImagePath/><issuePriorityImagePath/><issueSeverityImagePath/><issueStatusImagePath/><hasRestrictedVisibility/><hasCommentsWithRestrictedVisibility/><isSubIssue/><isParentIssue/><dateCreated/><timeStamp/></IssueEN>


light2
· 1
light2
helpful
0
not helpful

Nope; Don't seem to be able to post xml here :-p

Lets try just the xml body:

11111112TestMy Java test112


light2
· 1
light2
helpful
0
not helpful

Okay - so I enabled no empty tags to prevent stuff like and now I get a new error:

{"Exception":{"InnerInnerMessage":"could not insert: [CounterSoft.Gemini.Commons.IssueBareEN][SQL: INSERT INTO geminiissues (projectid, issuetypeid, issuepriorityid, issueseverityid, issuestatusid, issueresolutionid, reportedby, fixedinversionid, summary, longdesc, revised, startdate, duedate, resolveddate, closeddate, issuerisklevelid, userdata1, userdata2, userdata3, percentcomplete, estimatedays, estimatehours, estimateminutes, visibility, visibilitymembertype, parentissueid) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?); select SCOPEIDENTITY()]","InnerInnerSource":"NHibernate","InnerInnerStack":" at NHibernate.Id.Insert.AbstractReturningDelegate.PerformInsert(SqlCommandInfo insertSQL, ISessionImplementor session, IBinder binder)\r\n at NHibernate.Persister.Entity.AbstractEntityPersister.Insert(Object[] fields, Boolean[] notNull, SqlCommandInfo sql, Object obj, ISessionImplementor session)\r\n at NHibernate.Persister.Entity.AbstractEntityPersister.Insert(Object[] fields, Object obj, ISessionImplementor session)\r\n at NHibernate.Action.EntityIdentityInsertAction.Execute()\r\n at NHibernate.Engine.ActionQueue.Execute(IExecutable executable)\r\n at NHibernate.Event.Default.AbstractSaveEventListener.PerformSaveOrReplicate(Object entity, EntityKey key, IEntityPersister persister, Boolean useIdentityColumn, Object anything, IEventSource source, Boolean requiresImmediateIdAccess)\r\n at NHibernate.Event.Default.AbstractSaveEventListener.PerformSave(Object entity, Object id, IEntityPersister persister, Boolean useIdentityColumn, Object anything, IEventSource source, Boolean requiresImmediateIdAccess)\r\n at NHibernate.Event.Default.AbstractSaveEventListener.SaveWithGeneratedId(Object entity, String entityName, Object anything, IEventSource source, Boolean requiresImmediateIdAccess)\r\n at NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.SaveWithGeneratedOrRequestedId(SaveOrUpdateEvent event)\r\n at NHibernate.Event.Default.DefaultSaveEventListener.SaveWithGeneratedOrRequestedId(SaveOrUpdateEvent event)\r\n at NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.EntityIsTransient(SaveOrUpdateEvent event)\r\n at NHibernate.Event.Default.DefaultSaveEventListener.PerformSaveOrUpdate(SaveOrUpdateEvent event)\r\n at NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.OnSaveOrUpdate(SaveOrUpdateEvent event)\r\n at NHibernate.Impl.SessionImpl.FireSave(SaveOrUpdateEvent event)\r\n at NHibernate.Impl.SessionImpl.Save(Object obj)\r\n at CounterSoft.Gemini.DataProvider.x73a34067f4cd229a.xf606eb5e1032d933(BaseEN x6fcb9c1c812a0558, Boolean x8b15d0e18e6888d9, ISession x45b53be31e53d68b)\r\n at CounterSoft.Gemini.DataProvider.x73a34067f4cd229a.xf606eb5e1032d933(BaseEN x6fcb9c1c812a0558, Boolean x8b15d0e18e6888d9)\r\n at CounterSoft.Gemini.DataProvider.x73a34067f4cd229a.xf606eb5e1032d933(BaseEN x6fcb9c1c812a0558)\r\n at CounterSoft.Gemini.DataProvider.xc0186e148e957052.x0dd7228622330700(IssueEN x22c77d60925997e9)\r\n at CounterSoft.Gemini.Business.x95da312ae9372c2e.x0dd7228622330700(IssueEN x22c77d60925997e9)\r\n at CounterSoft.Gemini.Presenter.IssuePresenter.CreateIssue(IssueEN issue)\r\n at CounterSoft.Gemini.Web.Api.IssuesRestHandler.IssueCreate(RequestDetails rd)","InnerInnerType":"NHibernate.Exceptions.GenericADOException","InnerMessage":"could not insert: [CounterSoft.Gemini.Commons.IssueBareEN][SQL: INSERT INTO geminiissues (projectid, issuetypeid, issuepriorityid, issueseverityid, issuestatusid, issueresolutionid, reportedby, fixedinversionid, summary, longdesc, revised, startdate, duedate, resolveddate, closeddate, issuerisklevelid, userdata1, userdata2, userdata3, percentcomplete, estimatedays, estimatehours, estimateminutes, visibility, visibilitymembertype, parentissueid) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?); select SCOPEIDENTITY()]","InnerSource":"NHibernate","InnerStack":" at NHibernate.Id.Insert.AbstractReturningDelegate.PerformInsert(SqlCommandInfo insertSQL, ISessionImplementor session, IBinder binder)\r\n at NHibernate.Persister.Entity.AbstractEntityPersister.Insert(Object[] fields, Boolean[] notNull, SqlCommandInfo sql, Object obj, ISessionImplementor session)\r\n at NHibernate.Persister.Entity.AbstractEntityPersister.Insert(Object[] fields, Object obj, ISessionImplementor session)\r\n at NHibernate.Action.EntityIdentityInsertAction.Execute()\r\n at NHibernate.Engine.ActionQueue.Execute(IExecutable executable)\r\n at NHibernate.Event.Default.AbstractSaveEventListener.PerformSaveOrReplicate(Object entity, EntityKey key, IEntityPersister persister, Boolean useIdentityColumn, Object anything, IEventSource source, Boolean requiresImmediateIdAccess)\r\n at NHibernate.Event.Default.AbstractSaveEventListener.PerformSave(Object entity, Object id, IEntityPersister persister, Boolean useIdentityColumn, Object anything, IEventSource source, Boolean requiresImmediateIdAccess)\r\n at NHibernate.Event.Default.AbstractSaveEventListener.SaveWithGeneratedId(Object entity, String entityName, Object anything, IEventSource source, Boolean requiresImmediateIdAccess)\r\n at NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.SaveWithGeneratedOrRequestedId(SaveOrUpdateEvent event)\r\n at NHibernate.Event.Default.DefaultSaveEventListener.SaveWithGeneratedOrRequestedId(SaveOrUpdateEvent event)\r\n at NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.EntityIsTransient(SaveOrUpdateEvent event)\r\n at NHibernate.Event.Default.DefaultSaveEventListener.PerformSaveOrUpdate(SaveOrUpdateEvent event)\r\n at NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.OnSaveOrUpdate(SaveOrUpdateEvent event)\r\n at NHibernate.Impl.SessionImpl.FireSave(SaveOrUpdateEvent event)\r\n at NHibernate.Impl.SessionImpl.Save(Object obj)\r\n at CounterSoft.Gemini.DataProvider.x73a34067f4cd229a.xf606eb5e1032d933(BaseEN x6fcb9c1c812a0558, Boolean x8b15d0e18e6888d9, ISession x45b53be31e53d68b)\r\n at CounterSoft.Gemini.DataProvider.x73a34067f4cd229a.xf606eb5e1032d933(BaseEN x6fcb9c1c812a0558, Boolean x8b15d0e18e6888d9)\r\n at CounterSoft.Gemini.DataProvider.x73a34067f4cd229a.xf606eb5e1032d933(BaseEN x6fcb9c1c812a0558)\r\n at CounterSoft.Gemini.DataProvider.xc0186e148e957052.x0dd7228622330700(IssueEN x22c77d60925997e9)\r\n at CounterSoft.Gemini.Business.x95da312ae9372c2e.x0dd7228622330700(IssueEN x22c77d60925997e9)\r\n at CounterSoft.Gemini.Presenter.IssuePresenter.CreateIssue(IssueEN issue)\r\n at CounterSoft.Gemini.Web.Api.IssuesRestHandler.IssueCreate(RequestDetails rd)","InnerType":"NHibernate.Exceptions.GenericADOException","Message":"Exception has been thrown by the target of an invocation.","Source":"mscorlib","Stack":" at System.RuntimeMethodHandle._InvokeMethodFast(Object target, Object[] arguments, SignatureStruct& sig, MethodAttributes methodAttributes, RuntimeTypeHandle typeOwner)\r\n at System.RuntimeMethodHandle.InvokeMethodFast(Object target, Object[] arguments, Signature sig, MethodAttributes methodAttributes, RuntimeTypeHandle typeOwner)\r\n at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks)\r\n at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)\r\n at CounterSoft.Gemini.Web.Api.x984df3e201a5cc4a.xd8c6760a50aeba18(RequestDetails x4f7dd955f6bfaf92, MethodInfo x2a154456227d18a2)","Type":"System.Reflection.TargetInvocationException"},"Message":"Exception has been thrown by the target of an invocation.","Type":500}

Which I guess means I picked some incorrect values :-p. getting closer :-p


light2
· 1
light2
helpful
0
not helpful

Yes, this will occur due to type id, priority, reporter etc.. not being a valid id (not in the types table etc..).


Mark Wing
· 9108
Mark Wing
helpful
0
not helpful

Just trying out the getIssue api and I seem to be able to get all the data back; I can see that the component arrays are encased in a block titled "ComponentsNH", I guess when I send the xml I should send my IssueComponentENs within those?


light2
· 1
light2
helpful
0
not helpful

Yes.


Mark Wing
· 9108
Mark Wing
helpful
0
not helpful

reading into the json populator code it appears it determines the type of object based on the argument required to the function, nooo!! hehe. Php goes crazy trying to enforce these types on methods so I ended up leaving them out.

Looks like the XML responses include the "class" names so I'll revert to using XML instead ;-p


light2
· 1
light2
helpful
0
not helpful

Hi, Still not having much luck sending data :-p

I'm not sure what the Java version was spitting out so I've not got anything to compare to but I've uploaded my request and response to pastebin (seen as they won't paste into here :-p)

http://pastebin.com/d65ad8759


light2
· 1
light2
helpful
0
not helpful

I copied out my generated xml and started removing each line one by one until the error dissapeared (somthing one of my old bosses taught me :-p); and voila:

It was the DateRevised entry; I guess you guys are creating an actual object based on the date string and because a value didn't exist it failed;


light2
· 1
light2
helpful
0
not helpful

During the transform between java and PHP I'd missed a "this->" on the setDateRevised method and wasn't setting what was coming from the database (My test was pulling out an existing issue and then just re-posting it)


light2
· 1
light2
helpful
0
not helpful

Good news, so is it working now?

I suggest using the Java demo to see the actual request XML for creating issue etc...


Mark Wing
· 9108
Mark Wing
helpful
0
not helpful

Yep. I've nearly re-written the entire Java demo in PHP :-D

I'm just looking at the projects and for some reason it doesn't work using project id but does work if I use project code...

Using: /api/projects.ashx/{projectId} as: /api/projects.ashx/18

Where 18 is a valid project id, as in - in the URLs from within gemini I see PROJID=18

I just get the "Welcome to Gemini API" message, but if I use the

/api/projects.ashx/code/{code} using: /api/projects.ashx/code/09-777

I get a valid ProjectEN structure back...


light2
· 1
light2
helpful
0
not helpful

Also get the same response trying to create a project:

Request

POST https://*/api/projects.ashx [?xml version="1.0" encoding="UTF-8"?] [ProjectEN][ProjectID]-1[/ProjectID][ProjectCode]12-345[/ProjectCode][ProjectArchived]0[/ProjectArchived][VersionCount]0[/VersionCount][IssueSeveritySchemeID]1[/IssueSeveritySchemeID][SchemeID]0[/SchemeID][ProjectLeader]13[/ProjectLeader][ComponentAssignmentMode]Single[/ComponentAssignmentMode][ProjectLeadName]Chris Lightfoot[/ProjectLeadName][IssuePrioritySchemeID]1[/IssuePrioritySchemeID][ResourceAssignmentMode]Single[/ResourceAssignmentMode][UserCount]0[/UserCount][FieldVisibilitySchemeID]1[/FieldVisibilitySchemeID][IssueTypeSchemeID]1[/IssueTypeSchemeID][ComponentCount]1[/ComponentCount][ProjectLabel]Internal Development[/ProjectLabel][ProjectLabelID][/ProjectLabelID][UserID]13[/UserID][ProjectDesc]Project description![/ProjectDesc][IssueWorkflowId]0[/IssueWorkflowId][ProjectReadOnly]0[/ProjectReadOnly][ProjectName]Test Project Creation[/ProjectName][GlobalSchemeID]2[/GlobalSchemeID][DateCreated]2009-07-01T10:46:31[/DateCreated][TimeStamp]AAAAAAAAC74=[/TimeStamp][/ProjectEN]

Response

HTTP/1.1 100 Continue HTTP/1.1 200 OK Date: Tue, 27 Oct 2009 14:33:59 GMT Server: Microsoft-IIS/6.0 X-Powered-By: ASP.NET X-AspNet-Version: 2.0.50727 Cache-Control: private Content-Type: text/html; charset=utf-8 Content-Length: 48

[h1]Welcome to the Gemini Projects REST API[/h1]

(I've converted lt and gt symbols to square brackets so I can post here)


light2
· 1
light2
helpful
0
not helpful

Lots of the other methods don't seem to work either; Getting versions, components, resources - it either returns an error saying invalid resource id or I get an empty array; i.e:

GET https://*/api/projects.ashx/1/components

[?xml version="1.0" encoding="utf-8"?][ArrayOfComponentEN xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" /]

I tried the .NET example with the same method and it successfully returns the 6 componets... not sure what I'm doing wrong.


light2
· 1
light2
helpful
0
not helpful

We're running version: v3.5.4 (Build 2435)


light2
· 1
light2
helpful
0
not helpful

You are missing projects from the URL:

https://*/api/projects.ashx/projects/1/components


Mark Wing
· 9108
Mark Wing
helpful
0
not helpful

YAY, It works. Heh.

I've not been following any of the other posts so I don't know if you know this already but the docs do say:

/api/projects.ashx/{projectId}/components

Thanks for the quick reply though; Cheers, Chris


light2
· 1
light2
helpful
0
not helpful

Thanks for letting us know. Will be fixed shortly.


Mark Wing
· 9108
Mark Wing
helpful
0
not helpful

Cool. Cheers.


light2
· 1
light2
helpful
0
not helpful

Maybe this will also be useful to sombody else:

When converting the classes in the Java example, in the ProjectEN class; the method names are used to determine the XML output and I copied this in my PHP code; Anyway there were 2 methods that used the wrong case for "ID".

(get/set)IssueWorkflowId should be (get/set)IssueWorkflowID (get/set)ProjectLabelID should be (get/set)ProjectLabelId

I'm not sure why the IDs aren't consistant but my generated XML was using the same case as the Java version and returning errors; after changing the case to the one given in the XML in the Java Example the command worked :-p


light2
· 1
light2