Tuesday, January 31, 2017

Time to Drop Coyotes Season Tickets?


Coyotes season tickets are too expensive with little benefit anymore. There I said and anyone in Canada I am sure would start to go on a diatribe of how much THEY would have to spend for season tickets. But its not the cost of a ticket that makes its value, but its worth as a ticket and thats the problem. You may be 3-4 times the amount for a ticket in Toronto, but then you can also sell that ticket for 4-6 times that amount too. And herein lies the problem.

There is essentially 3 reasons to get season tickets.

1. Cost - Season tickets cost per game are less expensive than a regular face value for a ticket.
2. Guarantee - Guaranteed seat and guaranteed playoff seats.
3. Perks - this can be meet the team night, ice skate etc.

The problem I have been coming to none of these really apply to the coyotes anymore. And I ponder if this 5th year of owning season tickets will be my last, for now. Part of evaluating all this is also evaluating what would be the loss to drop season tickets for a few years and picking them up again later. The other part of the evaluation is I don't go to every game. There are 41 games a year and often 3-4 games in one week. Personally I also live on the opposite side of town so I often sell tickets not only to recoup costs but simply because I can't make every game.
So lets look at each of these.

Cost

This is a complex equation right here. While the Coyotes consistently have some of the lowest costs in the league per ticket, you still have to look at the cost per value and also price escalation. In addition the other factor to look at is if you decided to sell EVERY ticket would you come out ahead or behind. This can be a bit difficult to calculate because the coyotes scale there prices for the face value you pay the same for every game as a season ticket holder. So a ticket to the Penguins or Blackhawks on the weekend could easily cost 2 to 4 times the amount vs a ticket to the Panthers on a Tuesday. But in the end its a strong consideration to make as well as COULD you even sell your tickets for the face value at all.

Cost Increase

Lets first look at cost escalation when I first bought tickets for the Coyotes in 2012-13 season the cost was $45/seat plus free parking, the cost is now about $55/seat pluS $10 parking (if you buy it in advance) That represents a 33% increase in ticket cost in less than 5 years. Not sure about the rest of you but my salary has not gone up 33% in the last 5 years.
Keep in mind too what separates a market like Phoenix vs Edmonton as well is in Phoenix many of the season ticket holders are individuals whereas Edmonton you have a plethora of businesses who can absorb these costs more easily since they use tickets as perks and for sales teams.

Resale Cost

