StructureCMS

April 14, 2015

Sitefinity First Thoughts

Filed under: .net, Programming — joel.cass @ 4:06 pm

I have been playing with Sitefinity for the last 2 weeks or so. Being from a Sitecore background I must say that it has been difficult to adjust, to say the least.

While not as slick, Sitefinity is a pretty capable content management system. It allows the website to be built from scratch without any HTML development, which is great, as long as you’re not working with a design company that is delivering HTML they want you to implement :)

So we enter the world of HTML rendering and development in Sitefinity, which unfortunately, is not so good.

There is basically no framework available for developing pages. It would be great if they copied the templates / sublayouts system in sitefinity, where placeholders could be used to define editable areas, and the areas configured in the parent template roll through to the children.

Sitefinity seems to take a “one size fits all approach”, which means that you have to use their modules, their styles, their naming conventions, their CSS.

So, what if:

  • You have an editable content area that appears in the navigation dropdown?
  • You have a responsive design that has been delivered with their own styles and contexts?
  • You only want to configure the navigation / css / and content that appears on all pages in one place?

None of these seem possible. Placeholders are only possible when put within master templates or using their bizarre patterns for layout widgets. It’s not as simple as putting an tag wherever you want.

Say that you have 3 templates – one for home, one for landing page, one for content. Essentially they all use the same outer elements – navigation, imagery, breadcrumbs. But the content layout changes – home is a complex layout, landing is one column with no side navigation, and the content page is two columns, with the left being a floating column.

I was hoping that I could either

  • Create a master page that has the outer elements configured and then implement the different layouts using nested master pages – not possible – even worse, the elements in the parent master page are no longer configurable
  • Use Layout Widgets to implement the different layouts – while this sort of worked I was unable to assign an ID to the element meaning the CSS would need hacking
  • Share configured ares between templates – I couldn’t find anything about it

So, what I’ve had to to is create 3 different master pages, that all need their own configuration. Not impressed so far.

Next, we’re onto integrating our Active Directory with Sitefinity. We were hoping that if the permissions were granted to certain roles, then they would be able to access the administration. But no, instead actual Sitefinity roles needed to be mapped to our equivalent roles and initialised upon startup, which was really frustrating.

And then we wanted to get onto creating our own role and membership providers because, surprise surprise, Sitefinity could not integrate with 2 different LDAP providers at the same time (which I admit is an edge case). We tried the ‘Data’ providers as recommended by Sitefinity and it was a living hell – because they were LINQ providers talking to a non-SQL platform, running a query to get a single user would get all (22,000+) records and then filter them down to one user – very ineffective. Furthermore only the membership provider was documented, the roles provider didn’t work and needed hacking, as discovered by other poor users.

In the end, implementing the standard ASP.net patterns for security providers worked, and it worked well. Heaven knows why the developers are recommending the implementation of data providers.

At any rate we have no choice but to keep rolling with the punches. I feel that choosing Sitefinity may not have been the best choice, but I’m hoping that this is just the usual sort of trouble that is experienced with new software and once we’re used to it, working with Sitefinity will be much easier than it is right now.

June 20, 2014

Entity Framework Headaches!

Filed under: .net — joel.cass @ 3:41 pm

I want to get away from query oriented code and especially the mess that can result from almost any ADO.Net implementation over time. I’ve been lucky to finally be able to work with the latest .net framework on a new project and thought I would give the Entity Framework (EF) a go. After all, it has worked quite well on other projects I have tried with MVC.

However, it seems that things are not so rosy when you come at it from a database-first perspective. Say that your database is designed by a proper DBA to have all the proper indexes, constraints, and data types in place, plus it’s locked down so you can’t manipulate with via code anyway. You would want to go database-first, right? Well, the tools we use should allow that.

I am using Visual Studio 2013, .net 4.5.1, and EF 6. And the experience has been anything but smooth.

First problem: Keys

