Xomino

Domino with the new improved X

Practice what you preach – be fast and look sexy

Posted by MarkyRoden on December 16, 2014

As people who know me well may have heard once or twice, user experience is everything. When designing a custom web based application for a customer, there is always an unwritten requirement of “look sexy” and be fast.

This week my team and I at PSC successfully rolled out a new global application to a customer and here are some examples of the feedback we received within the first day or so:

  • I tried the new site only this morning and I have only one word: fantastic! It is very user friendly and fast.
  • …not to mention, based on the feedback from partners in the US and leaders across the world, it is the best system they have seen in the company.
  • …thanks for all your efforts! Looks “sexy” so (sponsor) is definitely pleased.

Not a single mention of how the functionality will meet their business needs. Not a thought for how well we have met their requirements. We have done that, but that would be irrelevant if we had delivered a poor looking, slow, but highly functional website.

To achieve the speed we were looking for the application is built primarily on Angular.js and Domino Data. Minimizing the amount of server processing for any given user interaction and minimizing the network traffic necessary to provide the expected response time, was a prime consideration in designing the architecture. Working with the talented design team at PSC and the customer we were able to create a visual user experience which adhered to the company’s strict style guides but looked “sexy”.

Be fast, look sexy, and make users want to tell their friends.

Posted in Angular.js, Just Marky, PSC | 8 Comments »

BTE 102: The Future of Web Development Write Once, Run Everywhere with AngularJS and Domino

Posted by MarkyRoden on December 16, 2014

Mark Leusink and I are very excited to be presenting a session at ConnectED this coming January. This is a great opportunity to come and find out about something a little different from the normal XPages run of the mill development. Mark and I will provide an introduction to the concepts and structure behind Angular.js, and then demonstrate how to build a very simple yet useful application using Angular.js and a Domino data store.

We are also going to blow some minds by showing the same application running on non-Domino platforms. If architected correctly, this transformation can be made with almost no code refactoring at all.

Come and see us in Orlando !

http://www.ibm.com/software/collaboration/events/connected/

Marky, Mark

 

Track: Beyond the Everyday

Abstract

AngularJS is currently the most popular JavaScript MVC framework. It’s driving more adoption and interest in the MVC/ REST API application architecture model. The ease of use, portability and re-usability of the code makes it an ideal solution for modern web developer needs. We’ll show you how to use AngularJS to modernize your existing Domino apps, while leveraging Domino’s best features. The speakers will also demonstrate how the power of architecting a solution based on AngularJS allows your Domino application to be made available through other platform interfaces. Taking “Write once, run everywhere” in the literal sense, you will see the same Angular/ Domino based app running natively in XPages, IBM Connections, Bluemix, IBM Worklight and more. Client-side JavaScript frameworks such as AngularJS are the future of web development – come and see it in action. 

Posted in Angular in XPages, Angular.js, IBMConnect | Leave a Comment »

Angular in XPages: Formatting Domino Data Services Date values with app.filter

Posted by MarkyRoden on December 14, 2014

In this article I will show how we can use the core angular date filter capabilities to format Date format, Domino data into an Angular.js based application

Introduction

In previous articles I have shown how to create a simple Angular.js application using a notes Domino Data Services feed from a notes database. If we want to add “date” information then we need a way to nicely format it. Using the Angular.js documentation page as reference I will show you how we can do this with Domino data.

Adding dates to our view

When we add a date field to a Domino Data Services feed we get something which is to the human eye pretty “ugly”

a1

And when we add lastModified into our template, it is well, less than appealing….

a2

 

Adding a formatting function to the template

We can modify the template to use a formatting function by changing up the template slightly and then adding a formatting filter to the application.

In the app.js we add the following

personApp.filter("formatDate", function () {
    return function (x) {
        return new Date(x);
    };
});

And then we reformat the template as such:

    <tr ng-repeat="person in people"  on-last-repeat>
        <td>{{person.firstname}}</td>
        <td>{{person.lastname}}</td>
        <td class="zipCode">{{person.zip}}</td>
        <td class="user">{{person.username}}</td>
        <td class="user">{{person.lastModified | formatDate | date:"dd MMM yyyy" }}</td>
        <td><a class="btn btn-info" href="#/person/{{person['@unid']}}">Edit</a></td>
        <td><a class="btn btn-warning" href="#/person/{{person['@unid']}}/delete">Delete</a></td>
    </tr>