Resell represents what you can purchase tickets for on sites like Stubhub or Ticketexchange. These tickets are generally other season ticket holders reselling there tickets. The way this works is you list your tickets, they tack on a fee and then you get a portion of that money. With Ticketmaster Ticketexchange there is a fee on the front and back (meaning the price I list it for ISN'T what I am getting and you also pay an extra fee)
This year I routinely see tickets for sale for $30 for the lower level on Stubhub (including fees). This shows the value of tickets right now, very low. If you want upper level it can often be had for $10-12. In fact this year if you just like to watch hockey its probably the best time to start watching and take the family during the week. But this means much of MY ability to resell has diminished and I often have to take a loss on a ticket.

Specials Cost

This is a tricky one and one the Coyotes do have direct control over. What they (and many teams) usually do is run promotions for mid week games against opponents that don't have large turnouts. Usually these promotions are sponsored by various companies. One example of which is there "Coors Light Special". This offer runs eight Thursdays a year and allows one to buy tickets for $5 CHEAPER than season ticket holder cost. This is a double whammy, for one you are spending MORE as a season ticket holder than they are, for another if you want to resell your ticket on Ticketexchange it becomes virtually impossible. In fact I can't even list my ticket below $50, and thats not including the fees the other party would pay. So for 8 games a year I cannot easily sell my tickets,  and I know others are going to the games cheaper than I paid. 
In addition there are other specials this year that I've seen that offer bonuses like food, or signed stick, etc that while would be more expensive than my tickets offer perks others may commit to for the price.
This essentially means the only tickets I've easily been able to sell this year in the resale market are for premium games. 

Guarantees

This can be self explanatory but having a team that hasn't made the playoffs in 5 years and the last two (and this one) a team that is no where near making the playoffs the perk of playoff tickets is meaningless. And without a team that looks like its in contention for at least 3 years. The value isn't there. 
In addition the other guarantee of keeping my seats (which are good) can be complicated. If you have first row upper level you know someone will pick them up if you leave. While my row is D and I would take the risk of not being able to get row D again, E and certainly F would be easy to pick up in the future. So the loss of seats is not as risky as it would be in other arenas.

Perks

One of the best values to season tickets can be the perks. When I first started attending the coyotes games the perks were amazing:

  • Free Parking
  • Extra tickets at my cost
  • Guarantee to receive the giveaway promotions
  • Holiday Skate
  • Season Ticket Autograph signing
The first 3 of these perks have gone away, and the last two have diminished over time.

Parking is an obvious one its free and now I have to pay. So thats a $400/year extra cost if you buy them all in advance or $15/game. Now the thing here is that if you show up early enough or want to walk a bit you can park for free by parking in the movie lot. So people who pay for this either really like the team or just want the easiest and quickest exit points from a game. My only real complaint (besides having to pay) is the lack of flexibility in the parking. They give us 41 vouchers per year ... but you can't use more than one per game. This would be more understandable if the parking lots were ever anywhere near full. But I believe given everything else there should be more flexibility h3ere.


My second point, the "extra tickets at cost", what this references for any game in the past one could buy extra tickets to a game at our cost ($55) for the amount of seats we have tickets for. Now they began to scale it depending on game. Part of the reasoning for this was because Coyotes fans would sell there tickets to big games, then buy an extra pair so they could attend. The Coyotes apparently wanted this to increase revenue, and while I understand the spirit of it, its another in a list of items that were giving less of a reason to be a season ticket member.

Guarantee on the "giveaways". Every year, and every team does this they have promotional nights. Usually a bobblehead or something. More often its limited to 5-10k people. The Diamondbacks seem to do this every week, Coyotes do it a few times a year. One of the annoying things is you have to get to the game early, and for the games that are on the weekdays this can be hard to make it to on time, often i get to the arena at puck drop. Well before they would always hold you at least 1 of the items. So if you couldn't make the game, sold your tickets, or were just late ... you were always guaranteed to get the bobblehead or whatever it is. This was an extremely nice perk for those of us who support the team soo often. This is now gone.

Whats made matters worse is the schedule of the giveaways now. They now seem to have the best giveaways on sellout type games (Penguins/Blackhawks). Which baffles my mind since again they sell out and there is no reason to have giveaways for those games. But on the other side since most of us take a loss on too many games its our own games to recoup some of that loss, but now the reward for loyal season ticket holder is no bobblehead or whatever.


All things end ... or diminish

The cost vs benefit is really dying to be a season ticket holder, at this point you are either one out of loyalty or because you really want to go to EVERY game and sit in the same spot every time. I still haven't decided what I will do for next year. I currently have 3 season tickets + parking. At the least I will cut back to two season tickets and never use the coyotes parking again. Even then it will depend on the cost increases for next year (because they shouldn't be any)

If any coyotes front office is reading this, I am not the only one who feels this way despite what you pretend to believe. Many of us can take a losing team because we understand rebuilding. But what we can't take is an ever increasing cost for season ticket holders vs an ever decreasing cost for the casual fan. The metrics don't work out. And if you want to keep me and many others like me there needs to be change. This doesn't mean I will stop being a Coyotes fan, all it means is I will be spending much less money on the Coyotes. 











Tuesday, January 4, 2011

Groovy MetaClassing Issue?

Does someone want to explain this to me?

Or can?

Here is my basic problem. I have a class, it takes a method, i want to intercept it and depending on the object do something with it.

It can accept some kind of Collection usually.

Now here is the problem. You can use the object fine. But when you do something like "list as Set" ... when it hits the invokeMethod the arg is a PojoWrapper and NOT a Set object. Note if you called the method directly it is a Set.

This provides all sorts of problems, for one you cant do args[0].getClass() or it will thrown an NPE.