Your Entity classes will not have keys. You will get the error “EntityType [Entity] has no key defined. Define the key for this EntityType”. But then you’re like, “the keys are there in the database! BLOODY HELL!”. So you look up, it seems you need to define the attribute [Key] above the field that represents the key in the database. Include the relevant namespace and you should be good to go, right? Wrong. Run a build and the class files are re-created, and changes are lost.

So what do you do? Open the edmx branch, find the relevant *.tt file, and:

Search for the string “simpleProperties”, then add the following like so (plus signs excluded):

var simpleProperties = typeMapper.GetSimpleProperties(entity);
    if (simpleProperties.Any())
    {
        foreach (var edmProperty in simpleProperties)
        {
+			if (ef.IsKey(edmProperty)) {
+				#>    [Key]
+<#		    }
#>
    <#=codeStringGenerator.Property(edmProperty)#>
<#
        }

..then, you will need to search for the method definition “UsingDirectives” and rewrite it as follows:

public string UsingDirectives(bool inHeader, bool includeCollections = true)
    {
        return inHeader == string.IsNullOrEmpty(_code.VsNamespaceSuggestion())
            ? string.Format(
                CultureInfo.InvariantCulture,
                "{0}using System;{1}{2}{3}",
                inHeader ? Environment.NewLine : "",
                Environment.NewLine + "using System.ComponentModel.DataAnnotations;",
                includeCollections ? (Environment.NewLine + "using System.Collections.Generic;") : "",
                inHeader ? "" : Environment.NewLine)
            : "";
    }

Build your project, and hopefully the classes come out right this time.

Second problem: Performance on bulk actions

OK, so it’s running now. Say that you want to do a bulk delete on a table that you were using for temporary data. Well, EF is not good at that at all. Deleting 2,000 records takes about 3 minutes. What about 20,000? Don’t even bother. So you’ll need to hack around it:

                /* TOO SLOW!
                IEnumerable<TempRecord> aryRecords = objContext.TempRecords;
                foreach (TempRecord r in aryRecords)
                {
                    objContext.TempRecords.Remove(r);
                }
                objContext.SaveChanges();
                */
                string strTableName = "TempRecord";
                DataContext.Database.ExecuteSqlCommand(String.Format("TRUNCATE TABLE {0}", strTableName));

So that works OK when connecting to the database, but what about when testing locally? Oops, next problem:

Second second problem: Database table names

When testing locally, the context will create a database using sqllocaldb.exe, that’s a nice idea. However this is where it fails: it creates the table names differently to the original schema. Say your table name was “TempRecord” (as some DB designers believe tables should NEVER be plurals), it will create the table in the temp database as “TempRecords”.

So begins the guessing game, as what makes it even worse is that the Entity Framework has NO METHOD FOR GETTING THE UNDERLYING TABLE NAME! DOUBLE BLOODY HELL!

So, what do you have to do? Run a fake query and then parse the SQL for the table name:

        public string GetTableName(DbSet dbset)
        {
            string sql = dbset.ToString();
            Regex regex = new Regex("FROM (?<table>.*) AS");
            Match match = regex.Match(sql);

            string table = match.Groups["table"].Value;
            return table;
        }

…and then update our preceding code:

                /* TOO SLOW!
                IEnumerable<TempRecord> aryRecords = objContext.TempRecords;
                foreach (TempRecord r in aryRecords)
                {
                    objContext.TempRecords.Remove(r);
                }
                objContext.SaveChanges();
                */
                string strTableName = objContext.GetTableName(objContext.TempRecords);
                objContext.Database.ExecuteSqlCommand(String.Format("TRUNCATE TABLE {0}", strTableName));

Another problem solved.

Third problem: Schema changes

Finally, what happens when the schema changes? Easy, you just update the EDMX from the database. It all works, then you decide to run some tests and you get the error “Model backing [Context] context has changed since database was created” TRIPLE BLOODY HELL. So, you delete all the files you can find that reference the old model. But that’s not actually the problem, it’s the test database!

So what can you do? What makes it even worse is that Visual Studio does not expose this test database in any way, it’s like the localdb instance is a dirty little secret it does not want to give away. You have to open the command prompt (or powershell in my instance as the SQLLocalDB.exe was not in my cmd path), and run the following commands:

// list databases (in my case, it was using "v11.0")
SQLLocalDB info
// stop database
SQLLocalDB stop v11.0
// delete database
SQLLocalDB delete v11.0

…and then run your test. Hopefully, Success!

Finally.

Even though this was horribly frustrating I feel that the EF is still the way to go. I just wish that Microsoft had spent that little bit of extra time QA’ing the database-first approach and the issues that arise in Visual Studio when testing using the local database. And it wouldn’t be a bad idea to have consistent underlying object (e.g. table) names, or at least expose them via the API somehow.

I don’t know where I’d be without the Internet, from which most of these problems were solved. It would be a long, difficult road otherwise. The Microsoft documentation leaves little to be desired from all fronts when it came to resolving these issues.

November 13, 2012

Month, day, and year are required…

Filed under: Linux — joel.cass @ 9:14 am

I had a bit of a brain fart earlier this week whilst trying to diagnose some SELinux issues. I had tried everything. Scanned the messages, audit log, used some tools like audit2allow, and for some reason I just could not get apache to talk to python. SELinux was blocking it, with nothing recorded anywhere. In the end I had to give up and set SELinux to permissive.

At any rate, I was banging my head against a wall with the ausearch program:

ausearch date format unknown

I was almost screaming, pulling my hair out! Geez, the response is so cryptic, the month, day, and year are there, I add the time and then it complains the time is not there! FFS! What date format do you want!!!! Gahhh!

Calm down Joel… Ok, so ausearch –help reveals nothing. What about man ausearch. Ah:

man ausearch

So it should be mm/dd/yyyy, not yyyy/mm/dd or dd/mm/yyyy. It’s making sense now. But why don’t they just state the format in the error message? It’s funny how the web is so focused on UX yet even the latest commands are stuck in the dark ages.

In the end it turned out that execute access was being blocked when python was run under the apache context, this was because I had compiled a special version of python to run with one of our legacy apps. A simple call to chcon to match the context of my compiled python with the installed python resolved the issue. It’s funny how neither audit2allow or scanning the messages and audit log showed the error I was looking for.

November 6, 2012

Sydney to Wollongong 2012

Filed under: Cycling — joel.cass @ 9:30 am

It’s over once again, and a big thanks to all who donated towards such a worthy cause. This year I have videotaped the entire thing and made a short movie about it. This is my first venture into movie making so excuse me if it’s a bit rusty:

This was a great ride and was enjoyed by all. It was great to be part of an excellent team.

October 26, 2012

Abusive bus drivers and ignorant call centres – does anyone know the road rules?

Filed under: Cycling — joel.cass @ 4:55 pm

Ignorant Bus driver It’s been a while since I posted here, mainly because I’ve either been too busy with work, away for holidays, or riding my bike in whatever free time I have. Part of my free time is spent on the commute to/from work. These days I’ve been trying to regain my fitness by riding to work, hence I haven’t had the capacity to post here.

Today is different. I’m catching a train and it’s because I’m still a little shaken from what happened yesterday. On the ride into work I was tailgated and abused by a sydney bus driver whilst I was riding into work.

Usually I do not have a problem with bus drivers, they are very courteous and usually once I pass them I never see them again anyway, due to the large number of stops on this road. However, yesterday was different. I was riding down Victoria Road toward the city. Things had been going pretty swell so far. I hit iron cove bridge and continued past the traffic at a high rate of speed, probably hitting around 45-50km/h for most of the stretch.

I could hear a honking in the distance. I figured it must have been one of those drivers that wants to get around the traffic by using the bus lane. I look back again and the number of cars seems to have dropped off but I still hear the honking. I pass an intersection and the last of the cars behind me turns off so it’s just a bus behind me now. Yet I still hear the honking.

I come to a stop behind another bus that takes off, I follow that bus and then the honking begins again. This time it sounds very close. I look behind me and there is a bus right on my tail. Literally inches away – perhaps 6-12 inches. I jump in shock, figuring that my life is in danger so I pull off and let the driver pass. Still he is honking at me.

He pulls over to pick up passengers at the top of the hill so I confront him and ask what his problem is. He states, “the bus lane is for buses, the bike lane is for bikes” or something like that with a few curse words thrown in. I ask him how the hell he got his license because knowing the rights of other road users is part of the test. I get no reply, I cannot remember what I said after this but by now I was quite upset so it was probably not very pleasant. I flip him the finger and continue on my way. He’s still honking.

I pull over and decide to report him. The lady at 131500 starts taking down details and then says something like “I’m pretty sure you’re not allowed to ride in bus lanes during peak hours”! I was truly shocked to hear this. I ask her to check. I’m sitting there for quite a while waiting for a reply. She comes back simply with an “I don’t know” answer. I continue to report exactly what happened as well as the bus number and my contact details, wanting the depot to contact me. 131500 lady says I can contact RTA for the road rules.

I call the RTA number 132243, and am greeted by another helpful lady, who once again thinks that bicycles shouldn’t be allowed to ride in bus lanes. I challenge this response and we start going through the legislation.

Road rules 2008, part 158, 2, c, i:

“158 Exceptions to driving in special purpose lanes etc
(2) The driver of any vehicle may drive in a bicycle lane, bus lane, tram lane, transit lane or truck lane if: (c) the driver is (i) riding a bicycle in a bus lane (other than a bus only lane), tram lane, transit lane or truck lane”

Oh, look at this, it seems cyclists can ride in bus lanes, and there does not seem to be any limitations on timing or circumstance. Reading this for what it is, it groups bicycles with buses, taxis, and motorbikes. So if a bicycle is not allowed in the bus lane, neither is a bus!

By now I’m truly pissed off. I want to bury this bus driver, I’m going to contact the police. I call them on 131444 and start to run through what happened. And what am I confronted with? “Oh, I’m pretty sure you’re not allowed to ride in bus lanes” – what the hell!!! I start going through the legislation, after which the lady says, “Oh, sorry I can not offer you any advice on that”, and then a couple of sentences later “but if you ever need any help on anything, you can call our number anytime.”. Help? define help! Were you helpful? Hell no. Not calling that number again.

So now I wait for a response from the depot. And maybe I will see if I can drop by a police station and log a formal report, regardless of the “legality” – I felt threatened and my life endangered. This is a huge failure of all NSW government departments I had contacted – it shows that there is a huge lack of education in all departments regarding the rights of road users, especially cyclists. Something seriously needs to be done about this.

Update: I was involved in another incident a week later, where a bus driver tried running me off the road (pictured). After this was reported the depot got back to me right away and unfortunately because the industry is so tightly unionized, the investigator can’t really do much, so he recommended I report them to the police. I called 131 444 again and this time got someone a bit more understanding. I still had to report it in person to a police office.

The people at the police office seemed a bit dismissive and needed some persuasion. I doubt much will be done, apparently the tapes are only kept for 2 weeks and it’s past that time now for the first incident. If anything at least a few drivers will learn that they can’t pick on cyclists.

And the shared use path following Victoria Road on the Iron Cove bridge is still closed.

July 17, 2012

Fuzzy result matching in Google – it sucks and there’s no way to stop it.

Filed under: Musings, Technology — joel.cass @ 9:41 am

Lately I’ve been having a lot of trouble finding the correct results on google. For example, a few weeks ago I wanted to know what is the quietest carriage (e.g. the carriage with the least number of people) on a peak hour cityrail train. So I search “what is the quietest carriage cityrail train” what are my results? Well, they completely ignored my request and figured I was looking for quiet carriages, not “quietest” carriages. So I get spammed with propaganda about quiet carriages.

Stupid google search results

Next, I tried searching “what is the +++++”quietest” carriage cityrail train” – no effect, same results..

Google shitty search results

So today after during my morning ride I noticed a light squeaking noise from the bottom bracket, so I searched for “squeaky bottom bracket”.. It decided to show results for “creaky bottom bracket”. I then try “+”squeaky” bottom bracket”. Same thing.

Google is not matching my keywords

The fix? Searching for “+”squeaky” bottom bracket -creaky” removed the offending results. But this is just plain stupid, this means that my results may not include pages that contain squeaky and creaky – what if the page I want contains both keywords?

Google tries in vain to render my search query

This reminds me of the days of the “excite” search engine – which was actually pretty good, until they started making the results fuzzy by just showing anything that matched any of your keywords. Then it just turned to shit. And where are they now? Gone.

Google, I hope you get your act together. I love it is free to search the web and lets face it, up to a few months ago the results were pretty good but it’s turning to rubbish. Even just having an option to disabled fuzzy searching would do for most of us!

January 27, 2012

Using the SmarterStats Query API service in ColdFusion

Filed under: ColdFusion, Programming — joel.cass @ 3:53 pm

I must admit that it’s been a while since I’ve posted anything in this blog. To be honest, it’s mainly because there’s been nothing remarkable to post about. Nothing anyone would benefit from knowing, really.

It’s even to the point that my role involves much more than just programming these days – recently I have been involved in reviewing web statistics packages in the hope of landing on a solution. Well, the solution is found in SmarterStats – quite a remarkable web statistics package that does most things. It even has an API.

About that API – it has a largely undocumented ‘Query’ webservice. It is not enabled by default, but once enabled it allows you to query the statistics data via a web service.

To enable the service, you will need to create an authorisation key. A good one to use is a UUID. Then, you need to define that key in [SmarterStats_Root]\MRS\App_Data\Config\AppConfig.xml:

    <LocalHostDeleted>false</LocalHostDeleted>
++  <WebServiceAuthorizationCode>nnnnnnnn-nnnn-nnnn-nnnnnnnnnnnnnnnn</WebServiceAuthorizationCode>
    <ExpirationNotification />

Then you can access the service via http://localhost:9999/Services/Query.asmx, WSDL path http://localhost:9999/Services/Query.asmx?wsdl

The query service uses some form of psuedo-sql that runs a query against what looks like a function result, ie. SELECT * FROM fTableName(siteId, dateFrom, dateTo, maxItems, extraParam**) WHERE blah=blah ORDER BY blah.

** Parameters maxItems and extraParam are undocumented and were found by chance. MaxItems is pretty obvious, it’s the number of records to retrieve. Use extraParam to filter certain queries by page. Only certain queries support the extra parameter so try them out.

A list of tables is available in the file [SmarterStats_Root]\MRS\App_Data\Config\ReportConfig.xml – you can copy this to your development directory and then use it to generate a list of available reports.

Here are some example reports you can call using the web service (assume site id = 1):

  • Get Daily Site Traffic
    SELECT * FROM fActivityTotalTrend(1, '2012-01-01T00:00:00', '2012-01-27T00:00:00', 50)
  • Get Daily traffic to home page
    SELECT * FROM fDailyActivityForFile(1, '2012-01-01T00:00:00', '2012-01-27T00:00:00', 20, '/')
  • All pages, ordered by popularity
    SELECT * FROM fTopPages(1, '2012-01-01T00:00:00', '2012-01-27T00:00:00')
  • Top 10 most popular pages
    SELECT * FROM fTopPages(1, '2012-01-01T00:00:00', '2012-01-27T00:00:00', 10)
  • Web browsers
    SELECT * FROM fBrowsers(1, '2012-01-01T00:00:00', '2012-01-27T00:00:00')
  • Visitors by City
    SELECT * FROM fGeographicCountryByCity(1, '2012-01-01T00:00:00', '2012-01-27T00:00:00')
  • Visitors by City, to a certain URL
    SELECT * FROM fGeographicsByFile(1, '2012-01-01T00:00:00', '2012-01-27T00:00:00', 20, '/some/url/')

Calling the web service from coldfusion is pretty easy:

<cfsetting enablecfoutputonly="true">

<!--- 'static' service parameters --->
<cfset strUsername = "username">
<cfset strPassword = "password">
<cfset strAuthCode = "nnnnnnnn-nnnn-nnnn-nnnnnnnnnnnnnnnn">
<cfset strWebServiceUrl = "http://127.0.0.1:9999/Services/Query.asmx?wsdl">

<!--- initialise web service --->
<cfset objWebService = createObject("webservice", strWebServiceUrl)>

<!--- query parameters (you can pass these in from a form) --->
<cfset strReport = "fTopPages">
<cfset numSiteId = 1>
<cfset dateFrom = createDate(year(now()), month(now()), 1)>
<cfset dateTo = createDate(year(now()), month(now()), day(now()))>
<cfset numRows = 20>

<!--- compose query --->
<cfset strQuery = "SELECT * FROM #strReport#(#numSiteId#, '#dateformat(dateFrom,'yyyy-mm-dd')#T00:00:00', '#dateformat(dateTo,'yyyy-mm-dd')#T00:00:00')">

<!--- execute query --->
<cfset dsResult = objWebservice.executeQuery(strUsername, strPassword, strAuthCode, numSiteId, strQuery, numRows)>

<!--- convert to query --->
<cfset qryResult = datasetToQuery(dsResult, 'Table1')><!--- version 7: it is 'Table1', version 6: it is 'results' --->

<!--- output result --->
<cfdump var="#qryResult#">

<!--- FUNCTION TO CONVERT .NET DATASET TO QUERY (added here for convenience - move to helper class) --->

<cffunction name="datasetToQuery" access="public" returntype="query" output="false">
	<cfargument type="any" name="dataset" required="true">
	<cfargument type="string" name="tablename" required="true">

	<!--- dataset has 2 nodes: 1) Column definitions 2) Data --->

	<cfset var qryResult = "">
	<cfset var lstColumns = "">
	<cfset var lstTypes = "">
	<cfset var aryDataset = ARGUMENTS.dataset.get_any()>
	<cfset var aryColumns = XmlSearch(aryDataset[1].getAsString(), "/xs:schema/xs:element[@name='#ARGUMENTS.tablename#']/xs:complexType/xs:sequence/xs:element")>
	<cfset var aryData = XmlSearch(aryDataset[2].getAsString(), "/diffgr:diffgram/NewDataSet/#ARGUMENTS.tablename#")>
	<cfset var i = 0>
	<cfset var c = 0>

	<!--- get columns --->
	<cfloop from="1" to="#arrayLen(aryColumns)#" index="i">
		<cfset lstColumns = listAppend(lstColumns, aryColumns[i].xmlAttributes.name)>
		<cfswitch expression="#aryColumns[i].xmlAttributes.type#">
			<cfcase value="xs:double,xs:long">
				<cfset lstTypes = listAppend(lstTypes, 'double')>
			</cfcase>
			<cfcase value="xs:date">
				<cfset lstTypes = listAppend(lstTypes, 'timestamp')>
			</cfcase>
			<cfdefaultcase>
				<cfset lstTypes = listAppend(lstTypes, 'varchar')>
			</cfdefaultcase>
		</cfswitch>
	</cfloop>

	<!--- create query object --->
	<cfset qryResult = queryNew(lstColumns, lstTypes)>

	<!--- populate query --->
	<cfloop from="1" to="#arrayLen(aryData)#" index="i">
		<cfset queryAddRow(qryResult)>
		<cfloop from="1" to="#arrayLen(aryData[i].xmlChildren)#" index="c">
			<cfset querySetCell(qryResult, aryData[i].xmlChildren[c].xmlName, aryData[i].xmlChildren[c].xmlText)>
		</cfloop>
	</cfloop>

	<cfreturn qryResult>
