14

I'm trying to use a custom SocketImpl with SSL in Java. Because of that I need to set ServerSocket's socket factory. I now noticed that it's static, which creates some hassle for me as a I want to supply it with some paramaters that differs between in each ServerSocket-instance. Does anyone know the rationale behind making it static? To me it feels like an unnecessary constraint that only introduces more global state in your app.

Update There seems to be some confusion on why this is a hassle. The problem this creates is that it forces me to use the same factory across the entire application. What if I want to use the default SocketImpl in one place and a custom one in another? That can't be done without resorting to some ugly reflection-hacks, because the factory can't be changed once it has been set. I also can't make my factory create default implementation because SocksSocketImpl is package private.

Yrlec
  • 3,401
  • 6
  • 39
  • 75
  • 2
    Is "why is it static" really the question you want answered? Isn't a more practical question "how can I solve this problem"? – Greg Kopff Aug 22 '12 at 11:15
  • why can't you assign those parameters to some variables inside your SocketImplFactory class ? why do you need to override a static function, however impossible that might be ? – Sreenath S Aug 22 '12 at 11:20
  • Where do I say that want to override a static function? – Yrlec Aug 22 '12 at 11:40
  • Why do think you need to do this? What problem are you trying to solve? – user207421 Aug 22 '12 at 11:43
  • I'm trying to use SSL together with a library called ice4. Ice4j has a functionality called PseudoTCP, which implements Socket and SocketImpl over UDP. However, it doesn't implement ServerSocket, so I need to create that myself. In addition to that there are other parts of the application that use normal TCP and therefore need to use ServerSocket with the default SocketImpl implementation. – Yrlec Aug 22 '12 at 11:49
  • That's what I've done. How do you expect one to call ServerSocket.setSocketFactory without implementing SocketImplFactory? – Yrlec Aug 22 '12 at 12:29
  • ice4j's implementation of PseudoTcp uses UDP DatagramSocket underneath, like you mentioned. And you want to layer SSL over that ? Is that what you are trying to do ? – Sreenath S Aug 23 '12 at 06:55
  • Yes. Note that it also implements Socket. The fact that it uses UDP DatagramSocket is irrelevant. It could use pigeons to the send the messages, as long as it implements Socket. – Yrlec Aug 23 '12 at 08:26
  • OK, so the underlying transfer protocol used by PseudoTcp is still UDP, right ? – Sreenath S Aug 23 '12 at 09:09
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/15706/discussion-between-sreenath-soman-and-yrlec) – Sreenath S Aug 23 '12 at 09:12

6 Answers6

4

SocketImpl is an abstract class that provides an interface for customizing socket implementations. Subclasses of SocketImpl are not intended to be explicitly instantiated. Instead, they are created by a SocketImplFactory. The motivation for this design is to allow you to change the default type of socket used by an entire application by calling Socket.setSocketImplFactory(), making it unnecessary to rewrite all of your networking code. Custom sockets are necessary for features such as SSL and firewall tunneling. Unfortunately, the global nature of setSocketImplFactory() is rather limiting, as it doesn't allow you to use multiple types of sockets within a single application. You can get around this by subclassing Socket and using the protected Socket(SocketImpl) constructor that was introduced in JDK 1.1.

Reference:http://www.devx.com/tips/Tip/26363

Sreenath S
  • 1,269
  • 1
  • 14
  • 21
  • 2
    If you look in the source code of ServerSocket you can see that this isn't enough. If you look in implAccept(Socket s) you can see that it gets its SocketImpl instance by calling getImpl() -> createImpl() -> setImpl(). In setImpl() it uses the static factory field if it's !=null, otherwise it calls new SocksSocketImpl(). In other words: if you want a custom SocketImpl you have to set the factory. Otherwise you can't call implAccept(). – Yrlec Aug 22 '12 at 11:38
  • 1
    I should also add that the constructor ServerSocket(SocketImpl impl) is package private, so I can't use that. – Yrlec Aug 22 '12 at 11:44