I tried to do just about anything to determine the variable when it is a PojoWrapper but everything threw an NPE.

Using groovy 1.7.5 ... cut and paste this into your groovy console and you will see


def a = [1,2,3]

def b = a as Set

t = new Temp()
t.stuff(a as Set)
println "*******"

t.metaClass.invokeMethod {String name, args ->
def ourVar = args[0]
println "name : $name / args : " + args[0]
if (ourVar instanceof Set) {
println "its a set"
}
else if (ourVar instanceof Collection) {
println "its a collection"
}
else if (ourVar instanceof org.codehaus.groovy.runtime.wrappers.PojoWrapper) {
println "Wrapper"
println ourVar
def list = []
list.addAll(ourVar)
println list.getClass()
}
//println ourVar.class
println "----"
}

t.joe(a)
t.joe(b)
t.joe(a as Set)

class Temp {

def stuff(t) {
println t
println t.getClass()
}

def invokeMethod(String name, args) {
println "huhg:: " + args
}
}


Tweak it, to me its pretty odd, i am using something similair in my code, and i can come up with a few hacks but none that are good. I'd really like to be able to determine what that PojoWrapper is.

Note if u do the as Set and set to a variable before hand it works fine.

Thursday, August 6, 2009

When NOT to use Injection in Seam

Seam has a very interesting and quite frankly very powerful and unique methodology for injection in the Java world. There injection methodology is a bit different in Spring in that it is done at method level (and the fact that Seam supports bi-jection as well). The injection works for services and for properties. So take the example below:



@Name("foo")
@Session
public class Foo implements FooService {

@In
UserTO user;

@In
UserService service;

public void process() {
service.run(user);
}
}



Here we are injecting a user and a service and can now have a seam component or a JSF page call this class. In fact they can both call this easily since there is nothing web specific in the definitions by having the transfer object "user" defined on there pages and then calling: foo.process(). The user being used will be injected as well as the service so they both will be accessible by the method.

This class can be a Stateless Session Bean or a POJO, which under normal circumstances could never handle a user specific class level variable. But with Seam it can. Why is this?

Method Level Injection
Simple. Seam intercepts everything at method invocation time. That way this code can work on classes that are usually stateless. Every time this method is called the bi-jection happens. So one can guarantee that multiple calls to the class will have access to the right user object. (based on scope)

Well that's great for transfer objects and domain objects, but what about that service up there? It's getting injected EACH time as well, which is fairly unnecessary. And each time you do it you are adding to the time it takes to run this method. For most web based applications that small overhead of injecting it will not be felt. However, what if you are using Seam to do some batch processing where you want to process multiple items per second. And what if the class you are using injects multiple services. That is where this scenario starts to show fatigue, and takes more time. This is the problem we were recently having at a client, we noticed an appreciable slowness due to this constant bi-jection of services. The time was enough we were processing 5 items per second instead of 10. so what's the answer?

Not Using @In
The answer is relatively simple. If the bean in question is a Stateless Session bean then use the normal @EJB for your services. Remember when using Seam we either define in the ejb-jar.xml or the Session Bean itself that Seam will be intercepting the Session bean. So when you use @EJB your service will still get injected with all the normal Seam bells and whistles; however, this will occur before the bean is given to the caller and not at method invocation time. The previous code would now look like this:




@Name("foo")
@Session
public class Foo implements FooService {

@In
UserTO user;

@EJB
UserService service;

public void process() {
service.run(user);
}
}



And if you using straight POJOs you can still make use of the @Create annotation and do a bit of coding to set the component yourself then. Just use the following to set the service:



Component.getInstance("serviceName")



Using the @EJB annotation not only helps performance but cleans up the code so that you know if you see @In it's for a transfer object that could be changing.

Tuesday, August 5, 2008

Beginning Groovy & Grails on Sale today only!!

Well i am assuming Apress has the most random site in the world at times.

But today only they have our recent book, Beginning Groovy & Grails for $10 (ebook)

Click here - http://www.apress.com/info/dailydeal

