-1

I have an object that I want to serialize using Protocol Buffers and store in redis. The object contains a java.util.regex.Pattern that is complied when the object is instantiated.

public class SerializableEntity {
    private Pattern pattern;
    private List<String> options;
}

This pattern is used to validate inputs to a certain api. Since compiling the pattern each time is expensive, I'm compiling the pattern once during instantiation and then reusing the same pattern instance each time the api is invoked. How do I serialize this compile Pattern field in the following schema so I when I de-serialize the object, I can use it without compiling the pattern again?

 message SerializableEntityProto {
     repeated string option = 1;
     // compiled pattern
 }

Thanks.

user207421
  • 289,834
  • 37
  • 266
  • 440
Termin4t0r
  • 169
  • 1
  • 7
  • 1
    Store [`pattern.pattern()`](https://docs.oracle.com/javase/8/docs/api/java/util/regex/Pattern.html#pattern--)? (and `pattern.flags()`, if you might compile it with non-default flags). – Andy Turner Feb 12 '19 at 12:33
  • @AndyTurner so this has to be compiled each time I retrieve it from redis? – Termin4t0r Feb 12 '19 at 12:42
  • You probably want some lazy initialization for the pattern. Read it only once from redis on first access, compile the pattern string and use the compiled pattern. Check [lazy initialization on demand holder idom](https://en.wikipedia.org/wiki/Initialization-on-demand_holder_idiom) – dpr Feb 12 '19 at 12:45
  • @dpr I'm reading it from redis each time the api is invoked and i need to perform some regex operation. it's not possible to store this locally. – Termin4t0r Feb 12 '19 at 12:48
  • Actually `Pattern` implements `Serializable`, that is you could rely on Java's (de)serialization. See https://stackoverflow.com/questions/2836646/java-serializable-object-to-byte-array Maybe convert it to base64 and store the string in redis. But I don't see why you would want to use protobufs for this. – dpr Feb 12 '19 at 13:27
  • Have you considered a static `Pattern`? Serialization looks like massive overkill for this problem. – user207421 Feb 23 '19 at 19:55

2 Answers2

1

java.util.regex.Pattern does not have encode and decode proto functions implemented in itself. However, you can implement that yourself pretty easy (as Andy Turner suggests). Something like this:

Proto

syntax = "proto2";

package termin4t0r;
option java_package = "com.example.termin4t0r";

// Proto for java.util.regex.Pattern
message RegexPatternProto {
  // See Pattern.pattern()
  optional string pattern = 1;
  // See Pattern.flags()
  optional int64 flags = 2;
}

Java encode and decode functions

class RegexpPatternProtos {
  public static RegexPatternProto encode(java.util.regex.Pattern pattern) {
    return RegexPatternProto.newBuilder()
        .setPattern(pattern.pattern())
        .setFlags(pattern.flags())
        .build();
  }

  public static java.util.regex.Pattern decode(RegexPatternProto patternProto) {
    return new RegexPatternProto(
      patternProto.getPattern(), patternProto.getFlags());
  }
}

I leave the unittests as an exercise :) I even find serializing this way preferable as protocol buffers have forward and backward compatibility, whereas java serialization has problems with that.

Christian
  • 2,071
  • 14
  • 10
0

I think this is a case of square peg and round hole, protobuf and serialization is not meant to be used that way.

Anyway it seems like you initialize a regex with every API call. I don't know how your app decides which Regex to use for a particular API, but you must start out with a Regex string to compile. Instead of trying to serializing the pattern, store it in memory in a HashMap<String,Pattern>( Regex string as a key and the compiled pattern as value). And then get the pattern when you need it.

lifesoordinary
  • 103
  • 1
  • 8