2

It's pretty disgusting, but you could create a DelegatingSocketFactory that looks back up the call stack at who called it, and either creates a SocksSocketImpl (using reflection to sort out the accessibility), or uses the Ice4J one. This counts as a reflection hack!

artbristol
  • 32,010
  • 5
  • 70
  • 103
1

Look at the Constructor of ServerSocket

If the application has specified a server socket factory, that factory's createSocketImpl method is called to create the actual socket implementation. Otherwise a "plain" socket is created.

So it has to be static, because there's the need that the Factory has to be set if you wish that it get used when you're creating a new instance of a socket.

Marvin Emil Brach
  • 3,984
  • 1
  • 32
  • 62
  • That just leads to the follow up question, why is createSocketImpl called in the constructor? There's a constructor that allows you to specify the SocketImpl instance manually (ServerSocket(SocketImpl impl)) but that is package private. – Yrlec Aug 22 '12 at 11:35
  • @Yrlec FWIW, at some point that finally changed so now the `ServerSocket(SocketImpl)` constructor is `protected` - so we can now get at it by subclassing. – Hakanai Nov 28 '22 at 23:01
0

To mee it seems that having this setter static makes it easier to use, because there is no need to have instance of ServerSocket and it lets you set Socket factory without having reference to it. I think making this setter global makes it actualy easier to implement, why is it hassle for you?

Eduard
  • 3,176
  • 3
  • 21
  • 31
  • In real applications, you eventually have more than one piece of code which uses sockets, and setting the factory statically for one socket breaks some unrelated code elsewhere which relies on the default behaviour. i.e., the same reason that _any_ static mutable state is bad. – Hakanai Nov 28 '22 at 22:57
-1

Would you expect a non-static factory to know how to magically instantiate your custom class?

Yrlec
  • 3,401
  • 6
  • 39
  • 75
deleted_user
  • 3,817
  • 1
  • 18
  • 27
  • I expect to be able to supply it my own non static factory. Why does the factory-instance have to be stored in a static field? – Yrlec Aug 28 '12 at 12:04
-1

This seems to me like a classic case of Factory Pattern, in which you provide a custom factory object with settings that dictate how instance of a certain class are created. It makes perfect sense to have methods manipulating factories to be static, since the factory acts as a "meta-object", directing the creation of other objects.

Having a factory of each instance simply would not make sense from a design point of view. What would be the point of having a different factory per instance? Do you plan to create instances of ServerSocket from other instances? If you want different settings you'll just have to supply a different factory every time.

Tudor
  • 61,523
  • 12
  • 102
  • 142
  • My application needs different ServerSockets for different parts of the app. One part needs normal TCP-socket and one part needs PseudoTCP-sockets from Ice4j. What makes this even stranger is that I can't change the factory once it has been set. setFactory throws an exception for evey subsequent calls to it. – Yrlec Aug 29 '12 at 08:27
  • 1
    @Yrlec: What you need then is a decorator pattern, which allows customization of individual instances. But factories are always static by definition. – Tudor Aug 29 '12 at 09:40
  • Well, I am not one who has decided the pattern of ServerSocket. I just think it's a very odd limitation. – Yrlec Aug 29 '12 at 10:28
  • @Yrlec: Of course, but your question was "Why is `setSocketFactory` static?", so my answer is: because it's a factory. :D – Tudor Aug 29 '12 at 10:31
  • I don't necessarily agree with you on that. For instance with when you use dependency injection you often have non-static factories that you inject into classes to enable them to create new instances on the fly. Like this: http://google-guice.googlecode.com/git/javadoc/com/google/inject/assistedinject/FactoryProvider.html – Yrlec Aug 29 '12 at 10:35
  • @Yrlec: Yes, that could be an example, but when they created the java socket API they were probably not thinking about injection, as it would have added unnecessary complexity. – Tudor Aug 29 '12 at 10:42