The critical part is {{person.lastModified | formatDate | date:”dd MMM yyyy” }}.

The documentation unfortunately is not clear on this and I found this Stackoverflow example which worked perfectly. http://stackoverflow.com/a/25856275/1171653

The resulting page now looks formatted and much easier to read

a3

Conclusion

I spent which a lot of time failing to achieve this date formatting without doing it the angular way. One quick google (or three) and I had the answer. Do it the angular way and oo look that that nice and simple formatting.

Posted in Angular in XPages, Angular.js, XPages | Tagged: , | 2 Comments »

Looking forward to IBM ConnectED – AD201: IBM Domino Applications in Bluemix

Posted by MarkyRoden on December 11, 2014

The session preview tool for ConnectED 2015 has been announced.

https://www-950.ibm.com/events/global/ibmced/agenda/preview.html

Looking through it I found the following abstract – which unsurprisingly has me really excited !!!

AD201: IBM Domino Applications in Bluemix

This session will show how Bluemix enables you to deploy Domino applications to the cloud in a matter of minutes. We will demonstrate how to leverage Bluemix buildpacks like XPages and Node.js both to modernize Domino applications and to give them a new home on a highly scalable and resilient PaaS. You will learn how to mix and match Bluemix runtimes and services to create Domino cloud apps rapidly, stage them privately and put them into production. You’ll see how to use cutting edge tooling to monitor and manage your apps. This is the future.

Presented by the XPages boys themselves – Martin Donnelly and Tony McGuckin

From Martin on Twitter –  “@MarkyRoden: it will be both me and @tonymcguckin presenting. Glad it’s caught your interest – should be lots of new stuff to see here :-)”

This is what I have been hoping for since it was announced that IBM were “investigating it” at MWLUG back in August 2014.

XPages buildpacks, mix and match run times – I might just be in developer heaven if this is as good as it sounds !!!

Save me a front seat I will be there !!!!

Posted in Bluemix, IBMConnect, XPages | 4 Comments »

Websockets in XPages: Improving on the automated partialRefresh interface

Posted by MarkyRoden on December 9, 2014

In this article I will further discuss how tom improve the user experience of an automated partial Refresh on an user’s XPage. Although these posts were originally about using Bluemix to host the node.js server I kinda feel that the focus has drifted onto websockets more than Bluemix. So in an attempt to make it easier to find I am going to use the Websockets in XPages title moniker for a few posts and then go back to Bluemix :)

Introduction

In the last article we looked at how to push a automated partialRefresh to a XPage application using websockets. In that article it was noted that the user experience was not ideal because the whole panel refreshed without the user knowing about it. For some apps that is appropriate and for others it may not be. At this point in his career Dave Leedy is impressed he gave someone else and idea and I quote: “wow! that’s fricken awesome!!!”

So, that’s not a great user experience – what if they were doing something at the time?

Yes I was thinking that too! So I believe we can improve the user experience a little and take what Dave suggested and tweak it a little. Now where have a seen something which let’s the user know there is new data changes but doesn’t refresh the page without their action……….

b4

oh yeah that.

Instead of refreshing the control automatically, we will make the message create a “refresh” icon on the page which the user can then update at their leisure.

b5

The modified code is all in what happens when the page receives the refresh socket message. I added a jQuery rotate function just for some added “je ne sais quoi“. In the function we can see that when the refresh event is detected by the socket code the refreshControl function is called. This in turn makes the hidden refreshIcon visible, adds an onClick event and then rotates it. The onClick event performed the partialRefreshGet as we saw in the previous example turning the page briefly grey. We then hide the icon and remove the click event (to avoid piling on multiple events as the page gets continually refreshed)

 

 // Function to add a message to the page
  var refreshControl = function(data) {

	  $('.refreshIcon')
	  	.css({display: 'block'})
	  	.on('click', function(){
	  	   var temp = $('[id*='+data.refreshId+']').css({background: '#CCCCCC', color: 'white'}).attr('id')
		   XSP.partialRefreshGet(temp, {})
		   $(this).css({display: 'none'}).off('click')
	  	})
	  	.rotate({
	      angle:0,
	      animateTo:360,
	      easing: function (x,t,b,c,d){        // t: current time, b: begInnIng value, c: change In value, d: duration
	          return c*(t/d)+b;
	      }
	   })
  };

  // When a refresh message is received from the server
  // action it
  socket.on('refresh', function(data) { refreshControl(data); });

