Immutable objects do not have identity and are values. And the distinction between primitives and objects in Java, for our discussion here, is irrelevant.
That the language does not enforce purity in any way (besides `final` members and values) that's irrelevant. A lot of things in programming happen by convention.
That Haskell can force purity via its laziness, that's a nice feature of the language, but not required for doing FP, just like how static types aren't required for doing FP either — Haskell devs would like to promote the notion that Haskell and derivatives are the only true languages for FP, but they've been preceded by LISP and ML.
A lot of things in programming happen by convention. That's not a good argument, or an argument that can be used efficiently for language advocacy. OOP isn't supported explicitly by C either, yet people have built an entire GUI/window manager, along with apps, on top of GObject, which in many ways is more OOP than C++ ;-)