</cffunction>

<cfsetting enablecfoutputonly="false">

All this was tested in SmarterStats 7.

November 7, 2011

Sydney to Gong – a big thanks

Filed under: Cycling — joel.cass @ 7:58 am
The Cellarbrations Team

Sydney to gong is over again, and thank you all who have supported me and helped fundraise over $400.

This year was different, as I wasnt riding alone this time, but instead as part of “team cellarbrations”, affiliated with the LACC and my previous employer, metcash.

What also made this year different was the lack of sleep, as it just happened that the Janet Jackson concert was the night before. With only 3 hours of sleep, it was a bit of a stretch for me.

At any rate, I managed to better last years’ attempt, having arrived before 9am. According to the speedo it was about 2 hrs and 38 minutes. It was different riding in a team but just as enjoyable.

September 14, 2011

Sydney to Gong – It’s on again!

Filed under: Cycling — joel.cass @ 4:20 pm



It’s on again!

I have entered the 2011 MS Sydney to the Gong Bike Ride and have committed to fundraise $1000.00 in support of people living with Multiple Sclerosis. This year MS Australia aims to raise $4.5 Million through the event, and I want to play my part and “ride for a purpose”.

Multiple Sclerosis is a disease of the central nervous system affecting more young adult Australians than any other neurological condition. Your donation will go directly towards providing a wide range of services and support to people living with MS.