The following video quickly demonstrates the new capability.

Conclusion

In this brief article we concentrated on how to improve a user experience by notifying them that changes were pending and then allowing them to determine when the changes were made.

I still don’t think this is as optimal as I would like but you get the idea. As I said a long time ago - the more DOM you are reloading the worse the user experience. With a viewPanel we are kinda limited on what we can and cannot refresh. A better option may be to architect the application just the new data and update as appropriate……….

 

Posted in Bluemix, node.js, WebSockets, WebSockets in XPages, XPages | Tagged: , , , | 6 Comments »

XPages and Bluemix: Pushing out data changes through automated partialRefresh

Posted by MarkyRoden on December 7, 2014

In this article I will demonstrate how using targeted websockets messages we are able to refresh user data on pertinent screens within an application, and keep user’s data up to date.

Introduction

In previous articles I have discussed the creation of a nodejs websockets service within Bluemix and how we are able to send messages to specific web pages using the socket.io rooms capability. Both of those examples were proofs of concept and the messages were generated in the browser via firebug console commands. We are going to look at how we can automate these messages and begin to build a user case for using websockets within our applications.

Disclaimer: This idea for an example was the brainchild of David Leedy and in many ways it is a genius example to relate websockets to XPages functionality. And at the same time, I am absolutely disgusted that I am even talking about this because I would never dream of actually implementing this within an application. The fact that the page changes without the user’s knowledge is poor, and the fact that it refreshes the entire control when only a small piece of data changes is horrible. All that said however, this is still a demonstration of the capability and in future blog posts on the subject I will actually show example which I would be proud to actually put into one of my own applications ;)

Keeping data up to data on an XPage

Let’s say we have a sample application with a simple XPages viewPanel on it

b1

Somewhere within the application – someone else makes a change to the data

b2

The only way to see the change would be to refresh the page – and you the user would never know when.

b3

This can be pseudo-automated from a user experience perspective in a number of ways but they all involve periodic checking for updates on way or another. If you scale that over many users this is extremely inefficient.

That is where websockets comes in very nicely.

Pushing to specific rooms

In the previous article I demonstrated how to record an XPage as a “room” dynamically and in this example we will do the same thing.

  var temp = (location.href.indexOf('copper.xomino.com')>0) ? "http://localhost:3000" : 'http://xominosocket.mybluemix.net'
  var socket = io.connect(temp)

  // Send message to server that user has joined
  nickname=$('.username').text()
  var xpageName = location.href.split('.nsf/')[1]
  xpageName = xpageName.split('.xsp')[0]
  socket.emit('joinRoom', xpageName, nickname);

Automating a partialRefresh

In a similar manner to listening for a new chat message and then acting upon it, we are going to listen for a “refresh” socket event and then action it. In this case we are also going to pass in the id of the XSP control we want to refresh. For the sake of this example I am also using some CSS to make the element appear momentarily grey (see the video and all will be clear)

  // Function to add a message to the page
  var refreshControl = function(data) {
	  //Get the refreshId from the incoming data and color the control grey
	  //then get the id of the element via the is attribute
	  var temp = $('[id*='+data.refreshId+']').css({background: '#CCCCCC', color: 'white'}).attr('id')
	  //With the known id - trigger a XPages partial refresh of the control
	  XSP.partialRefreshGet(temp, {})
  };

  // When a refresh message is received from the server
  // action it by calling the refreshControl function
  socket.on('refresh', function(data) { refreshControl(data); });

Creating a new listener on the node.js server

I created a new route to post my refresh data to “xpagesRefresh”. When data is POSTed at xpagesRefresh it is parsed and send back out via websockets using the “refresh” socket event.

// Handle the form POST containing the name and , reply with the language
app.post('/xpagesRefresh', cors(corsOptions), function(req, res){
  var request_data = {};

  if (req.body){
    request_data = {
      'refreshId': req.body.refreshId,
      'nickname': req.body.nickname,
      'rt': 'text'
    };
  }

  var data = { refreshId: request_data.refreshId, nickname: request_data.nickname};
  console.log("POSTing at xpagesRrefresh")
  console.log(req.body)

  io.sockets.emit("refresh", data);
  res.send(data);
});

Automating the partial refresh via the user action