If you want to purchase it i suggest going before midnight tonight.

Tuesday, June 10, 2008

Authentication With Seam

One characteristics of modern web frameworks is to provide lots of functionality out of the box. This functionality ranges from authentication, to batch processing, to validation. For those of you who have used Seam's authentication framework, you know it is extremely easy to use. However, if you want to add some custom messaging in there, it is NOT as easy to use. We will go over here a work around to that issue. But first let's discuss how to create Seam authentication in general.

The main component to remember is the `Identiy` class. This will store the user, password, and provides the methods on it for logging in and out. This class is provided by Seam out of the box. In the first part we will create the login itself.

The login can be fairly simple and will use the `Identity` object. Here is a simple login form.

Partial of login.xhtml

<h:form id="login">
<h:inputText id="username" size="20" value="#{identity.username}" required="true"/>
<h:inputSecret id="password" size="22" value="#{identity.password}" required="true"/>
<h:selectBooleanCheckbox id="rememberMe" value="#{identity.rememberMe}"/>
<h:commandButton value="Login" action="#{identity.login}"/>


As you see everything here references the `Identity`, now thats just the first part. We need to tell Seam what class/method to use for authentication.
In your *components.xml* you will define an authentication method and class to call when `#{identity.login}` is called.

components.xml

<security:identity
authenticate-method="#{authenticator.authenticate}"/>


Then you simply define a Seam component named "authenticator" with a method "authenticate". By default Seam allows you to inject an object called `Identity` ( a Seam Session scoped component). The `Identity` object contains the username, password, and roles associated with the user, the first two will be used for logging in. A base skeleton of this code is here:

Authenticator.java


@Name("authenticator")
public class Authenticator
{
@In
Identity identity;

public boolean authenticate() {
// Do your database, ldap, etc lookup
// then return true/false based on if it was successful
}
}



Simple enough eh? It's simple and straight to the point. However, there is one **IMPORANT** thing to remember when using Seam Security. And that is Authentication != Login. This distinction will for the most part not effect you unless you want to start dealing with error messages.

By default there are two messages, a failure or successful login that are displayed by Seam automatically when an authentication passes/fails. Both of these are defined in the `message.resources` file as :

message_en.properties

org.jboss.seam.loginFailed=Login failed!
org.jboss.seam.loginSuccessful=Welcome


You can change the messages there. However, what if your requirements are more complex. What if you want to display a message that specifically the username or password is in correct, or if you are using something like LDAP or CAS, and you want to report that their servers are down. Simple enough right? Just do a `FacesMessage` context look up and add to it? Right? Wrong! What's the problem with this? You run a good chance that the error message will show up twice on the screen. While this isn't the worse thing to happen, it is a bit annoying. So why does this happen? The authenticator is just that its "authentication" it is NOT logging in. Meaning that the authenticator is actually called multiple times depending on the scenario and you do not necessarily have control over when and how often the authenticator is called.

So how do we fix this? Well the answer is, we do not write messages directly inside the authenticator. Instead, we will write login messages where they should be written, at login. So how do we do this while still using Seam's login? One way is to use a combination of the Seam Events/Observers and to write a "custom login".

The purpose of the Events/Observer, is actually quite interesting. You can write an event in one area of the code, and the Observer can pick it up based on a keyword in a separate class and process it. So in the authenticator you can add this line of code whenever you want to raise a specific message.


Events.instance().raiseEvent("invalidLogin", "Invalid password!!");


The first part of the method contains the key "invalidLogin", the second part displays whatever string we want to display to the front end. Please note, the actual method takes an array of Objects for it's second parameter, so you could pass as many strings, or whatever object you want to it.

We have now saved this event, now comes the part of retrieving it and storing it to the `FacesMessages`, this part is a BIT trickier, but not that bad. We need to create our own `Identity` class. The `Identity`, as I explained is the component that actually performs the logging in. But wait just earlier i said that `Identity` is a Seam level component. What we are going to do is basically extend the `Identity` class and then replace the component with ours. Lets take a look at our custom identity component.

CustomIdentity.java


