0

When migrating websites often dead URLs happen since old website used different URL structure or technology. Correct 301 "permanent" redirect is important for SEO friendly migrations.

Example:

Old page https://example.com/product/coca-cola-bottle.html moved in our JSF project to https://example.com/p/coca-cola-1-l/1000

Concept

We will save those mappings in our database and add them to our JSF application.

If an URL is requested that is not valid or rewritten we want to check the current requested URL if it exists in our database and redirect to the new target.

Some Ideas?

  • Create a custom exception handler and redirect if resource was not found
  • Override navigation handler to handle it before exception handler
  • Use @WebFilter with DispatcherType.ERROR and 404 error code check
  • Use OCPSoft rewrite solution. Not sure how to do this without loading all mappings into configuration. I prefer dynamic (lazy) approach.

Right now i implemented @WebFilter version using an injected bean to lookup the mapping.

djmj
  • 5,579
  • 5
  • 54
  • 92
  • 1
    To be honest, I guess build a custom web filter for this is the best approach. And it should be fairly easy to do. Not sure if you really should try to detect 404 errors though. Why not matching the incoming request again the rewrite rules you have in your DB and then redirect the user accordingly. – chkal Nov 25 '21 at 08:48
  • 1
    You could also inject the bean into your rewrite config and look it up dynamically in the rewrite ConfigurationProvider as well. You would probably need to add the "rewrite-integration-cdi" module to support @Inject on your configuration provider. – Lincoln Nov 25 '21 at 19:41

1 Answers1

1

I would start by including the rewrite-integration-cdi module:

https://github.com/ocpsoft/rewrite/blob/master/documentation/src/main/asciidoc/integration/cdi.asciidoc

Then create a CDI bean/Java class that can access your database.

Inject an instance of that class into your Rewrite ConfigurationProvider, then use it to build / create your Rewrite rules.

Here is an example of both @Injecting beans into your ConfigurationProvider, and also defining custom HTTP operations:

https://github.com/ocpsoft/rewrite/blob/master/showcase/rest-ws/src/main/java/org/ocpsoft/rewrite/showcase/rest/RestRewriteConfiguration.java

Depending on how dynamic you want your database lookups to be, you could either preload them at startup time (when the Config is built), or load & cache them inside the Request/Response lifecycle itself using a custom HttpCondition and `HttpOperation:

https://github.com/ocpsoft/rewrite/blob/master/api-servlet/src/main/java/org/ocpsoft/rewrite/servlet/config/HttpCondition.java

https://github.com/ocpsoft/rewrite/blob/master/api-servlet/src/main/java/org/ocpsoft/rewrite/servlet/config/HttpOperation.java

Then use those operations in your ConfigurationProvider to perform the database operations. Essentially you will do something like this, but check the database to see if the requested URL is a ‘known/stored’ redirect:

https://github.com/ocpsoft/rewrite/blob/851ccbabb8b6248c66589076fa67cb0ec07b3132/impl-servlet-tests/src/test/java/org/ocpsoft/rewrite/servlet/config/HttpRequestParameterTestProvider.java#L45

And then use an custom HttpOperation to perform the actions you want to take.

https://github.com/ocpsoft/rewrite/blob/851ccbabb8b6248c66589076fa67cb0ec07b3132/config-servlet/src/test/java/org/ocpsoft/rewrite/servlet/config/JoinBindingConfigurationProvider.java#L48

You could also technically just use a Condition that matches all requests, and an HttpOperation That only takes action if there is a database entry.

All that said, this sounds more complicated than it is, but there’s no good example I can find to link to that does exactly what you want, so I’m trying to piece it together.

Lincoln
  • 3,151
  • 17
  • 22
  • Thanks for your detailed reply and condition and operation look interesting. Since not all incoming URLs are known, which i did not thought about before asking it will lead to `Condition that matches all requests` where i also think a `@WebFilter` as @chkal mentioned is the better solution right now. – djmj Nov 28 '21 at 22:19
  • 1
    Fair enough! You can always just use an `Operation` without a `Condition` and it will match everything :) But I tend to agree a simple filter might be the easiest option with least overhead and "magic". – Lincoln Nov 30 '21 at 17:15