In a real application we are not going to have someone sitting on a browser pushing updates via firebug. We want to be able to create the update when the XPage is saved in the first place. To do this we transfer the code we saw in previous firebug blog example into the onComplete of a Save button. In this way when a document is updated within the application. A notification is sent out to all the people looking at the page, updating the data for them.

 

<xp:button value="Save" id="button1" rendered="#{javascript:document1.isEditable()}">
	<xp:eventHandler event="onclick" submit="true" refreshMode="partial"
		save="true" refreshId="blank">
		<xp:this.onComplete>
		<![CDATA[
			var socketServerURL = (location.href.indexOf('copper.xomino.com')>0) ? "http://copper.xomino.com:3000" : 'http://xominosocket.mybluemix.net'

			var data = {
			  refreshId: 'wrapper',
			  nickname: 'automated'
			   };

			  console.log(data)
			  $.ajax({ url:
			          socketServerURL+"/xpagesRefresh",
			      type: "POST",
			      data: data
			  }).done(function( msg ) {
			      console.log( msg);
			  });
			]]>
			</xp:this.onComplete>
	</xp:eventHandler>
	</xp:button>

Demonstration

The video below shows how we are able to trigger a partial refresh after updating a document within the application. Note the screen flickers grey as the CSS change happens before the partial refresh. It is so quick it is almost instant.

Pushing to Bluemix

As before, pushing my new code to Bluemix is as simple as checking it in to the jazz hub repository and redeploying. In the picture below we can see that we are using marky.psclistens.com as the application domain and not copper.xomino.com. As we showed before, if not copper then use Bluemix.

b6

 

We create the capability locally, tested it, proved it and deployed it seamlessly to Bluemix with a “Commit and Push” – and that is *so* cool :)

Conclusion
In this article we saw how to trigger core XPages functionality automatically without the user having to interact with the application. In the next article we will look at how to improve on this, frankly horrible, user experience.

Thanks Dave :)

Posted in Bluemix, node.js, socket.io, WebSockets, WebSockets in XPages | 3 Comments »

XPages and Bluemix: Sending a targeted Websockets message to specific XPages

Posted by MarkyRoden on November 30, 2014

In this article I will demonstrate how the use of socket.io “rooms” enables us to send message to users who are only accessing specific pages within our application, rather than blanket messages to all users.

Introduction

In the previous article I demonstrated how to use a message POST to the node.js server which could then be turned into a chat message and sent out to all users. While this is a nice example it only serves as such and does not have significant business value. In this article I will begin the peel back the potential for much greater application flexibility through the controlled use of targeted Websockets messages to users of an application.

Most applications have more than one “page” within it and we may wish to send a message to users of one page rather than all pages. Conversely we may want to only send messages to users who are viewing certain types of information wherever they are within the application.

In this article we are still going to use the chat example but this will be the last time we use “chat” as the use case. In future articles I will look into more practical applications of Websockets messaging within an application.

Using rooms within socket.io

Looking at the socket.io documentation for rooms and namespaces you can see that the API exposes the ability to create individual communication channels between the server and the application users.

How this translates to our application on the node.js server looks like this:

  socket.on('joinRoom', function(room, name){
    socket.join(room);
    io.sockets.in(room).emit('notice', name+" has joined");
    console.log(name+" has joined room "+room)
  })

When the “joinRoom” event is registered on the server then the socket is joined to the room name which is passed in. A message is the broadcast specifically out to all the existing room members that the new user has joined. Note that this message is room specific because of the io.sockets.in(room) rather than a blanket message to all users.

With this code in place on any page we can register our application page (chat room in this case) with the socket server. In my case I created a generic function to take the name of the “room” from the XPage URL. The following client side JavaScript sends the “joinRoom” request to the server.

  nickname=$('.username').text()
  // Send message to server that user has joined WinX.nsf/xRoom1.xsp?open&login
  var xpageName = location.href.split('.nsf/')[1] //xRoom1.xsp?open&login
  xpageName = xpageName.split('.xsp')[0] //xRoom1
  socket.emit('joinRoom', xpageName, nickname);

On the server we can then see the console.log as someone joins the room:

s1
We can then have multiple users in individual “rooms” which are in this case 3 separate xPages xRoom1.xsp, xRoom2.xsp, xRoom3.xsp From the original chat room I am able to sen all three rooms a blanket message because they are all “listening” for “msg” as in the previous articles

 socket.on('msg', function(data) {
    console.log('msg here')
    console.log(data)
    redisClient.lpush('messages', JSON.stringify(data));
    redisClient.ltrim('messages', 0, 99);
    socket.broadcast.emit('msg', data);        //broadcast to all users indiscriminately
  });

