Adding an Easter Egg to Your App
A Zone Leader talks about how he added a simple "Easter Egg" to an application he built for a family member.
Join the DZone community and get the full member experience.
Join For FreeThose growing up in North America likely have a memory of the Easter Bunny — a mythical creature that magically left baskets or eggs filled with prizes for children. The concept of an Easter Egg Hunt pairs a group of children with a large area filled with hidden eggs. In some cases, the child with the most eggs found wins a prize. In other cases, the child which finds the single "golden egg" wins a prize too.
As you might expect, this idea of putting undocumented features (Easter Eggs) into a software program was destined to happen. Over the years, I have found myself seeking out such hidden gems and finally decided to add one into my mother-in-law's application as noted in my "New Application Journey" series.
Determining the Egg
For me, determining the content of the Easter Egg was simple. I wanted to replace the link behind the logo of the application to return a modal filled with random content from a collection of Instagram accounts. Once found, end-users of the application (which is basically just my mother-in-law) could see a random photo from one of our family members just by clicking the top left corner of her application:
API Updates
For the content retrieval of the Easter Egg, I decided I would use the Spring Boot RESTful API to create EasterEggData
to be used by the Angular client:
public class EasterEggData {
private String url;
private String caption;
private Calendar timestamp;
public String toString() {
return "easterEggData=EasterEggData(url=" + url + ", caption=" + caption +", timestamp=" + timestamp.getTime();
}
}
The Angular client would then call the /easterEgg
URI via a controller in the API project:
xxxxxxxxxx
name = "Easter Egg API") (
produces = MediaType.APPLICATION_JSON_VALUE) (
"hasAuthority('AppUser') || #oauth2.hasScope('openid')") (
public class EasterEggController {
private final EasterEggService easterEggService;
value = "/easterEgg") (
public ResponseEntity<EasterEggData> getEasterEggUrl() {
try {
return new ResponseEntity<>(easterEggService.getEasterEgg(), HttpStatus.OK);
} catch (Exception e) {
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
}
}
}
Client-Side Updates
On the client-side, I introduced a simple EasterEggService
:
xxxxxxxxxx
@Injectable()
export class EasterEggService {
constructor(private http: HttpClient) { }
baseUrl: string = environment.api + '/easterEgg';
getEasterEgg(): Observable<EasterEggData> {
const httpOptions = {
headers: new HttpHeaders({
'Authorization': 'Bearer ' + myToken
})
};
return this.http.get<EasterEggData>(this.baseUrl, httpOptions);
}
}
I created EasterEggData
on the client-side:
xxxxxxxxxx
export class EasterEggData {
url: string;
caption: string;
timestamp: number;
constructor() {}
}
Then, I wired the logo link to the following component:
xxxxxxxxxx
export class EasterEggModalComponent implements OnInit {
easterEggData: EasterEggData;
constructor(public activeModal: NgbActiveModal, private easterEggService: EasterEggService) { }
async ngOnInit() {
this.easterEggData = new EasterEggData();
this.easterEggService.getEasterEgg().subscribe(data => {
this.easterEggData = data;
});
}
}
Service Updates
With the basic wiring in place, I just needed to create the service-level work to populate the EasterEggData object. Without revealing the source of my personal data, the core processing logic is shown below:
xxxxxxxxxx
public EasterEggData getEasterEgg() throws AmhsException {
log.debug("getEasterEgg()");
EasterEggData easterEggData = new EasterEggData();
List<InstagramData.Edges> instagramData = getInstagramData();
if (CollectionUtils.isNotEmpty(instagramData)) {
RandomGenerator<InstagramData.Edges> randomGenerator = new RandomGenerator<>();
List<InstagramData.Edges> edges = randomGenerator.randomize(instagramData, 1);
easterEggData.setUrl(edges.get(0).getNode().getDisplay_url());
easterEggData.setCaption(edges.get(0).getNode()
.getEdge_media_to_caption().getEdges().get(0).getNode().getText());
easterEggData.setTimestamp(edges.get(0).getNode().getTimeStamp());
}
log.info("easterEggData={}", easterEggData);
return easterEggData;
}
In the example above, I am actually using RandomGenerator
as discussed in my "Building a Random Generator" series. In this case, there is a List<InstagramData>
that is being retrieved. The randomize()
method will return one item, at random, from this list and convert it to an EasterEggData
object.
Conclusion
When my mother-in-law clicks the logo link of her application, she will now see something like this:
Clicking the logo again will show something like this:
Every time the modal is requested in Angular, the image, caption, and original post date are all from a random Instagram post from one of our family members' accounts. My mother-in-law doesn't get out to Instagram very often, so this gives her a quick way to check in to see what she may have missed.
Have a really great day!
Opinions expressed by DZone contributors are their own.
Comments