@Name("org.jboss.seam.security.identity")
@Scope(ScopeType.SESSION)
@Install(precedence = Install.APPLICATION)
@BypassInterceptors
@Startup
public class CustomIdentity extends Identity {
private static final long serialVersionUID = -9154737979944336061L;

@Override
public String login() {
String retVal = "";
try {
// clear out the login message in case it was triggered
// by an authenticate occurring outside the login
loginErrorMessage = null;
retVal = super.login();
} finally {
// check if any error messages were registered from
// this logging., if they are write them out
if (StringUtils.isNotBlank(loginErrorMessage)) {
FacesMessages.instance().add(loginErrorMessage);
}
}
return retVal;
}

private String loginErrorMessage;

/**
* This is used to save off an error message in case of a login.
* @param message
*/
@Observer("invalidLogin")
public void writeInvalidLogin(String message) {
loginErrorMessage = message;
}
}



This code is a bit of a mouthful, but really not that hard to implement. The class level annotations are similar to the ones by default with `Identity` except we change the precedence to a later time. By default `Identity` has a `BUILT_IN` precedence. By changing it to `APPLICATION` we guarantee that our custom component will be the one used by Seam instead of Seam's `Identity` component.

The last method in the code defines the `Observer`. The `Observer` is called when the event is raised, so we are going to set it to a class level string.

Finally, you will see the login. It again is fairly straight forward as well. We are going to call the parent's login method (which is Seam's Identity login method) but after the login call we will check to see if any messages were saved by our Events/Observer pattern and if they are we will add them to the `FacesMessages`.

And that is it. You now will display errors the screen without them displaying multiple times.

While this is not the MOST straight forward way to add messages, it unfortunately is one of the ways you can do it in Seam. I have seen quite a few questions in the past at conferences and message boards about why dual messages are sent back. I hope this help explains it and shows you a way around the issue.

Saturday, April 26, 2008

Grails - Perfect for College Students


My three co-authors are starting to put the finishing touches on our Groovy and Grails book, which is out in June. Today we had to design the cover letter (which goes on the back) that tells the audience what this book is about and who its intended for.

Well it struck me as I was helping to write the how perfect Grails is not only for advanced Java users but for extremely basic Java users. The FACT remains despite what many might tell you, Java is strong in the work place and growing even stronger. And there is very good reasons for this, the Java stack can do things that some of the smaller more flexible dynamic stacks just can't do. For example one of the systems I am helping to write right now contains an extreme amount of nightly processing, this system is managed for its starts, the amount of beans running at a time, etc. My point is ... Java is needed for the system.

So where does Grails play into all this? Learning Java is actually fairly easy. Using it properly a bit harder, understanding the components used for applications and how to set up and create a Web 2.0 framework MUCH harder. (this is one are that Java gets rightfully dinged) Its quite the effort and beginners WILL get lost. Enter Grails. It not only sets everything up for you, but makes it easy to run and deploy, you don't even need to configure a database.

But not only that. It uses Spring and Hibernate, tools many Java developers use in their daily work. Now while it wraps much of the pains of both, the general ideas will still be there. Not to mention the clear separation of MVC and Services exists as well. In the end what Grails will give you an easier route to learn more advance items, and when it comes time to use any other Java framework out there you will have an easier time ramping up than your peers. Not to mention you will be able to intelligently talk about Web 2.0 Java development in interviews.


Wednesday, February 13, 2008

JBoss World Day 1


Today is the first day of JBoss World, I survived the first three presentations and waiting for the keynote to be  complete to do some of the "socializing" / "networking" aspect of this conference. Has gone very well so far. The first session on JBoss Clustering was quite interesting. Also attended Big Lots session. I was not going to at first, but it is always interesting to see what others are doing in the technologies one works with. I also even met two people from the company I used to work at when I was in Georgia (I knew one of the guys but did not recognize him at first)

All in all good soo far. I do find it weird how many of their sessions someone duplicate (like Seam). I hope by the time they get to my session people are not thinking, you know i am tired of Seam now.

At any rate, will post more later.