s2

Sending a message to a specific room

Modifying the original POST code which was shown in the previous article I was then able to create an XPage which will send a targetted message to a specific room. To do this, all I had to do was pass in an additional POST parameter of the room I wanted to send a message to.

I create a new Master XPage which had 3 fields on it – one for each room. Each of the individual fields had a “room” attribute which allows me to pick up a value to specify which room to send it to.

<div id="msgRoom1" class="msgCenter">
	<input placeholder="Send a message to Room1" room="xRoom1" autocomplete="off" autofocus="autofocus" />
	<button type="button">Send</button>
</div>
<br/><br/>
<div id="msgRoom2" class="msgCenter">
	<input placeholder="Send a message to Room2"  room="xRoom2" autocomplete="off"  />
	<button type="button">Send</button>
</div>
<br/><br/>
<div id="msgRoom3" class="msgCenter">
	<input placeholder="Send a message to Room3"  room="xRoom3" autocomplete="off" />
	<button type="button">Send</button>
</div>

s3

In the following code we bind to each of the buttons so that when the are clicked they:

  • set msgField to be the jQuery object representing the pertinent field
  • create the data object to send to the socket server
  • create the newMessage passing in data

The new message function then:

  • POSTs the data object at the “/roomPost” path on the server
  var socketServerURL = (location.href.indexOf('copper.xomino.com')>0) ? "http://copper.xomino.com:3000" : 'http://xominosocket.mybluemix.net'
  var socket = io.connect(socketServerURL)

$('.msgCenter Button').on('click', function(){
  	var msgField = $(this).prev('INPUT')
	var data = { text: msgField.val(), nickname: nickname, when: new Date(), room: msgField.attr("room") };
	sendMessageToRoom(data)
	newMessage(data);
	// Clear the message field
	msgField.val('');
})

var sendMessageToRoom = function(data){
	console.log(data)
	$.ajax({ url:
	        socketServerURL+"/roomPost",
		type: "POST",
		data: data
	}).done(function( msg ) {
		console.log( msg);
	});
}

We can see the message come through on the server

s4

You can also see from the log that I was able to join 3 rooms from the Message Center page – this is as simple as creating three requests to join:

  //client side JavaScript
  socket.emit('joinRoom', 'xRoom1', nickname);
  socket.emit('joinRoom', 'xRoom2', nickname);
  socket.emit('joinRoom', 'xRoom3', nickname);

Site in action
The best way to see all this is to see it in action – as you can see from the video below.

Moving the application to Bluemix

Working locally I used to following code to determine if I was on copper.xomino.com or another server (demo.xomino.com or different again)

  var socketServerURL = (location.href.indexOf('copper.xomino.com')>0) ? "http://copper.xomino.com:3000" : 'http://xominosocket.mybluemix.net'
  var socket = io.connect(socketServerURL)

I had to make a slight change to my cors code in the local node server setup. I looked at the cors npm site to see how to dynamically add cors support and found the answer and modified my code accordingly. So you need to make sure you

//Marky adding CORS from copper
//app.use(cors()); //not used for whitelists

var whitelist = ['http://copper.xomino.com', 'http://demo.xomino.com', 'http://marky.psclistens.com'];
var corsOptions = {
  origin: function(origin, callback){
    var originIsWhitelisted = whitelist.indexOf(origin) !== -1;
    callback(null, originIsWhitelisted);
  }
};

marky.psclistens.com is the same local server as copper.xomino.com (I use a hosts file to make them both look at localhost). But this allows me to play with cors and in this case talk to the local or bluemix node server without needing another “Domino” server.

s6

Because the site running locally is already connected to the Jazz Hub Git repository, as with the previous examples all I have to do is commit the changes locally, push to the Jazz Hub repository, the application will then be re-built and re-deployed to Bluemix.

It’s really about as simple as that. Because the code is already primed to check to see if we are looking locally or at Bluemix, a new URL for the application now looks at Bluemix.

s5

 

So why do we need Bluemix again?

While the development was performed locally, the intention is to be able to create a capability which does not require the user to have a locally running node.js server. That is where Bluemix comes in. In essence what we are creating is a cloud hosted Websockets service which can be integrated into existing applications.

 

Conclusion