Did you know?
- The average age of diagnosis of MS is just 30 years
- 3 times more women than men are affected by MS
- An estimated 20,000 people in Australia have MS
- There is no known cause or cure

Please take a moment to view my online fundraising web page and help me reach my goal. It”s quick and easy. You can donate securely online using your credit card by clicking on the link below:
http://register.gongride.org.au/2011-Sydney-to-Gong-Ride/jozza81/e

All information is secure and all donations will be sent electronically to MS Australia ACT/NSW/VIC. A tax-deductible receipt will automatically be emailed to you once the donation is verified.

Your support is greatly appreciated.

August 17, 2011

ColdFusion on Linux – Make sure your hostname is correct!

Filed under: ColdFusion, Technology — joel.cass @ 10:52 am

Recently I have been given the task to install ColdFusion on CentOS. Everything went well, Apache installed fine, related dependencies installed fine, even ColdFusion installed fine. Until I tried accessing the site, upon which I was presented with this error:

java.lang.NullPointerException
	at java.lang.String.indexOf(String.java:1733)
	at java.lang.String.indexOf(String.java:1715)
	at jrun.servlet.session.SessionService.getUrlSessionID(SessionService.java:1097)
	at jrun.servlet.ForwardRequest.getRequestedSessionId(ForwardRequest.java:426)
	at jrun.servlet.ForwardRequest.isRequestedSessionIdValid(ForwardRequest.java:467)
	at jrun.servlet.ForwardRequest.getSession(ForwardRequest.java:344)
	at jrun.servlet.ForwardRequest.create(ForwardRequest.java:135)
	at jrun.servlet.JRunRequestDispatcher.invoke(JRunRequestDispatcher.java:253)
	at jrun.servlet.ServletEngineService.dispatch(ServletEngineService.java:543)
	at jrun.servlet.http.WebService.invokeRunnable(WebService.java:172)
	at jrunx.scheduler.ThreadPool$ThreadThrottle.invokeRunnable(ThreadPool.java:428)
	at jrunx.scheduler.WorkerThread.run(WorkerThread.java:66)

I had installed ColdFusion 9, in a similar method to that described here. So, I tried installing ColdFusion 8 following the same method. Still got the error. I then tried installing ColdFusion 9 to use the root user (not recommended). Still got the error.

So I pulled my hair out for a bit, and then started scanning logs, upon which I came across this line:

08/16 23:23:54 error centostemplate.xxxx.xxx.au: centostemplate.xxxx.xxx.au
java.net.UnknownHostException: centostemplate.xxxx.xxx.au: centostemplate.xxxx.xxx.au

…and then it all fell together! The instance I had been given was created off a template, in which the host name was set in /etc/sysconfig/network to ‘centostemplate.xxxx.xxx.au’ – which did not resolve via DNS! So, the easy fix was to map this over in /etc/hosts to localhost, i.e.

127.0.0.1    centostemplate.xxxx.xxx.au

Restart the services, fixed! This is CentOS in my case, but I think if you ever run into this problem on a *nix platform, check your network config and ensure that your configured hostname resolves to an IP address.

Older Posts »