In this article we have seen that with a little creativity we are able to register different chat rooms within the same application. There are other ways to do this of course but the point of this example was to demonstrate the ability to send a specific message to specific users looking at an individual XPage.

In the next article we will take a look at the practical implications of this within an XPages application.

 

Posted in Bluemix, node.js, socket.io, WebSockets, Webstorm, XPages | Tagged: , , , , | 1 Comment »

Multiple Chrome Incognito browsers share the same data

Posted by MarkyRoden on November 23, 2014

In a previous post I talked about how going porn-mode on your browser is great for a developer. What I didn’t realize until today is that incognito mode is not as unique as I want it to be.

We use localStorage in one of the applications we are developing and I had issues when I was opening up multiple Chrome Incognito mode browsers, assuming they were unique….I wanted to compare separate instances in separate windows

Mr. Genius (Toby) pointed out to me that localStorage is shared amongst Incognito windows – and that was causing things to screw up for me.

This is simple to demonstrate – open up an incognito window

a1

Then go to a site (http://demo.xomino.com) in my case

Open up developer, go to the console and create a localStorage item (.marky in this case)

a2

Then open a new incognito window, go to the same site and check out the Resources, localStorage. As you can see from the image below – the second incognito window has the localStorage values that were created in the first one.

It also appears that cookies are shared between then as well – they are not at all unique.

a4

Good to know !! Bad for my testing

 

PS

I was dared to call this post “multiple porn windows…sharing porn.”…..I resisted ;)

 

 

Posted in Chrome Dev Tools | 4 Comments »

x$ – now a part of XPages Extension Library

Posted by MarkyRoden on November 18, 2014

I am very flattered to find out that not only is my x$ OpenNTF xSnippet being used more widely than I realized (over 600 downloads). It now being used in the latest release of the OpenNTF Extension library.

If you look here – http://bootstrap4xpages.com/xsp/.ibmxspres/.extlib/responsive/xpages/js/xsp-mixin.js and search for it you will find


//jQuery selector that works with XPages IDs
//See - http://openntf.org/XSnippets.nsf/snippet.xsp?id=x-jquery-selector-for-xpages
function x$(idTag, param){
	idTag = idTag.replace(/:/gi, "\\:") + (param ? param : "");
	return($("#" + idTag));
}

Who knew my first foray into the XPages community would have such an impact.

The lesson here boys and girls should be that you should *share* your work however small and insignificant you think it is. Like all scientific research, very little code is “a completely new way of doing things”. Generally everything grows incrementally and just because you don’t think something is significant, someone else might.

You are reading this – what have you shared recently?

:)

 

Posted in Extension Library, jQuery, x$, XPages | Tagged: , , , | 4 Comments »

Got non-XPages design elements? You really should use WebContent.

Posted by MarkyRoden on November 17, 2014

Recently I was able to help explain an issue Russ Maher was having with his application png files – http://xpagetips.blogspot.com/2014/11/got-png-you-may-get-problems.html. It got me thinking that as modern web developers (which is what XPage developers need to be), we should not be using Domino database elements for “web elements”.

Back before R8 we all used the Database Files, Style sheets and Database Images as a way to reference files as part of the database. I now believe we need to stop using these altogether for “web development”.

w1

WebContent is better

A modern (non-XPages) web based application typically looks like this

w2

As you can see from the image above within a well structured web application css, images and js are all neatly separated out into separate folders. This makes it easy to drag and drop them from web server to web server because all the links are relative and easy to find.

Within our WebContent folder (Accessible within the package manager Window – Open Perspective – XPages) we are able to drag and drop a web project,  jQuery plugin, angular.js directive, extjs and many items and have them continue to function without any issue.

Bootstrap is another great example, well structured and easy to add to our applications.

w3

Source control

When we build out our applications and use source control the “database structure” is stored locally and then committed to our Git or Mercurial repository. Not using the WebContent folder causes us problems when we are searching for files in this environment. Having all our files as it they were in our database makes our lives harder and certainly harder for non-XPages developer to find our code. Some is in “Code” and the rest is in “Resources”, that doesn’t make sense.

w4

 

Conclusion

We as XPages developers need to stop using the “database” for files etc and start to use the WebContent like proper web developers.

 

PS

Yes – I know we all have old applications which get modernized and we cannot always do anything about it, but at the same time for new development moving forward this is where I am at.

 

 

 

Posted in Just Marky, XPages | 18 Comments »